MPEG4Extractor.cpp revision 442cc6dc48f8188e097617f7f804c314a9dacd0e
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>
3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h>
3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
3618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h>
3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h>
3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h>
3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h>
4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé#include <byteswap.h>
42328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé#include "include/ID3.h"
43fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource {
4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic:
4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    // Caller retains ownership of both "dataSource" and "sampleTable".
49693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    MPEG4Source(const sp<MetaData> &format,
50693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber                const sp<DataSource> &dataSource,
5148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                int32_t timeScale,
5205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const sp<SampleTable> &sampleTable,
5305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                Vector<SidxEntry> &sidx,
5405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                off64_t firstMoofOffset);
5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t start(MetaData *params = NULL);
5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual status_t stop();
5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
5920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    virtual sp<MetaData> getFormat();
6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
6205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
64693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected:
65693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    virtual ~MPEG4Source();
66693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate:
687b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex mLock;
697b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    sp<MetaData> mFormat;
71693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<DataSource> mDataSource;
7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t mTimescale;
73693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    sp<SampleTable> mSampleTable;
7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t mCurrentSampleIndex;
7505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentFragmentIndex;
7605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<SidxEntry> &mSegments;
7705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mFirstMoofOffset;
7805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mCurrentMoofOffset;
7905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t mNextMoofOffset;
8005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t mCurrentTime;
8105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mLastParsedTrackId;
8205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int32_t mTrackId;
8320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
84ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mCryptoMode;    // passed in from extractor
85ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int32_t mDefaultIVSize; // passed in from extractor
86ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t mCryptoKey[16]; // passed in from extractor
87ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoType;
88ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentAuxInfoTypeParameter;
8948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    int32_t mCurrentDefaultSampleInfoSize;
90ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoCount;
91ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoAllocSize;
92ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t* mCurrentSampleInfoSizes;
93ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetCount;
94ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t mCurrentSampleInfoOffsetsAllocSize;
95ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint64_t* mCurrentSampleInfoOffsets;
96ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mIsAVC;
986064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t mNALLengthSize;
996064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool mStarted;
10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBufferGroup *mGroup;
10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MediaBuffer *mBuffer;
10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
106dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool mWantsNALFragments;
10720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1080024245e134467d120b40099da16c467dc365e76Andreas Huber    uint8_t *mSrcBuffer;
1090024245e134467d120b40099da16c467dc365e76Andreas Huber
1106064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    size_t parseNALSize(const uint8_t *data) const;
11105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseChunk(off64_t *offset);
11205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
11305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    status_t parseTrackFragmentRun(off64_t offset, off64_t size);
114ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
115ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
11605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
11705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct TrackFragmentHeaderInfo {
11805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        enum Flags {
11905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kBaseDataOffsetPresent         = 0x01,
12005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kSampleDescriptionIndexPresent = 0x02,
12105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleDurationPresent  = 0x08,
12205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleSizePresent      = 0x10,
12305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDefaultSampleFlagsPresent     = 0x20,
12405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            kDurationIsEmpty               = 0x10000,
12505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        };
12605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
12705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mTrackID;
12805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mFlags;
12905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mBaseDataOffset;
13005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mSampleDescriptionIndex;
13105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleDuration;
13205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleSize;
13305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t mDefaultSampleFlags;
13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint64_t mDataOffset;
13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
13705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    TrackFragmentHeaderInfo mTrackFragmentHeaderInfo;
13805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    struct Sample {
14005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset;
14105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t size;
14205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t duration;
143ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint8_t iv[16];
144ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> clearsizes;
145ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Vector<size_t> encryptedsizes;
14605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
14705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Vector<Sample> mCurrentSamples;
1486064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source(const MPEG4Source &);
15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MPEG4Source &operator=(const MPEG4Source &);
15120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber};
15220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
15350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests
15450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding
15550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource.
15650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track,
15750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e.
15850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track.
15950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource {
16150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const sp<DataSource> &source);
16250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
16350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual status_t initCheck() const;
164c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
165c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    virtual status_t getSize(off64_t *size);
16650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual uint32_t flags();
16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
168c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    status_t setCachedRange(off64_t offset, size_t size);
16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected:
17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    virtual ~MPEG4DataSource();
17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate:
17450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex mLock;
17550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    sp<DataSource> mSource;
177c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t mCachedOffset;
17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    size_t mCachedSize;
17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    uint8_t *mCache;
18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    void clearCache();
18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource(const MPEG4DataSource &);
18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    MPEG4DataSource &operator=(const MPEG4DataSource &);
18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber};
18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    : mSource(source),
18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedOffset(0),
19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCachedSize(0),
19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber      mCache(NULL) {
19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() {
19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() {
19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache) {
20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        free(mCache);
20150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        mCache = NULL;
20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = 0;
20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = 0;
20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const {
20950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->initCheck();
21050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
212c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
21350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
21450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
21550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (offset >= mCachedOffset
21650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            && offset + size <= mCachedOffset + mCachedSize) {
21750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        memcpy(data, &mCache[offset - mCachedOffset], size);
21850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return size;
21950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
22050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
22150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->readAt(offset, data, size);
22250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
224c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::getSize(off64_t *size) {
22550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->getSize(size);
22650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
22750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
22850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() {
22950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return mSource->flags();
23050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
23150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
232c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
23350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    Mutex::Autolock autoLock(mLock);
23450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    clearCache();
23650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCache = (uint8_t *)malloc(size);
23850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
23950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (mCache == NULL) {
24050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return -ENOMEM;
24150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
24250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedOffset = offset;
24450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    mCachedSize = size;
24550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
24750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
24850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    if (err < (ssize_t)size) {
24950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        clearCache();
25050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber        return ERROR_IO;
25250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    }
25350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber    return OK;
25550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}
25650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber////////////////////////////////////////////////////////////////////////////////
25850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) {
26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const uint8_t *data = (const uint8_t *)_data;
26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    size_t offset = 0;
26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (offset < size) {
263377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        printf("0x%04zx  ", offset);
26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        size_t n = size - offset;
26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (n > 16) {
26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            n = 16;
26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < 16; ++i) {
27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (i == 8) {
27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(" ");
27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (offset + i < size) {
27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%02x ", data[offset + i]);
27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("   ");
27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf(" ");
28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        for (size_t i = 0; i < n; ++i) {
28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (isprint(data[offset + i])) {
28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf("%c", data[offset + i]);
28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                printf(".");
28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        printf("\n");
29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        offset += 16;
29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
29818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) {
29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch (fourcc) {
30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
30118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AAC;
30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
30418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
306371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
30718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
308371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
31018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_MPEG4;
31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
313e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
314e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
31518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_H263;
31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
31818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber            return MEDIA_MIMETYPE_VIDEO_AVC;
31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
321dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            CHECK(!"should not be here.");
32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
32320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
32420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
32648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
32748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
32848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR NB audio is always mono, 8kHz
32948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
33048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 8000;
33148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
33248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
33348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // AMR WB audio is always mono, 16kHz
33448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *channels = 1;
33548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        *rate = 16000;
33648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return true;
33748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
33848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    return false;
33948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
34048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
341693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
34205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    : mSidxDuration(0),
34305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mMoofOffset(0),
34405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mDataSource(source),
345bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber      mInitCheck(NO_INIT),
3467be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber      mHasVideo(false),
347fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen      mHeaderTimescale(0),
34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mFirstTrack(NULL),
34972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber      mLastTrack(NULL),
350dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFileMetaData(new MetaData),
351dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mFirstSINF(NULL),
352dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mIsDrm(false) {
35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
35520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() {
35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        Track *next = track->next;
35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        delete track;
36120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = next;
36220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
36320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mFirstTrack = mLastTrack = NULL;
364dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
365dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
366dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf) {
367dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        SINF *next = sinf->next;
368dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf->IPMPData;
369dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete sinf;
370dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = next;
371dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
372dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    mFirstSINF = NULL;
373ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
374ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
375ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        delete [] mPssh[i].data;
376ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
37905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenuint32_t MPEG4Extractor::flags() const {
38005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return CAN_PAUSE |
38105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ((mMoofOffset == 0 || mSidxEntries.size() != 0) ?
38205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
38305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
38405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3857be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() {
3867be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    status_t err;
3877be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    if ((err = readMetaData()) != OK) {
38872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return new MetaData;
3897be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber    }
3907be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
39172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return mFileMetaData;
3927be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber}
3937be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
394693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() {
39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
397ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("MPEG4Extractor::countTracks: no tracks");
398693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return 0;
39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
401693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    size_t n = 0;
40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (track) {
404693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        ++n;
40520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
408ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("MPEG4Extractor::countTracks: %d tracks", n);
409693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return n;
41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
4127e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData(
4137e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        size_t index, uint32_t flags) {
41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return NULL;
41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return NULL;
42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
429371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
430371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
431371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
432371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
4337e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    if ((flags & kIncludeExtensiveMetaData)
4347e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            && !track->includes_expensive_metadata) {
4357e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        track->includes_expensive_metadata = true;
4367e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
4377e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        const char *mime;
4387e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
4397e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        if (!strncasecmp("video/", mime, 6)) {
44005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (mMoofOffset > 0) {
44105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int64_t duration;
44205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->meta->findInt64(kKeyDuration, &duration)) {
44305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // nothing fancy, just pick a frame near 1/4th of the duration
44405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
44505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime, duration / 4);
44605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
44705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
44805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleIndex;
44905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t sampleTime;
45005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
45105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        && track->sampleTable->getMetaDataForSample(
45205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            sampleIndex, NULL /* offset */, NULL /* size */,
45305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            &sampleTime) == OK) {
45405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    track->meta->setInt64(
45505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            kKeyThumbnailTime,
45605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                            ((int64_t)sampleTime * 1000000) / track->timescale);
45705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
4587e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber            }
4597e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber        }
4607e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber    }
4617e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber
46220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return track->meta;
46320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
46420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
46548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) {
46648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[0] = x >> 24;
46748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[1] = (x >> 16) & 0xff;
46848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[2] = (x >> 8) & 0xff;
46948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[3] = x & 0xff;
47048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    s[4] = '\0';
47148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen}
47248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() {
474bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck != NO_INIT) {
475bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        return mInitCheck;
47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
47720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
478c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset = 0;
47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
48005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    while (true) {
48105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        err = parseChunk(&offset, 0);
48205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err == OK) {
48305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            continue;
48405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
48505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
48605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t hdr[2];
48705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(offset, hdr, 8) < 8) {
48805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
48905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
49005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t chunk_type = ntohl(hdr[1]);
49105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_type == FOURCC('s', 'i', 'd', 'x')) {
49205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // parse the sidx box too
49305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            continue;
49405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
49505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // store the offset of the first segment
49605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mMoofOffset = offset;
49705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
49805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        break;
49920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
5007be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
501bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    if (mInitCheck == OK) {
50272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (mHasVideo) {
503bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber            mFileMetaData->setCString(
504bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
50572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
50672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
50772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
50872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
5094678a6dc5f09008481524949a9667af5a6190374Andreas Huber        mInitCheck = OK;
510bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    } else {
511bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        mInitCheck = err;
51220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
51320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
514bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    CHECK_NE(err, (status_t)NO_INIT);
515ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
516ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // copy pssh data into file metadata
517ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int psshsize = 0;
518ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mPssh.size(); i++) {
519ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        psshsize += 20 + mPssh[i].datalen;
520ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
521ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (psshsize) {
522ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *buf = (char*)malloc(psshsize);
523ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        char *ptr = buf;
524ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        for (size_t i = 0; i < mPssh.size(); i++) {
525ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
526ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
527ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ptr += (20 + mPssh[i].datalen);
528ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
529ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
530ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        free(buf);
531ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
532bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return mInitCheck;
53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
535dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
536dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mFirstSINF == NULL) {
537dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
538dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
539dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
540dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    SINF *sinf = mFirstSINF;
541dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (sinf && (trackID != sinf->trackID)) {
542dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        sinf = sinf->next;
543dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
544dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
545dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (sinf == NULL) {
546dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return NULL;
547dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
548dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
549dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *len = sinf->len;
550dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return sinf->IPMPData;
551dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
552dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
553dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
55456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic int32_t readSize(off64_t offset,
555dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        const sp<DataSource> DataSource, uint8_t *numOfBytes) {
556dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint32_t size = 0;
557dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    uint8_t data;
558dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    bool moreData = true;
559dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *numOfBytes = 0;
560dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
561dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    while (moreData) {
562dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (DataSource->readAt(offset, &data, 1) < 1) {
563dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return -1;
564dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
565dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        offset ++;
566dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        moreData = (data >= 128) ? true : false;
567dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        size = (size << 7) | (data & 0x7f); // Take last 7 bits
568dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        (*numOfBytes) ++;
569dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
570dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
571dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return size;
572dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
573dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
57484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Extractor::parseDrmSINF(
57584333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        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];
687f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            data_offset += 2;
688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
689f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara            if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) {
690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_IO;
691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            data_offset += sinf->len;
693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size -= (dataLen + numOfBytes + 1);
695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (size != 0) {
699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return ERROR_MALFORMED;
700dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
701dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
702dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return UNKNOWN_ERROR;  // Return a dummy error.
703dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
704dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
70572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder {
70672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
70772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        : mPath(path) {
70872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->push(chunkType);
70972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
71072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
71172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    ~PathAdder() {
71272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        mPath->pop();
71372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
71472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
71572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate:
71672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    Vector<uint32_t> *mPath;
71772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
71872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder(const PathAdder &);
71972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder &operator=(const PathAdder &);
72072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber};
72172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
72272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
72372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return path.size() >= 5
72472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[0] == FOURCC('m', 'o', 'o', 'v')
72572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[1] == FOURCC('u', 'd', 't', 'a')
72672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[2] == FOURCC('m', 'e', 't', 'a')
72772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        && path[3] == FOURCC('i', 'l', 's', 't');
72872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
72972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string.
73172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
73272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
73372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    char tmp[32];
73572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
73672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
73772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    s->setTo(tmp);
73872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
73972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
740c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
7415d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("entering parseChunk %lld/%d", *offset, depth);
74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t hdr[2];
74334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return ERROR_IO;
74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint64_t chunk_size = ntohl(hdr[0]);
74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint32_t chunk_type = ntohl(hdr[1]);
748c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t data_offset = *offset + 8;
74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (chunk_size == 1) {
75134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
75220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return ERROR_IO;
75320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
75420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        chunk_size = ntoh64(chunk_size);
75520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        data_offset += 8;
75671b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber
75771b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        if (chunk_size < 16) {
75871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            // The smallest valid chunk is 16 bytes long in this case.
75971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber            return ERROR_MALFORMED;
76071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        }
76171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber    } else if (chunk_size < 8) {
76271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        // The smallest valid chunk is 8 bytes long.
76371b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber        return ERROR_MALFORMED;
76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char chunk[5];
76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    MakeFourCCString(chunk_type, chunk);
76805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth);
76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0
77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    static const char kWhitespace[] = "                                        ";
77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    char buffer[256];
776ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    size_t n = chunk_size;
777ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (n > sizeof(buffer)) {
778ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        n = sizeof(buffer);
779ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    }
780ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    if (mDataSource->readAt(*offset, buffer, n)
781ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber            < (ssize_t)n) {
782ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        return ERROR_IO;
78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
784ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
785ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber    hexdump(buffer, n);
78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif
78720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
78872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    PathAdder autoAdder(&mPath, chunk_type);
78972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
790c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t chunk_data_size = *offset + chunk_size - data_offset;
79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
79272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (chunk_type != FOURCC('c', 'p', 'r', 't')
793515e855eae78aa495da58356486aaa666cb57fd1James Dong            && chunk_type != FOURCC('c', 'o', 'v', 'r')
79472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            && mPath.size() == 5 && underMetaDataPath(mPath)) {
795c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t stop_offset = *offset + chunk_size;
79672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        *offset = data_offset;
79772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        while (*offset < stop_offset) {
79872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            status_t err = parseChunk(offset, depth + 1);
79972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (err != OK) {
80072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return err;
80172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
80272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
803bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
804bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (*offset != stop_offset) {
805bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
806bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
80772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
80872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return OK;
80972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
81072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    switch(chunk_type) {
81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'v'):
81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'k'):
81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'i', 'a'):
81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'i', 'n', 'f'):
81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('d', 'i', 'n', 'f'):
81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'b', 'l'):
81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'v', 'e', 'x'):
81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'o', 'o', 'f'):
82020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'r', 'a', 'f'):
82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'f', 'r', 'a'):
82272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('u', 'd', 't', 'a'):
82372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('i', 'l', 's', 't'):
824ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'i', 'n', 'f'):
825ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'c', 'h', 'i'):
8260a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'd', 't', 's'):
82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
82850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
8293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size);
83050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
831b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                if (mDataSource->flags()
832b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                        & (DataSource::kWantsPrefetching
833b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber                            | DataSource::kIsCachingDataSource)) {
83450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    sp<MPEG4DataSource> cachedSource =
83550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        new MPEG4DataSource(mDataSource);
83650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
83750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
83850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                        mDataSource = cachedSource;
83950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                    }
84050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber                }
8411edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber
8421edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber                mLastTrack->sampleTable = new SampleTable(mDataSource);
84350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber            }
84450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber
8456f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            bool isTrack = false;
846bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
8476f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                isTrack = true;
8486f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
849bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                Track *track = new Track;
850bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->next = NULL;
851bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (mLastTrack) {
852bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mLastTrack->next = track;
853bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                } else {
854bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    mFirstTrack = track;
855bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
856bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                mLastTrack = track;
857bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
858bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta = new MetaData;
859bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->includes_expensive_metadata = false;
8606f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                track->skipTrack = false;
861bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->timescale = 0;
862bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
863bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
864bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
865c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset;
86720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
86920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
87020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
87120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
87220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
87320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
874bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
875bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
876bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
877bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
8786f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber            if (isTrack) {
8796f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                if (mLastTrack->skipTrack) {
8806f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    Track *cur = mFirstTrack;
8816f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
8826f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    if (cur == mLastTrack) {
8836f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete cur;
8846f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mFirstTrack = mLastTrack = NULL;
8856f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    } else {
8866f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        while (cur && cur->next != mLastTrack) {
8876f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                            cur = cur->next;
8886f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        }
8896f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        cur->next = NULL;
8906f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        delete mLastTrack;
8916f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                        mLastTrack = cur;
8926f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    }
8936f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
8946f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                    return OK;
8956f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber                }
8966f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber
897bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                status_t err = verifyTrack(mLastTrack);
898bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
899bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                if (err != OK) {
900bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                    return err;
901bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                }
902bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
903bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                mInitCheck = OK;
90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
905dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (!mIsDrm) {
906dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return UNKNOWN_ERROR;  // Return a dummy error.
907dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                } else {
908dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return OK;
909dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9140a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        case FOURCC('e', 'l', 's', 't'):
9150a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        {
9160a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            // See 14496-12 8.6.6
9170a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint8_t version;
9180a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
9190a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9220a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            uint32_t entry_count;
9230a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) {
9240a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                return ERROR_IO;
9250a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9260a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9270a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            if (entry_count != 1) {
9280a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                // we only support a single entry at the moment, for gapless playback
9290a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                ALOGW("ignoring edit list with %d entries", entry_count);
930fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            } else if (mHeaderTimescale == 0) {
931210efd48ed21ca0084d9440f9a1db7d9878f8094Marco Nelissen                ALOGW("ignoring edit list because timescale is 0");
9320a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            } else {
9330a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                off64_t entriesoffset = data_offset + 8;
9340a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                uint64_t segment_duration;
9350a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t media_time;
9360a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9370a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (version == 1) {
9380a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
9390a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
9400a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9410a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9420a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else if (version == 0) {
9430a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    uint32_t sd;
9440a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int32_t mt;
9450a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
9460a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                            !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
9470a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        return ERROR_IO;
9480a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    }
9490a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    segment_duration = sd;
9500a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    media_time = mt;
9510a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                } else {
9520a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    return ERROR_IO;
9530a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
9540a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
955fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                uint64_t halfscale = mHeaderTimescale / 2;
956fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale;
957fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale;
9580a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9590a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int64_t duration;
9600a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                int32_t samplerate;
9610a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
9620a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
9630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
9650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
9660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
9670a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingus = duration - (segment_duration + media_time);
968465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    if (paddingus < 0) {
969465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // track duration from media header (which is what kKeyDuration is) might
970465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // be slightly shorter than the segment duration, which would make the
971465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        // padding negative. Clamp to zero.
972465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                        paddingus = 0;
973465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen                    }
9740a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
9750a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
9760a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen                }
9770a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            }
9780a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            *offset += chunk_size;
9790a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen            break;
9800a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen        }
9810a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen
982ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('f', 'r', 'm', 'a'):
983ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
98448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t original_fourcc;
985ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
986ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
987ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
988ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            original_fourcc = ntohl(original_fourcc);
989ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("read original format: %d", original_fourcc);
990ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
99148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = 0;
99248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t sample_rate = 0;
99348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
99448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
99548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
99648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            }
997ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
998ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
999ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1000ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1001ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('t', 'e', 'n', 'c'):
1002ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
1003ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_size < 32) {
1004ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1005ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1006ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1007ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
1008ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // default IV size, 16 bytes default KeyID
1009ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // (ISO 23001-7)
1010ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            char buf[4];
1011ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1012ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
1013ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1014ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1015ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
1016ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (defaultAlgorithmId > 1) {
1017ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only 0 (clear) and 1 (AES-128) are valid
1018ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1019ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1020ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1021ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            memset(buf, 0, 4);
1022ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
1023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1024ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1025ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
1026ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1027ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
1028ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
1029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only unencrypted data must have 0 IV size
1030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            } else if (defaultIVSize != 0 &&
1032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 8 &&
1033ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                    defaultIVSize != 16) {
1034ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // only supported sizes are 0, 8 and 16
1035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1037ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1038ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint8_t defaultKeyId[16];
1039ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1040ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
1041ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1042ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1043ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1044ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
1045ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
1046ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
1047ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
1048ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1049ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1050ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
105120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('t', 'k', 'h', 'd'):
105220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1053ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            status_t err;
1054ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
1055ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                return err;
105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
105720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
105820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
105920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
106020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('p', 's', 's', 'h'):
1063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        {
1064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            PsshInfo pssh;
1065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t psshdatalen = 0;
1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.datalen = ntohl(psshdatalen);
1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("pssh data size: %d", pssh.datalen);
1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (pssh.datalen + 20 > chunk_size) {
1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // pssh data length exceeds size of containing box
1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_MALFORMED;
1079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            pssh.data = new uint8_t[pssh.datalen];
1082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("allocated pssh @ %p", pssh.data);
1083ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ssize_t requested = (ssize_t) pssh.datalen;
1084ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
1085ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
1086ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
1087ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mPssh.push_back(pssh);
1088ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
1089ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
1090ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
1091ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
1092ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
109320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'd', 'h', 'd'):
109420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
109520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
109620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
109720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t version;
110034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
110120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, &version, sizeof(version))
110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(version)) {
110320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
110520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1106c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t timescale_offset;
110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 16;
111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else if (version == 0) {
111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                timescale_offset = data_offset + 4 + 8;
111220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
111320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
111420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
111620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t timescale;
111734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
111820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        timescale_offset, &timescale, sizeof(timescale))
111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    < (ssize_t)sizeof(timescale)) {
112020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
112220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
112320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->timescale = ntohl(timescale);
112420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
112505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t duration = 0;
112620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (version == 1) {
112734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration, sizeof(duration))
112920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration)) {
113020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
113120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
113220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                duration = ntoh64(duration);
113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            } else {
113405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                uint32_t duration32;
113534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                if (mDataSource->readAt(
113620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                            timescale_offset + 4, &duration32, sizeof(duration32))
113720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        < (ssize_t)sizeof(duration32)) {
113820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return ERROR_IO;
113920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
114005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // ffmpeg sets duration to -1, which is incorrect.
114105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (duration32 != 0xffffffff) {
114205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    duration = ntohl(duration32);
114305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
114420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
114548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mLastTrack->meta->setInt64(
114648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
114720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
11487a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            uint8_t lang[2];
11497a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            off64_t lang_offset;
11507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (version == 1) {
11517a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 8;
11527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else if (version == 0) {
11537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                lang_offset = timescale_offset + 4 + 4;
11547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else {
11557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
11567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
11577a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
11597a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    < (ssize_t)sizeof(lang)) {
11607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                return ERROR_IO;
11617a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
11627a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11637a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // To get the ISO-639-2/T three character language code
11647a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // 1 bit pad followed by 3 5-bits characters. Each character
11657a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            // is packed as the difference between its ASCII value and 0x60.
11667a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            char lang_code[4];
11677a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
11687a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
11697a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[2] = (lang[1] & 0x1f) + 0x60;
11707a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            lang_code[3] = '\0';
11717a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
11727a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            mLastTrack->meta->setCString(
11737a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                    kKeyMediaLanguage, lang_code);
11747a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'd'):
118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 8) {
118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8];
1186c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1187bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1188bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1189bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
119034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, 8) < 8) {
119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint32_t entry_count = U32_AT(&buffer[4]);
120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (entry_count > 1) {
12033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // For 3GPP timed text, there could be multiple tx3g boxes contain
12043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // multiple text display formats. These formats will be used to
12053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                // display the timed text.
1206ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // For encrypted files, there may also be more than one entry.
12073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                const char *mime;
12083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1209ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1210ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                        strcasecmp(mime, "application/octet-stream")) {
12113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    // For now we only support a single type of media per track.
12123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    mLastTrack->skipTrack = true;
12133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    *offset += chunk_size;
12143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    break;
12153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                }
121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1217c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + 8;
121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            for (uint32_t i = 0; i < entry_count; ++i) {
122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
122320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
122420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1225bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1226bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1227bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1228bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'a'):
123348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        case FOURCC('e', 'n', 'c', 'a'):
123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 'a', 'm', 'r'):
1235371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        case FOURCC('s', 'a', 'w', 'b'):
123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[8 + 20];
123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic AudioSampleEntry size.
124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
124220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
124948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint32_t num_channels = U16_AT(&buffer[16]);
125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
125181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint16_t sample_size = U16_AT(&buffer[18]);
125281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
125381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
125448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
125548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                // if the chunk type is enca, we'll get the type from the sinf/frma box later
125648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
125748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
125948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
126081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber                   chunk, num_channels, sample_size, sample_rate);
126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
126220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
126320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1264c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
126720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
126820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
126920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
127120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1272bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1273bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1274bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1275bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('m', 'p', '4', 'v'):
1280ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('e', 'n', 'c', 'v'):
128120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', '2', '6', '3'):
1282e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('H', '2', '6', '3'):
1283e071b055cee301d71335519601474c62b10af411James Dong        case FOURCC('h', '2', '6', '3'):
128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', '1'):
128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
12867be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber            mHasVideo = true;
12877be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber
128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[78];
128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Basic VideoSampleEntry size.
129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
129720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
129820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
129920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t data_ref_index = U16_AT(&buffer[6]);
130020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t width = U16_AT(&buffer[6 + 18]);
130120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint16_t height = U16_AT(&buffer[6 + 20]);
130220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1303ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // The video sample is not standard-compliant if it has invalid dimension.
1304a6256238d9015c42129fe43791968768fe501efaJames Dong            // Use some default width and height value, and
1305a6256238d9015c42129fe43791968768fe501efaJames Dong            // let the decoder figure out the actual width and height (and thus
1306a6256238d9015c42129fe43791968768fe501efaJames Dong            // be prepared for INFO_FOMRAT_CHANGED event).
1307a6256238d9015c42129fe43791968768fe501efaJames Dong            if (width == 0)  width  = 352;
1308a6256238d9015c42129fe43791968768fe501efaJames Dong            if (height == 0) height = 288;
1309a6256238d9015c42129fe43791968768fe501efaJames Dong
1310134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            // printf("*** coding='%s' width=%d height=%d\n",
1311134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber            //        chunk, width, height);
131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1313ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1314ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // if the chunk type is encv, we'll get the type from the sinf/frma box later
1315ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1316ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyWidth, width);
131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setInt32(kKeyHeight, height);
131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1320c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset = data_offset + sizeof(buffer);
132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            while (*offset < stop_offset) {
132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                status_t err = parseChunk(offset, depth + 1);
132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                if (err != OK) {
132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    return err;
132620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                }
132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
1328bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1329bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1330bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1331bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'c', 'o'):
133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('c', 'o', '6', '4'):
133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setChunkOffsetParams(
134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'c'):
135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleToChunkParams(
135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 'z'):
136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 'z', '2'):
136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSampleSizeParams(
136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        chunk_type, data_offset, chunk_data_size);
137020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
137120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1375738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber            size_t max_size;
137649110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
137749110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber
137849110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            if (err != OK) {
137949110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber                return err;
138049110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber            }
1381738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber
138205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (max_size != 0) {
138305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // Assume that a given buffer only contains at most 10 chunks,
138405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // each chunk originally prefixed with a 2 byte length will
138505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
138605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // and thus will grow by 2 bytes per chunk.
138705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
138805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            } else {
138905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                // No size was specified. Pick a conservatively large size.
139005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                int32_t width, height;
1391f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!mLastTrack->meta->findInt32(kKeyWidth, &width) ||
1392f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    !mLastTrack->meta->findInt32(kKeyHeight, &height)) {
139305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("No width or height, assuming worst case 1080p");
1394f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    width = 1920;
1395f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    height = 1080;
139605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1397f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar
13984256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                const char *mime;
13994256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1400f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1401f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // AVC requires compression ratio of at least 2, and uses
1402f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // macroblocks
1403f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
1404f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                } else {
1405f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // For all other formats there is no minimum compression
1406f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    // ratio. Use compression ratio of 1.
1407f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                    max_size = width * height * 3 / 2;
140805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
1409f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
141005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
1412113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
14134256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // NOTE: setting another piece of metadata invalidates any pointers (such as the
14144256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen            // mimetype) previously obtained, so don't cache them.
1415113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            const char *mime;
1416113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1417113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            // Calculate average frame rate.
1418113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            if (!strncasecmp("video/", mime, 6)) {
1419113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                size_t nSamples = mLastTrack->sampleTable->countSamples();
1420113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                int64_t durationUs;
1421113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1422113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    if (durationUs > 0) {
1423113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        int32_t frameRate = (nSamples * 1000000LL +
1424113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                                    (durationUs >> 1)) / durationUs;
1425113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1426113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                    }
1427113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong                }
1428113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong            }
1429113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong
143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
143120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
143220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 't', 's'):
143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
143520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setTimeToSampleParams(
143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
143820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
143920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
144420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
144620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14474931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        case FOURCC('c', 't', 't', 's'):
14484931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        {
14494931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            status_t err =
14504931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
14514931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                        data_offset, chunk_data_size);
14524931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
14534931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            if (err != OK) {
14544931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber                return err;
14554931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            }
14564931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
14574931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            *offset += chunk_size;
14584931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber            break;
14594931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber        }
14604931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber
146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('s', 't', 's', 's'):
146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
146320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            status_t err =
146420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                mLastTrack->sampleTable->setSyncSampleParams(
146520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, chunk_data_size);
146620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
146720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (err != OK) {
146820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return err;
146920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
147020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
147120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
147220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
147320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
147420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
14754948818cb91176df74c972ac27b2f392b5d148bcJames Dong        // @xyz
14764948818cb91176df74c972ac27b2f392b5d148bcJames Dong        case FOURCC('\xA9', 'x', 'y', 'z'):
14774948818cb91176df74c972ac27b2f392b5d148bcJames Dong        {
14784948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Best case the total data length inside "@xyz" box
14794948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
14804948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // where "\x00\x04" is the text string length with value = 4,
14814948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // "\0x15\xc7" is the language code = en, and "0+0" is a
14824948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // location (string) value with longitude = 0 and latitude = 0.
14834948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (chunk_data_size < 8) {
14844948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
14854948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
14864948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14874948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Worst case the location string length would be 18,
14884948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // for instance +90.0000-180.0000, without the trailing "/" and
14894948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // the string length + language code.
14904948818cb91176df74c972ac27b2f392b5d148bcJames Dong            char buffer[18];
14914948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14924948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // Substracting 5 from the data size is because the text string length +
14934948818cb91176df74c972ac27b2f392b5d148bcJames Dong            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
14944948818cb91176df74c972ac27b2f392b5d148bcJames Dong            off64_t location_length = chunk_data_size - 5;
14954948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (location_length >= (off64_t) sizeof(buffer)) {
14964948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_MALFORMED;
14974948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
14984948818cb91176df74c972ac27b2f392b5d148bcJames Dong
14994948818cb91176df74c972ac27b2f392b5d148bcJames Dong            if (mDataSource->readAt(
15004948818cb91176df74c972ac27b2f392b5d148bcJames Dong                        data_offset + 4, buffer, location_length) < location_length) {
15014948818cb91176df74c972ac27b2f392b5d148bcJames Dong                return ERROR_IO;
15024948818cb91176df74c972ac27b2f392b5d148bcJames Dong            }
15034948818cb91176df74c972ac27b2f392b5d148bcJames Dong
15044948818cb91176df74c972ac27b2f392b5d148bcJames Dong            buffer[location_length] = '\0';
15054948818cb91176df74c972ac27b2f392b5d148bcJames Dong            mFileMetaData->setCString(kKeyLocation, buffer);
15064948818cb91176df74c972ac27b2f392b5d148bcJames Dong            *offset += chunk_size;
15074948818cb91176df74c972ac27b2f392b5d148bcJames Dong            break;
15084948818cb91176df74c972ac27b2f392b5d148bcJames Dong        }
15094948818cb91176df74c972ac27b2f392b5d148bcJames Dong
151020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('e', 's', 'd', 's'):
151120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
151220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (chunk_data_size < 4) {
151320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
151420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
151520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
151620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            uint8_t buffer[256];
1517c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size > (off64_t)sizeof(buffer)) {
151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_BUFFER_TOO_SMALL;
151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
152020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            if (U32_AT(buffer) != 0) {
152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                // Should be version 0, flags 0.
152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_MALFORMED;
152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1534ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            if (mPath.size() >= 2
1535ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1536ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // Information from the ESDS must be relied on for proper
1537ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // setup of sample rate and channel count for MPEG4 Audio.
1538ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // The generic header appears to only contain generic
1539ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                // information...
1540ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1541ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1542ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                        &buffer[4], chunk_data_size - 4);
1543ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
1544ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                if (err != OK) {
1545ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                    return err;
1546ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                }
1547ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            }
1548ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
154920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
155020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
155120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
155220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
155320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        case FOURCC('a', 'v', 'c', 'C'):
155420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
1555d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
155620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
155734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber            if (mDataSource->readAt(
1558d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
155920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                return ERROR_IO;
156020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            }
156120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mLastTrack->meta->setData(
1563d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
156420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
156520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
156620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
156720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
156820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1569244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        case FOURCC('d', '2', '6', '3'):
1570244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        {
157117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            /*
157217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * d263 contains a fixed 7 bytes part:
157317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   vendor - 4 bytes
157417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   version - 1 byte
157517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   level - 1 byte
157617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   profile - 1 byte
157717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * optionally, "d263" box itself may contain a 16-byte
157817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             * bit rate box (bitr)
157917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   average bit rate - 4 bytes
158017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             *   max bit rate - 4 bytes
158117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong             */
158217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            char buffer[23];
158317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong            if (chunk_data_size != 7 &&
158417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong                chunk_data_size != 23) {
158529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("Incorrect D263 box size %lld", chunk_data_size);
1586244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_MALFORMED;
1587244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1588244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1589244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            if (mDataSource->readAt(
1590244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1591244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong                return ERROR_IO;
1592244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            }
1593244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1594244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1595244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
1596244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            *offset += chunk_size;
1597244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong            break;
1598244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong        }
1599244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong
160072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'e', 't', 'a'):
160172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
160272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            uint8_t buffer[4];
1603c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1604bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1605bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
1606bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
160772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
160872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, buffer, 4) < 4) {
160972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
161072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
161172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
161272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (U32_AT(buffer) != 0) {
161372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                // Should be version 0, flags 0.
1614ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber
1615ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // If it's not, let's assume this is one of those
1616ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // apparently malformed chunks that don't have flags
1617ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // and completely different semantics than what's
1618ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                // in the MPEG4 specs and skip it.
1619ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                *offset += chunk_size;
1620ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber                return OK;
162172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
162272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1623c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong            off64_t stop_offset = *offset + chunk_size;
162472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset = data_offset + sizeof(buffer);
162572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            while (*offset < stop_offset) {
162672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                status_t err = parseChunk(offset, depth + 1);
162772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
162872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
162972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
163072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
1631bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
1632bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            if (*offset != stop_offset) {
1633bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
1634bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            }
163572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
163672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
163772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
16385d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('m', 'e', 'a', 'n'):
16395d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('n', 'a', 'm', 'e'):
164072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('d', 'a', 't', 'a'):
164172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
164272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1643fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                status_t err = parseITunesMetaData(data_offset, chunk_data_size);
164472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
164572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                if (err != OK) {
164672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    return err;
164772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                }
164872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
164972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
165072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
165172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
165272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
165372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
165472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('m', 'v', 'h', 'd'):
165572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
1656fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            if (chunk_data_size < 24) {
165772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_MALFORMED;
165872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
165972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1660fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint8_t header[24];
166172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (mDataSource->readAt(
166272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                        data_offset, header, sizeof(header))
166372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    < (ssize_t)sizeof(header)) {
166472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                return ERROR_IO;
166572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
166672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1667fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen            uint64_t creationTime;
166872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (header[0] == 1) {
166972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U64_AT(&header[4]);
1670fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[20]);
1671bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            } else if (header[0] != 0) {
1672bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                return ERROR_MALFORMED;
167372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            } else {
167472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                creationTime = U32_AT(&header[4]);
1675fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen                mHeaderTimescale = U32_AT(&header[12]);
167672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
167772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
167872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            String8 s;
167972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            convertTimeToDate(creationTime, &s);
168072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
168172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(kKeyDate, s.string());
168272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
168372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            *offset += chunk_size;
168472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
168572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
168672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
1687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        case FOURCC('m', 'd', 'a', 't'):
1688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        {
1689ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("mdat chunk, drm: %d", mIsDrm);
1690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (!mIsDrm) {
1691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                *offset += chunk_size;
1692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                break;
1693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            if (chunk_size < 8) {
1696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                return ERROR_MALFORMED;
1697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
1698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
1699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return parseDrmSINF(offset, data_offset);
1700dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
1701dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
17023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        case FOURCC('h', 'd', 'l', 'r'):
17033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        {
17043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t buffer;
17053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (mDataSource->readAt(
17063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        data_offset + 8, &buffer, 4) < 4) {
17073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
17083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type = ntohl(buffer);
17113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // For the 3GPP file format, the handler-type within the 'hdlr' box
1712e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // shall be 'text'. We also want to support 'sbtl' handler type
1713e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            // for a practical reason as various MPEG4 containers use it.
1714e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
17153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
17163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            *offset += chunk_size;
17193b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            break;
17203b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
17213b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17227a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        case FOURCC('t', 'x', '3', 'g'):
17237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        {
17243b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
17253b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            const void *data;
17263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size_t size = 0;
17273b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mLastTrack->meta->findData(
17283b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, &type, &data, &size)) {
17293b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                size = 0;
17303b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17313b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17323b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint8_t *buffer = new uint8_t[size + chunk_size];
17333b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17343b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (size > 0) {
17353b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                memcpy(buffer, data, size);
17363b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17373b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17383b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
17393b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    < chunk_size) {
17403b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                delete[] buffer;
17413b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                buffer = NULL;
17423b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17433b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_IO;
17443b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
17453b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17463b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mLastTrack->meta->setData(
17473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                    kKeyTextFormatData, 0, buffer, size + chunk_size);
17483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
17493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            delete[] buffer;
17507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
17517a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            *offset += chunk_size;
17527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            break;
17537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
17547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1755515e855eae78aa495da58356486aaa666cb57fd1James Dong        case FOURCC('c', 'o', 'v', 'r'):
1756515e855eae78aa495da58356486aaa666cb57fd1James Dong        {
1757515e855eae78aa495da58356486aaa666cb57fd1James Dong            if (mFileMetaData != NULL) {
17583856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                ALOGV("chunk_data_size = %lld and data_offset = %lld",
1759515e855eae78aa495da58356486aaa666cb57fd1James Dong                        chunk_data_size, data_offset);
17601552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
1761515e855eae78aa495da58356486aaa666cb57fd1James Dong                if (mDataSource->readAt(
17621552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
1763515e855eae78aa495da58356486aaa666cb57fd1James Dong                    return ERROR_IO;
1764515e855eae78aa495da58356486aaa666cb57fd1James Dong                }
1765515e855eae78aa495da58356486aaa666cb57fd1James Dong                const int kSkipBytesOfDataBox = 16;
1766515e855eae78aa495da58356486aaa666cb57fd1James Dong                mFileMetaData->setData(
1767515e855eae78aa495da58356486aaa666cb57fd1James Dong                    kKeyAlbumArt, MetaData::TYPE_NONE,
17681552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
1769515e855eae78aa495da58356486aaa666cb57fd1James Dong            }
1770515e855eae78aa495da58356486aaa666cb57fd1James Dong
1771515e855eae78aa495da58356486aaa666cb57fd1James Dong            *offset += chunk_size;
1772515e855eae78aa495da58356486aaa666cb57fd1James Dong            break;
1773515e855eae78aa495da58356486aaa666cb57fd1James Dong        }
1774515e855eae78aa495da58356486aaa666cb57fd1James Dong
1775fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
1776fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
1777fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
1778fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
1779fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
1780fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
1781fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
1782fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            status_t err = parse3GPPMetaData(data_offset, chunk_data_size, depth);
1783fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
1784fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (err != OK) {
1785fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                return err;
1786fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
1787fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
1788fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            *offset += chunk_size;
1789fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
1790fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
1791fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
1792328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        case FOURCC('I', 'D', '3', '2'):
1793328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        {
1794328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (chunk_data_size < 6) {
1795328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                return ERROR_MALFORMED;
1796328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
1797328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
1798328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            parseID3v2MetaData(data_offset + 6);
1799328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
1800328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            *offset += chunk_size;
1801328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            break;
1802328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
1803328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
18045d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
18055d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
18065d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentMean.clear();
18075d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentName.clear();
18085d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            mLastCommentData.clear();
18095d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            *offset += chunk_size;
18105d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
18115d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
18125d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen
181305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('s', 'i', 'd', 'x'):
181405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        {
181505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseSegmentIndex(data_offset, chunk_data_size);
181605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
181705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return UNKNOWN_ERROR; // stop parsing after sidx
181805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
181905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
182020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        default:
182120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        {
182220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            *offset += chunk_size;
182320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            break;
182420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
182520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
182620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
182720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
182820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
182920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
183005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
183105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen  ALOGV("MPEG4Extractor::parseSegmentIndex");
183205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
183305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 12) {
183405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      return -EINVAL;
183505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
183605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
183705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
183805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
183905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
184005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
184105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t version = flags >> 24;
184305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    flags &= 0xffffff;
184405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx version %d", version);
184605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
184705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t referenceId;
184805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
184905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
185005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
185105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
185205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t timeScale;
185305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
185405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
185505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
185605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
185705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
185805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t earliestPresentationTime;
185905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t firstOffset;
186005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
186105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 12;
186205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 12;
186305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
186405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (version == 0) {
186505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
186605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
186705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
186805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t tmp;
186905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
187005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
187105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
187205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        earliestPresentationTime = tmp;
187305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
187405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
187505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
187605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        firstOffset = tmp;
187705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
187805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
187905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
188005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 16) {
188105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
188205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
188305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
188405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
188505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
188605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
188705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
188805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
188905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 16;
189005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 16;
189105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
189205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset);
189305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
189405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 4) {
189505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
189605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
189705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
189805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint16_t referenceCount;
189905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
190005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
190105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
190205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 4;
190305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 4;
190405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("refcount: %d", referenceCount);
190505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
190605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < referenceCount * 12) {
190705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
190805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
190905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
191005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t total_duration = 0;
191105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (unsigned int i = 0; i < referenceCount; i++) {
191205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        uint32_t d1, d2, d3;
191305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
191405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &d1) ||     // size
191505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 4, &d2) || // duration
191605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
191705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
191805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
191905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
192005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (d1 & 0x80000000) {
192105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("sub-sidx boxes not supported yet");
192205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
192305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool sap = d3 & 0x80000000;
192405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool saptype = d3 >> 28;
192505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!sap || saptype > 2) {
192605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGW("not a stream access point, or unsupported type");
192705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
192805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        total_duration += d2;
192905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 12;
193005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
193105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        SidxEntry se;
193205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mSize = d1 & 0x7fffffff;
193305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        se.mDurationUs = 1000000LL * d2 / timeScale;
193405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mSidxEntries.add(se);
193505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
193605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
193705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mSidxDuration = total_duration * 1000000 / timeScale;
193805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("duration: %lld", mSidxDuration);
193905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
194005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t metaDuration;
194105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
194205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mLastTrack->meta->setInt64(kKeyDuration, mSidxDuration);
194305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
194405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
194505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
194605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
194705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
194805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
1949ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader(
1950c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t data_offset, off64_t data_size) {
1951ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (data_size < 4) {
1952ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1953ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1954ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1955ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t version;
1956ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
1957ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1958ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1959ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1960ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t dynSize = (version == 1) ? 36 : 24;
1961ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1962ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint8_t buffer[36 + 60];
1963ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1964c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    if (data_size != (off64_t)dynSize + 60) {
1965ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_MALFORMED;
1966ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1967ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1968ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (mDataSource->readAt(
1969ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber                data_offset, buffer, data_size) < (ssize_t)data_size) {
1970ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        return ERROR_IO;
1971ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1972ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1973ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint64_t ctime, mtime, duration;
1974ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t id;
1975ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1976ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (version == 1) {
1977ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U64_AT(&buffer[4]);
1978ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U64_AT(&buffer[12]);
1979ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[20]);
1980ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U64_AT(&buffer[28]);
198104022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else if (version == 0) {
1982ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        ctime = U32_AT(&buffer[4]);
1983ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mtime = U32_AT(&buffer[8]);
1984ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        id = U32_AT(&buffer[12]);
1985ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        duration = U32_AT(&buffer[20]);
198604022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen    } else {
198704022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen        return ERROR_UNSUPPORTED;
1988ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
1989ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1990ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    mLastTrack->meta->setInt32(kKeyTrackID, id);
1991ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
1992ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    size_t matrixOffset = dynSize + 16;
1993ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a00 = U32_AT(&buffer[matrixOffset]);
1994ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
1995ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
1996ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
1997ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
1998ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
1999ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2000ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0
2001df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
2002ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
2003df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
2004ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
2005ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif
2006ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2007ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t rotationDegrees;
2008ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2009ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    static const int32_t kFixedOne = 0x10000;
2010ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
2011ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        // Identity, no rotation
2012ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2013ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
2014ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 90;
2015ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
2016ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 270;
2017ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
2018ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 180;
2019ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    } else {
20205ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("We only support 0,90,180,270 degree rotation matrices");
2021ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        rotationDegrees = 0;
2022ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2023ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2024ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    if (rotationDegrees != 0) {
2025ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
2026ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    }
2027ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2028b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // Handle presentation display size, which could be different
2029b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    // from the image size indicated by kKeyWidth and kKeyHeight.
2030ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t width = U32_AT(&buffer[dynSize + 52]);
2031ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    uint32_t height = U32_AT(&buffer[dynSize + 56]);
2032b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
2033b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
2034ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2035ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber    return OK;
2036ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber}
2037ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber
2038fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) {
203972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (size < 4) {
204072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_MALFORMED;
204172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
204272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
204372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint8_t *buffer = new uint8_t[size + 1];
204472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    if (mDataSource->readAt(
204572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                offset, buffer, size) != (ssize_t)size) {
204672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        delete[] buffer;
204772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        buffer = NULL;
204872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
204972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        return ERROR_IO;
205072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
205172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
205272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t flags = U32_AT(buffer);
205372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
205472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    uint32_t metadataKey = 0;
20555d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    char chunk[5];
20565d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    MakeFourCCString(mPath[4], chunk);
20575d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen    ALOGV("meta: %s @ %lld", chunk, offset);
205872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    switch (mPath[4]) {
205972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'a', 'l', 'b'):
206072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
206172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbum;
206272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
206372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
206472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'A', 'R', 'T'):
206572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
206672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyArtist;
206772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
206872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
206966ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        case FOURCC('a', 'A', 'R', 'T'):
207066ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        {
207166ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            metadataKey = kKeyAlbumArtist;
207266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen            break;
207366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen        }
207472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'd', 'a', 'y'):
207572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
207672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyYear;
207772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
207872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
207972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'n', 'a', 'm'):
208072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
208172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyTitle;
208272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
208372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
208472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC(0xa9, 'w', 'r', 't'):
208572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
208672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyWriter;
208772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
208872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
208972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('c', 'o', 'v', 'r'):
209072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
209172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyAlbumArt;
209272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
209372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
209472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('g', 'n', 'r', 'e'):
209572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
209672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            metadataKey = kKeyGenre;
209772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
209872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
209926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC(0xa9, 'g', 'e', 'n'):
210026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
210126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            metadataKey = kKeyGenre;
210226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
210326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
210411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        case FOURCC('c', 'p', 'i', 'l'):
210511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        {
210611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            if (size == 9 && flags == 21) {
210711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                char tmp[16];
210811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                sprintf(tmp, "%d",
210911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                        (int)buffer[size - 1]);
211011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen
211111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen                mFileMetaData->setCString(kKeyCompilation, tmp);
211211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            }
211311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen            break;
211411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen        }
211572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        case FOURCC('t', 'r', 'k', 'n'):
211672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        {
211772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (size == 16 && flags == 0) {
211872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char tmp[16];
2119afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTrack = (uint16_t*)&buffer[10];
2120afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2121afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
212272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
212372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
212472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
212572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
212672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
212726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        case FOURCC('d', 'i', 's', 'k'):
212826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        {
2129afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik            if ((size == 14 || size == 16) && flags == 0) {
213026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                char tmp[16];
2131afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pDisc = (uint16_t*)&buffer[10];
2132afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2133afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
213426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
213526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(kKeyDiscNumber, tmp);
213626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            }
213726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            break;
213826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen        }
21395d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        case FOURCC('-', '-', '-', '-'):
21405d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        {
21415d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            buffer[size] = '\0';
21425d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            switch (mPath[5]) {
21435d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('m', 'e', 'a', 'n'):
21445d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentMean.setTo((const char *)buffer + 4);
21455d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21465d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('n', 'a', 'm', 'e'):
21475d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentName.setTo((const char *)buffer + 4);
21485d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21495d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                case FOURCC('d', 'a', 't', 'a'):
21505d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    mLastCommentData.setTo((const char *)buffer + 8);
21515d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                    break;
21525d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
21538c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21548c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // Once we have a set of mean/name/data info, go ahead and process
21558c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // it to see if its something we are interested in.  Whether or not
21568c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // were are interested in the specific tag, make sure to clear out
21578c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // the set so we can be ready to process another tuple should one
21588c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            // show up later in the file.
21598c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman            if ((mLastCommentMean.length() != 0) &&
21608c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentName.length() != 0) &&
21618c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                (mLastCommentData.length() != 0)) {
21628c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21638c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                if (mLastCommentMean == "com.apple.iTunes"
21648c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        && mLastCommentName == "iTunSMPB") {
21658c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    int32_t delay, padding;
21668c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    if (sscanf(mLastCommentData,
21678c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                               " %*x %x %x %*x", &delay, &padding) == 2) {
21688c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
21698c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
21708c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman                    }
21715d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                }
21728c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman
21735d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentMean.clear();
21745d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentName.clear();
21755d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen                mLastCommentData.clear();
21765d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            }
21775d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen            break;
21785d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen        }
217926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
218072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        default:
218172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            break;
218272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
218372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2184328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {
218572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        if (metadataKey == kKeyAlbumArt) {
218672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setData(
218772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    kKeyAlbumArt, MetaData::TYPE_NONE,
218872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    buffer + 8, size - 8);
218972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else if (metadataKey == kKeyGenre) {
219072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            if (flags == 0) {
219126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // uint8_t genre code, iTunes genre codes are
219226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // the standard id3 codes, except they start
219326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // at 1 instead of 0 (e.g. Pop is 14, not 13)
219426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // We use standard id3 numbering, so subtract 1.
219526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                int genrecode = (int)buffer[size - 1];
219626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                genrecode--;
219726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                if (genrecode < 0) {
219826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                    genrecode = 255; // reserved for 'unknown genre'
219926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                }
220072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                char genre[10];
220126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                sprintf(genre, "%d", genrecode);
220272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
220372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                mFileMetaData->setCString(metadataKey, genre);
220426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen            } else if (flags == 1) {
220526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                // custom genre string
220626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                buffer[size] = '\0';
220726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen
220826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                mFileMetaData->setCString(
220926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen                        metadataKey, (const char *)buffer + 8);
221072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            }
221172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        } else {
221272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            buffer[size] = '\0';
221372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
221472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber            mFileMetaData->setCString(
221572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber                    metadataKey, (const char *)buffer + 8);
221672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber        }
221772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    }
221872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
221972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    delete[] buffer;
222072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    buffer = NULL;
222172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
222272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber    return OK;
222372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}
222472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber
2225fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) {
2226fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (size < 4) {
2227fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_MALFORMED;
2228fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2229fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2230fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    uint8_t *buffer = new uint8_t[size];
2231fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (mDataSource->readAt(
2232fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                offset, buffer, size) != (ssize_t)size) {
2233fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        delete[] buffer;
2234fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        buffer = NULL;
2235fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2236fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        return ERROR_IO;
2237fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2238fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2239fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    uint32_t metadataKey = 0;
2240fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    switch (mPath[depth]) {
2241fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('t', 'i', 't', 'l'):
2242fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2243fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyTitle;
2244fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2245fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2246fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('p', 'e', 'r', 'f'):
2247fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2248fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyArtist;
2249fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2250fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2251fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'u', 't', 'h'):
2252fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2253fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyWriter;
2254fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2255fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2256fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('g', 'n', 'r', 'e'):
2257fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2258fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyGenre;
2259fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2260fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2261fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('a', 'l', 'b', 'm'):
2262fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2263fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (buffer[size - 1] != '\0') {
2264fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              char tmp[4];
2265fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              sprintf(tmp, "%u", buffer[size - 1]);
2266fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2267fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé              mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
2268fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2269fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2270fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            metadataKey = kKeyAlbum;
2271fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2272fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2273fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        case FOURCC('y', 'r', 'r', 'c'):
2274fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        {
2275fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            char tmp[5];
2276fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            uint16_t year = U16_AT(&buffer[4]);
2277fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2278fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (year < 10000) {
2279fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                sprintf(tmp, "%u", year);
2280fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2281fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                mFileMetaData->setCString(kKeyYear, tmp);
2282fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2283fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2284fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2285fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2286fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        default:
2287fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            break;
2288fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2289fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2290fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    if (metadataKey > 0) {
2291fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        bool isUTF8 = true; // Common case
2292fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        char16_t *framedata = NULL;
2293fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        int len16 = 0; // Number of UTF-16 characters
2294fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2295fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        // smallest possible valid UTF-16 string w BOM: 0xfe 0xff 0x00 0x00
2296fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (size - 6 >= 4) {
2297fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            len16 = ((size - 6) / 2) - 1; // don't include 0x0000 terminator
2298fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            framedata = (char16_t *)(buffer + 6);
2299fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfffe == *framedata) {
2300fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // endianness marker (BOM) doesn't match host endianness
2301fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                for (int i = 0; i < len16; i++) {
2302fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                    framedata[i] = bswap_16(framedata[i]);
2303fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                }
2304fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // BOM is now swapped to 0xfeff, we will execute next block too
2305fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2306fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2307fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            if (0xfeff == *framedata) {
2308fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                // Remove the BOM
2309fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                framedata++;
2310fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                len16--;
2311fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé                isUTF8 = false;
2312fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            }
2313fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // else normal non-zero-length UTF-8 string
2314fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // we can't handle UTF-16 without BOM as there is no other
2315fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // indication of encoding.
2316fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2317fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2318fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        if (isUTF8) {
2319fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, (const char *)buffer + 6);
2320fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        } else {
2321fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            // Convert from UTF-16 string to UTF-8 string.
2322fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            String8 tmpUTF8str(framedata, len16);
2323fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé            mFileMetaData->setCString(metadataKey, tmpUTF8str.string());
2324fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé        }
2325fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    }
2326fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2327fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    delete[] buffer;
2328fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    buffer = NULL;
2329fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2330fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé    return OK;
2331fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé}
2332fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé
2333328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhévoid MPEG4Extractor::parseID3v2MetaData(off64_t offset) {
2334328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    ID3 id3(mDataSource, true /* ignorev1 */, offset);
2335328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2336328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    if (id3.isValid()) {
2337328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        struct Map {
2338328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            int key;
2339328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag1;
2340328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            const char *tag2;
2341328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2342328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const Map kMap[] = {
2343328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbum, "TALB", "TAL" },
2344328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyArtist, "TPE1", "TP1" },
2345328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAlbumArtist, "TPE2", "TP2" },
2346328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyComposer, "TCOM", "TCM" },
2347328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyGenre, "TCON", "TCO" },
2348328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyTitle, "TIT2", "TT2" },
2349328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyYear, "TYE", "TYER" },
2350328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyAuthor, "TXT", "TEXT" },
2351328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCDTrackNumber, "TRK", "TRCK" },
2352328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyDiscNumber, "TPA", "TPOS" },
2353328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            { kKeyCompilation, "TCP", "TCMP" },
2354328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        };
2355328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
2356328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2357328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        for (size_t i = 0; i < kNumMapEntries; ++i) {
2358328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            if (!mFileMetaData->hasData(kMap[i].key)) {
2359328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
2360328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2361328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2362328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    it = new ID3::Iterator(id3, kMap[i].tag2);
2363328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2364328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2365328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                if (it->done()) {
2366328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    delete it;
2367328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                    continue;
2368328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                }
2369328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2370328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                String8 s;
2371328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                it->getString(&s);
2372328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                delete it;
2373328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2374328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé                mFileMetaData->setCString(kMap[i].key, s);
2375328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            }
2376328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2377328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2378328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        size_t dataSize;
2379328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        String8 mime;
2380328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        const void *data = id3.getAlbumArt(&dataSize, &mime);
2381328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2382328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        if (data) {
2383328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
2384328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé            mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string());
2385328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé        }
2386328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé    }
2387328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé}
2388328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé
2389693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
239020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    status_t err;
239120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if ((err = readMetaData()) != OK) {
2392693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        return NULL;
239320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
239420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
239520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Track *track = mFirstTrack;
239620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    while (index > 0) {
239720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (track == NULL) {
2398693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber            return NULL;
239920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
240020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
240120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        track = track->next;
240220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        --index;
240320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
240420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2405371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    if (track == NULL) {
2406371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber        return NULL;
2407371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber    }
2408371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber
2409ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("getTrack called, pssh: %d", mPssh.size());
2410ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2411693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber    return new MPEG4Source(
241205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            track->meta, mDataSource, track->timescale, track->sampleTable,
241305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mSidxEntries, mMoofOffset);
241420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
241520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2416bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static
2417bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) {
2418bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const char *mime;
2419bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2420bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2421bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    uint32_t type;
2422bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    const void *data;
2423bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    size_t size;
2424bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
2425bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
2426bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeAVCC) {
2427bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2428bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2429bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
2430bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2431bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
2432bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber                || type != kTypeESDS) {
2433bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber            return ERROR_MALFORMED;
2434bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber        }
2435bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    }
2436bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2437169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    if (!track->sampleTable->isValid()) {
2438169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        // Make sure we have all the metadata we need.
2439169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber        return ERROR_MALFORMED;
2440169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber    }
2441169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber
2442bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber    return OK;
2443bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber}
2444bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber
2445f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivitypedef enum {
2446f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NONE             = -1,
2447f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_NULL_OBJECT      = 0,
2448f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_MAIN         = 1, /**< Main profile                              */
2449f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_AAC_LC           = 2,   /**< Low Complexity object                     */
2450f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SSR          = 3,
2451f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_LTP          = 4,
2452f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_SBR              = 5,
2453f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SCAL         = 6,
2454f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TWIN_VQ          = 7,
2455f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_CELP             = 8,
2456f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_HVXC             = 9,
2457f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_10          = 10, /**< (reserved)                                */
2458f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_11          = 11, /**< (reserved)                                */
2459f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_TTSI             = 12, /**< TTSI Object                               */
2460f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MAIN_SYNTH       = 13, /**< Main Synthetic object                     */
2461f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_WAV_TAB_SYNTH    = 14, /**< Wavetable Synthesis object                */
2462f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_GEN_MIDI         = 15, /**< General MIDI object                       */
2463f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */
2464f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LC        = 17,   /**< Error Resilient(ER) AAC Low Complexity    */
2465f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_18          = 18, /**< (reserved)                                */
2466f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_LTP       = 19, /**< Error Resilient(ER) AAC LTP object        */
2467f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_SCAL      = 20,   /**< Error Resilient(ER) AAC Scalable object   */
2468f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_TWIN_VQ       = 21, /**< Error Resilient(ER) TwinVQ object         */
2469f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_BSAC          = 22,   /**< Error Resilient(ER) BSAC object           */
2470f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ER_AAC_LD        = 23,   /**< Error Resilient(ER) AAC LowDelay object   */
2471f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_CELP          = 24, /**< Error Resilient(ER) CELP object           */
2472f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HVXC          = 25, /**< Error Resilient(ER) HVXC object           */
2473f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_HILN          = 26, /**< Error Resilient(ER) HILN object           */
2474f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_PARA          = 27, /**< Error Resilient(ER) Parametric object     */
2475f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_28          = 28, /**< might become SSC                          */
2476f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_PS               = 29,   /**< PS, Parametric Stereo (includes SBR)      */
2477f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MPEGS            = 30, /**< MPEG Surround                             */
2478f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2479f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    AOT_ESCAPE           = 31,   /**< Signal AOT uses more than 5 bits          */
2480f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2481f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L1      = 32, /**< MPEG-Layer1 in mp4                        */
2482f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L2      = 33, /**< MPEG-Layer2 in mp4                        */
2483f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_MP3ONMP4_L3      = 34, /**< MPEG-Layer3 in mp4                        */
2484f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_35          = 35, /**< might become DST                          */
2485f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD_36          = 36, /**< might become ALS                          */
2486f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_AAC_SLS          = 37, /**< AAC + SLS                                 */
2487f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SLS              = 38, /**< SLS                                       */
2488f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_ER_AAC_ELD       = 39, /**< AAC Enhanced Low Delay                    */
2489f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2490f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_USAC             = 42, /**< USAC                                      */
2491f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_SAOC             = 43, /**< SAOC                                      */
2492f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_LD_MPEGS         = 44, /**< Low Delay MPEG Surround                   */
2493f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2494f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    //AOT_RSVD50           = 50,  /**< Interim AOT for Rsvd50                   */
2495f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi} AUDIO_OBJECT_TYPE;
2496f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2497ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
2498ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        const void *esds_data, size_t esds_size) {
2499ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    ESDS esds(esds_data, esds_size);
250081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
250181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    uint8_t objectTypeIndication;
250281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
250381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return ERROR_MALFORMED;
250481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
250581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
250681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    if (objectTypeIndication == 0xe1) {
250781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        // This isn't MPEG4 audio at all, it's QCELP 14k...
250881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
250981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber        return OK;
251081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber    }
251181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber
2512633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    if (objectTypeIndication  == 0x6b) {
2513633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // The media subtype is MP3 audio
2514633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // Our software MP3 audio decoder may not be able to handle
2515633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
251629357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("MP3 track in MP4/3GPP file is not supported");
2517633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong        return ERROR_UNSUPPORTED;
2518633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong    }
2519633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong
2520ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    const uint8_t *csd;
2521ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    size_t csd_size;
2522ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (esds.getCodecSpecificInfo(
2523ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber                (const void **)&csd, &csd_size) != OK) {
2524ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2525ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2526ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2527ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0
2528ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    printf("ESD of size %d\n", csd_size);
2529ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    hexdump(csd, csd_size);
2530ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif
2531ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2532a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    if (csd_size == 0) {
2533a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // There's no further information, i.e. no codec specific data
2534a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // Let's assume that the information provided in the mpeg4 headers
2535a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        // is accurate and hope for the best.
2536a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2537a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber        return OK;
2538a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber    }
2539a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber
2540ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (csd_size < 2) {
2541ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_MALFORMED;
2542ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2543ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
254400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    static uint32_t kSamplingRate[] = {
254500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
254600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        16000, 12000, 11025, 8000, 7350
254700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    };
254800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
2549aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    ABitReader br(csd, csd_size);
2550aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t objectType = br.getBits(5);
2551ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2552aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    if (objectType == 31) {  // AAC-ELD => additional 6 bits
2553aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        objectType = 32 + br.getBits(6);
2554ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2555ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2556db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    //keep AOT type
2557db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
2558db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent
2559aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke    uint32_t freqIndex = br.getBits(4);
2560aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke
2561ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t sampleRate = 0;
2562ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t numChannels = 0;
2563ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (freqIndex == 15) {
2564ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        if (csd_size < 5) {
2565ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber            return ERROR_MALFORMED;
2566ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2567aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        sampleRate = br.getBits(24);
2568aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke        numChannels = br.getBits(4);
2569ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    } else {
2570595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        numChannels = br.getBits(4);
257100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent
257200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (freqIndex == 13 || freqIndex == 14) {
257300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            return ERROR_MALFORMED;
2574ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        }
2575ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
257600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        sampleRate = kSamplingRate[freqIndex];
257700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent    }
2578595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen
2579f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13
258000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        uint32_t extFreqIndex = br.getBits(4);
258100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        int32_t extSampleRate;
258200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        if (extFreqIndex == 15) {
258300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (csd_size < 8) {
2584595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen                return ERROR_MALFORMED;
2585595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen            }
258600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = br.getBits(24);
258700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        } else {
258800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            if (extFreqIndex == 13 || extFreqIndex == 14) {
258900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent                return ERROR_MALFORMED;
259000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            }
259100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent            extSampleRate = kSamplingRate[extFreqIndex];
2592595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen        }
259300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //TODO: save the extension sampling rate value in meta data =>
259400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
2595ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2596ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2597f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    switch (numChannels) {
2598f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        // values defined in 14496-3_2009 amendment-4 Table 1.19 - Channel Configuration
2599f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 0:
2600f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 1:// FC
2601f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 2:// FL FR
2602f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 3:// FC, FL FR
2603f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 4:// FC, FL FR, RC
2604f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 5:// FC, FL FR, SL SR
2605f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 6:// FC, FL FR, SL SR, LFE
2606f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            //numChannels already contains the right value
2607f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2608f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 11:// FC, FL FR, SL SR, RC, LFE
2609f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 7;
2610f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2611f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 7: // FC, FCL FCR, FL FR, SL SR, LFE
2612f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 12:// FC, FL  FR,  SL SR, RL RR, LFE
2613f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        case 14:// FC, FL  FR,  SL SR, LFE, FHL FHR
2614f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            numChannels = 8;
2615f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            break;
2616f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        default:
2617f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            return ERROR_UNSUPPORTED;
2618f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
2619f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2620f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    {
2621f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_SBR || objectType == AOT_PS) {
2622f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t extensionSamplingFrequency = br.getBits(4);
2623f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            objectType = br.getBits(5);
2624f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2625f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (objectType == AOT_ESCAPE) {
2626f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType = 32 + br.getBits(6);
2627f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2628f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
2629f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        if (objectType == AOT_AAC_LC || objectType == AOT_ER_AAC_LC ||
2630f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_AAC_LD || objectType == AOT_ER_AAC_SCAL ||
2631f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                objectType == AOT_ER_BSAC) {
2632f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t frameLengthFlag = br.getBits(1);
2633f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2634f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t dependsOnCoreCoder = br.getBits(1);
2635f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2636f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (dependsOnCoreCoder ) {
2637f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t coreCoderDelay = br.getBits(14);
2638f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2639f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2640f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            const int32_t extensionFlag = br.getBits(1);
2641f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2642f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            if (numChannels == 0 ) {
2643f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsEffectiveNum = 0;
2644f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int32_t channelsNum = 0;
2645f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t ElementInstanceTag = br.getBits(4);
2646f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t Profile = br.getBits(2);
2647f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t SamplingFrequencyIndex = br.getBits(4);
2648f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumFrontChannelElements = br.getBits(4);
2649f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumSideChannelElements = br.getBits(4);
2650f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumBackChannelElements = br.getBits(4);
2651f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumLfeChannelElements = br.getBits(2);
2652f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumAssocDataElements = br.getBits(3);
2653f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t NumValidCcElements = br.getBits(4);
2654f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2655f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MonoMixdownPresent = br.getBits(1);
2656f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MonoMixdownPresent != 0) {
2657f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t MonoMixdownElementNumber = br.getBits(4);
2658f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2659f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2660f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t StereoMixdownPresent = br.getBits(1);
2661f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (StereoMixdownPresent != 0) {
2662f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t StereoMixdownElementNumber = br.getBits(4);
2663f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2664f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2665f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                const int32_t MatrixMixdownIndexPresent = br.getBits(1);
2666f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                if (MatrixMixdownIndexPresent != 0) {
2667f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t MatrixMixdownIndex = br.getBits(2);
2668f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t PseudoSurroundEnable = br.getBits(1);
2669f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2670f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2671f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                int i;
2672f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumFrontChannelElements; i++) {
2673f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t FrontElementIsCpe = br.getBits(1);
2674f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t FrontElementTagSelect = br.getBits(4);
2675f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += FrontElementIsCpe ? 2 : 1;
2676f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2677f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2678f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumSideChannelElements; i++) {
2679f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t SideElementIsCpe = br.getBits(1);
2680f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t SideElementTagSelect = br.getBits(4);
2681f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += SideElementIsCpe ? 2 : 1;
2682f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2683f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2684f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumBackChannelElements; i++) {
2685f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t BackElementIsCpe = br.getBits(1);
2686f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t BackElementTagSelect = br.getBits(4);
2687f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += BackElementIsCpe ? 2 : 1;
2688f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2689f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                channelsEffectiveNum = channelsNum;
2690f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2691f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                for (i=0; i < NumLfeChannelElements; i++) {
2692f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    const int32_t LfeElementTagSelect = br.getBits(4);
2693f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                    channelsNum += 1;
2694f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                }
2695f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsNum = %d", channelsNum);
2696f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                ALOGV("mpeg4 audio channelsEffectiveNum = %d", channelsEffectiveNum);
2697f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi                numChannels = channelsNum;
2698f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi            }
2699f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi        }
2700f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi    }
2701f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi
2702ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (numChannels == 0) {
2703ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber        return ERROR_UNSUPPORTED;
2704ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2705ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2706ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevSampleRate;
2707ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
2708ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2709ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevSampleRate != sampleRate) {
27103856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio sample rate different from previous setting. "
2711ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevSampleRate, sampleRate);
2712ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2713ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2714ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
2715ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2716ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    int32_t prevChannelCount;
2717ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
2718ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2719ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    if (prevChannelCount != numChannels) {
27203856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        ALOGV("mpeg4 audio channel count different from previous setting. "
2721ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber             "was: %d, now: %d", prevChannelCount, numChannels);
2722ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    }
2723ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2724ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
2725ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
2726ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber    return OK;
2727ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber}
2728ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber
272920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber////////////////////////////////////////////////////////////////////////////////
273020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
273120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source(
273220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        const sp<MetaData> &format,
2733693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &dataSource,
273448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        int32_t timeScale,
273505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const sp<SampleTable> &sampleTable,
273605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        Vector<SidxEntry> &sidx,
273705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t firstMoofOffset)
273820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    : mFormat(format),
273920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mDataSource(dataSource),
274048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber      mTimescale(timeScale),
274120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mSampleTable(sampleTable),
274220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mCurrentSampleIndex(0),
274305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentFragmentIndex(0),
274405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mSegments(sidx),
274505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mFirstMoofOffset(firstMoofOffset),
274605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentMoofOffset(firstMoofOffset),
274705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen      mCurrentTime(0),
2748ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoAllocSize(0),
2749ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoSizes(NULL),
2750ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsetsAllocSize(0),
2751ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen      mCurrentSampleInfoOffsets(NULL),
275220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mIsAVC(false),
27536064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber      mNALLengthSize(0),
275420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mStarted(false),
275520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mGroup(NULL),
275620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber      mBuffer(NULL),
2757dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber      mWantsNALFragments(false),
27580024245e134467d120b40099da16c467dc365e76Andreas Huber      mSrcBuffer(NULL) {
2759ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2760ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
276148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mDefaultIVSize = 0;
2762ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
2763ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t keytype;
2764ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    const void *key;
2765ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    size_t keysize;
2766ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
2767ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        CHECK(keysize <= 16);
2768ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(mCryptoKey, 0, 16);
2769ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memcpy(mCryptoKey, key, keysize);
2770ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2771ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
277220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    const char *mime;
277320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    bool success = mFormat->findCString(kKeyMIMEType, &mime);
2774dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(success);
277520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
277618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
27776064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
27786064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    if (mIsAVC) {
27796064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        uint32_t type;
27806064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const void *data;
27816064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t size;
27826064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
27836064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
27846064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        const uint8_t *ptr = (const uint8_t *)data;
27856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
27866064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(size >= 7);
2787ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
27886064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
27896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        // The number of bytes used to encode the length of a NAL unit.
27906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        mNALLengthSize = 1 + (ptr[4] & 3);
27916064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
279205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
279305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
279405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
279505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset != 0) {
279605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        off64_t offset = mFirstMoofOffset;
279705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&offset);
279805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
279920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
280020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
280120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() {
280220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mStarted) {
280320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        stop();
280420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
2805ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoSizes);
2806ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    free(mCurrentSampleInfoOffsets);
280720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
280820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
280920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) {
28107b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
28117b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2812dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(!mStarted);
281320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
281420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int32_t val;
2815dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (params && params->findInt32(kKeyWantsNALFragments, &val)
281620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        && val != 0) {
2817dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = true;
281820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    } else {
2819dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mWantsNALFragments = false;
282020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
282120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
282220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = new MediaBufferGroup;
282320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2824738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    int32_t max_size;
2825738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
282620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2827738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber    mGroup->add_buffer(new MediaBuffer(max_size));
28280024245e134467d120b40099da16c467dc365e76Andreas Huber
28290024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = new uint8_t[max_size];
283020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
283120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = true;
283220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
283320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
283420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
283520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
283620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() {
28377b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
28387b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
2839dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
284020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
284120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (mBuffer != NULL) {
284220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->release();
284320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
284420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
284520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
28460024245e134467d120b40099da16c467dc365e76Andreas Huber    delete[] mSrcBuffer;
28470024245e134467d120b40099da16c467dc365e76Andreas Huber    mSrcBuffer = NULL;
28480024245e134467d120b40099da16c467dc365e76Andreas Huber
284920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    delete mGroup;
285020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mGroup = NULL;
285120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
285220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mStarted = false;
285320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    mCurrentSampleIndex = 0;
285420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
285520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return OK;
285620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
285720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
285805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) {
285905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t hdr[2];
286005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
286105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_IO;
286205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
286305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t chunk_size = ntohl(hdr[0]);
286405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t chunk_type = ntohl(hdr[1]);
286505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t data_offset = *offset + 8;
286605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
286705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (chunk_size == 1) {
286805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
286905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
287005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
287105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        chunk_size = ntoh64(chunk_size);
287205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        data_offset += 8;
287305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
287405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (chunk_size < 16) {
287505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // The smallest valid chunk is 16 bytes long in this case.
287605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
287705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
287805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (chunk_size < 8) {
287905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // The smallest valid chunk is 8 bytes long.
288005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
288105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
288205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
288305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    char chunk[5];
288405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    MakeFourCCString(chunk_type, chunk);
288505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset);
288605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
288705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t chunk_data_size = *offset + chunk_size - data_offset;
288805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
288905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    switch(chunk_type) {
289005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
289105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'a', 'f'):
289205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('m', 'o', 'o', 'f'): {
289305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t stop_offset = *offset + chunk_size;
289405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset = data_offset;
289505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (*offset < stop_offset) {
289605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err = parseChunk(offset);
289705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (err != OK) {
289805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
289905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
290005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
290105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
2902ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                // *offset points to the mdat box following this moof
290305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                parseChunk(offset); // doesn't actually parse it, just updates offset
290405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mNextMoofOffset = *offset;
290505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
290605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
290705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
290805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
290905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'f', 'h', 'd'): {
291005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
291105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
291205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return err;
291305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
291405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
291505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
291605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
291705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
291805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        case FOURCC('t', 'r', 'u', 'n'): {
291905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                status_t err;
292005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mLastParsedTrackId == mTrackId) {
292105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
292205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        return err;
292305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
292405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
292505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
292605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                *offset += chunk_size;
292705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                break;
292805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
292905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
2930ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'z'): {
2931ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
2932ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
2933ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
2934ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2935ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2936ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2937ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2938ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('s', 'a', 'i', 'o'): {
2939ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            status_t err;
2940ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
2941ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return err;
2942ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
2943ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2944ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2945ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2946ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2947ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        case FOURCC('m', 'd', 'a', 't'): {
2948ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // parse DRM info if present
2949ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            ALOGV("MPEG4Source::parseChunk mdat");
2950ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            // if saiz/saoi was previously observed, do something with the sampleinfos
2951ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            *offset += chunk_size;
2952ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            break;
2953ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2954ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
295505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        default: {
295605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *offset += chunk_size;
295705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            break;
295805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
295905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
296005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
296105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
296205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
296384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(
296484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
2965ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationSizes");
2966ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.12
2967ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
2968ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(
2969ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset, &version, sizeof(version))
2970ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            < (ssize_t)sizeof(version)) {
2971ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2972ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2973ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2974ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (version != 0) {
2975ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_UNSUPPORTED;
2976ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2977ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
2978ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2979ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
2980ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
2981ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
2982ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2983ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
2984ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2985ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (flags & 1) {
2986ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        uint32_t tmp;
2987ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
2988ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
2989ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2990ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoType = tmp;
2991ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
2992ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (!mDataSource->getUInt32(offset, &tmp)) {
2993ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_MALFORMED;
2994ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
2995ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentAuxInfoTypeParameter = tmp;
2996ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        offset += 4;
2997ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
2998ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
2999ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t defsize;
3000ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
3001ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3002ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3003ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentDefaultSampleInfoSize = defsize;
3004ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3005ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3006ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t smplcnt;
3007ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &smplcnt)) {
3008ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_MALFORMED;
3009ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
301048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    mCurrentSampleInfoCount = smplcnt;
3011ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3012ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
301348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (mCurrentDefaultSampleInfoSize != 0) {
301448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
301548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        return OK;
301648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
3017ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (smplcnt > mCurrentSampleInfoAllocSize) {
3018ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
3019ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoAllocSize = smplcnt;
3020ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3021ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3022ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
3023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3024ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3025ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
302684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
302784333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber        off64_t offset, off64_t /* size */) {
3028ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    ALOGV("parseSampleAuxiliaryInformationOffsets");
3029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // 14496-12 8.7.13
3030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint8_t version;
3031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
3032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3033ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3034ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset++;
3035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t flags;
3037ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt24(offset, &flags)) {
3038ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3039ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3040ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 3;
3041ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3042ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    uint32_t entrycount;
3043ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &entrycount)) {
3044ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        return ERROR_IO;
3045ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3046ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    offset += 4;
3047ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3048ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
3049ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
3050ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        mCurrentSampleInfoOffsetsAllocSize = entrycount;
3051ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3052ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    mCurrentSampleInfoOffsetCount = entrycount;
3053ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3054ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < entrycount; i++) {
3055ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (version == 0) {
3056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint32_t tmp;
3057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt32(offset, &tmp)) {
3058ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3060ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 4;
3062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        } else {
3063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            uint64_t tmp;
3064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            if (!mDataSource->getUInt64(offset, &tmp)) {
3065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            mCurrentSampleInfoOffsets[i] = tmp;
3068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            offset += 8;
3069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    // parse clear/encrypted data
3073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
3075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    drmoffset += mCurrentMoofOffset;
3077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    int ivlength;
3078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
307948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
308048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    // read CencSampleAuxiliaryDataFormats
3081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
3082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        Sample *smpl = &mCurrentSamples.editItemAt(i);
3083ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3084ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        memset(smpl->iv, 0, 16);
3085ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
3086ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            return ERROR_IO;
3087ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3088ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3089ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        drmoffset += ivlength;
3090ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
309148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
309248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize == 0) {
309348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smplinfosize = mCurrentSampleInfoSizes[i];
3094ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
309548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        if (smplinfosize > ivlength) {
309648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            uint16_t numsubsamples;
309748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
3098ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen                return ERROR_IO;
3099ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
3100ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            drmoffset += 2;
310148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            for (size_t j = 0; j < numsubsamples; j++) {
310248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint16_t numclear;
310348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                uint32_t numencrypted;
310448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
310548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
310648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
310748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 2;
310848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
310948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                    return ERROR_IO;
311048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                }
311148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                drmoffset += 4;
311248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.add(numclear);
311348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.add(numencrypted);
3114ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen            }
311548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        } else {
311648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->clearsizes.add(0);
311748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen            smpl->encryptedsizes.add(smpl->size);
3118ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        }
3119ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    }
3120ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3121ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
3122ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    return OK;
3123ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen}
3124ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen
312505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
312605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
312705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
312805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
312905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
313005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
313105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
3132ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
313305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
313405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
313505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
313605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
313705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
313805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
313905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
314005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
314105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
314205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
314305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
314405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mLastParsedTrackId != mTrackId) {
314505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // this is not the right track, skip it
314605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
314705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
314805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
314905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mFlags = flags;
315005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
315105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
315205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
315305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
315405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
315505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
315605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
315705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 8) {
315805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
315905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
316005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
316105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
316205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
316305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
316405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 8;
316505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 8;
316605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
316705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
316805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
316905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
317005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
317105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
317205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
317305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
317405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
317505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
317605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
317705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
317805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
317905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
318005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
318105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
318205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
318305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
318405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
318505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
318605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
318705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
318805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
318905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
319005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
319105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
319205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
319305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
319405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
319505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
319605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
319705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
319805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
319905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
320005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
320105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
320205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
320305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
320405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
320505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
320605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
320705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
320805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
320905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
321005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
321105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
321205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
321305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
321405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
321505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
321605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
321705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
321805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
321905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
322005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = 0;
322105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
322205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
322305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
322405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
322505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
322605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
322705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < 8) {
322805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
322905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
323005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
323105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    enum {
323205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kDataOffsetPresent                  = 0x01,
323305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kFirstSampleFlagsPresent            = 0x04,
323405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleDurationPresent              = 0x100,
323505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleSizePresent                  = 0x200,
323605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleFlagsPresent                 = 0x400,
323705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        kSampleCompositionTimeOffsetPresent = 0x800,
323805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    };
323905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
324005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t flags;
324105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset, &flags)) {
324205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
324305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
324405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("fragment run flags: %08x", flags);
324505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
324605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & 0xff000000) {
324705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
324805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
324905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
325005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
325105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // These two shall not be used together.
325205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
325305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
325405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
325505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleCount;
325605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
325705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return ERROR_MALFORMED;
325805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
325905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    offset += 8;
326005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size -= 8;
326105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
326205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
326305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
326405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t firstSampleFlags = 0;
326505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
326605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kDataOffsetPresent) {
326705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
326805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
326905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
327005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
327105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t dataOffsetDelta;
327205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
327305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
327405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
327505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
327605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
327705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
327805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
327905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
328005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
328105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
328205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kFirstSampleFlagsPresent) {
328305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (size < 4) {
328405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return -EINVAL;
328505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
328605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
328705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
328805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
328905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
329005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset += 4;
329105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size -= 4;
329205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
329305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
329405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
329505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen             sampleCtsOffset = 0;
329605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
329705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    size_t bytesPerSample = 0;
329805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleDurationPresent) {
329905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
330005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
330105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
330205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
330305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
330405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
330505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
330605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
330705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleSizePresent) {
330805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
330905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
331005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
331105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
331205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
331305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
331405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
331505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
331605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleFlagsPresent) {
331705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
331805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else if (mTrackFragmentHeaderInfo.mFlags
331905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
332005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
332105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
332205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
332305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
332405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
332505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (flags & kSampleCompositionTimeOffsetPresent) {
332605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bytesPerSample += 4;
332705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
332805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        sampleCtsOffset = 0;
332905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
333005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
333105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (size < sampleCount * bytesPerSample) {
333205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return -EINVAL;
333305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
333405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
333505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    Sample tmp;
333605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    for (uint32_t i = 0; i < sampleCount; ++i) {
333705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleDurationPresent) {
333805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
333905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
334005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
334105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
334205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
334305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
334405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleSizePresent) {
334505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleSize)) {
334605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
334705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
334805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
334905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
335005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
335105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleFlagsPresent) {
335205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
335305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
335405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
335505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
335605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
335705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
335805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (flags & kSampleCompositionTimeOffsetPresent) {
335905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
336005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_MALFORMED;
336105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
336205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            offset += 4;
336305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
336405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3365ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen        ALOGV("adding sample %d at offset 0x%08llx, size %u, duration %u, "
3366ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen              " flags 0x%08x", i + 1,
336705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dataOffset, sampleSize, sampleDuration,
336805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                (flags & kFirstSampleFlagsPresent) && i == 0
336905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ? firstSampleFlags : sampleFlags);
337005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.offset = dataOffset;
337105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.size = sampleSize;
337205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        tmp.duration = sampleDuration;
337305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.add(tmp);
337405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
337505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        dataOffset += sampleSize;
337605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
337705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
337805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
337905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
338005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    return OK;
338105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
338205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
338320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() {
33847b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
33857b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
338620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return mFormat;
338720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
338820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
33896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const {
33906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    switch (mNALLengthSize) {
33916064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 1:
33926064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return *data;
33936064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 2:
33946064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U16_AT(data);
33956064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 3:
33966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
33976064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        case 4:
33986064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber            return U32_AT(data);
33996064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    }
34006064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
34016064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // This cannot happen, mNALLengthSize springs to life by adding 1 to
34026064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    // a 2-bit integer.
34036064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    CHECK(!"Should not be here.");
34046064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
34056064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber    return 0;
34066064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber}
34076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
340820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read(
340920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
34107b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber    Mutex::Autolock autoLock(mLock);
34117b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber
3412dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    CHECK(mStarted);
341320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
341405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mFirstMoofOffset > 0) {
341505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return fragmentedRead(out, options);
341605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
341820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    *out = NULL;
341920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3420abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    int64_t targetSampleTimeUs = -1;
3421abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
342220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    int64_t seekTimeUs;
3423abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    ReadOptions::SeekMode mode;
3424abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3425abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t findFlags = 0;
3426abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        switch (mode) {
3427abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_PREVIOUS_SYNC:
3428abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagBefore;
3429abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3430abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_NEXT_SYNC:
3431abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagAfter;
3432abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3433abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST_SYNC:
3434abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            case ReadOptions::SEEK_CLOSEST:
3435abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                findFlags = SampleTable::kFlagClosest;
3436abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3437abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            default:
3438abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                CHECK(!"Should not be here.");
3439abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                break;
3440abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3441abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
344220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        uint32_t sampleIndex;
3443abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        status_t err = mSampleTable->findSampleAtTime(
344420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber                seekTimeUs * mTimescale / 1000000,
3445abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                &sampleIndex, findFlags);
3446abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3447abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3448abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // We found the closest sample already, now we want the sync
3449abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // sample preceding it (or the sample itself of course), even
3450abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            // if the subsequent sync sample is closer.
3451abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            findFlags = SampleTable::kFlagBefore;
3452abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3453abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3454abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleIndex;
3455abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (err == OK) {
3456abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            err = mSampleTable->findSyncSampleNear(
3457abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    sampleIndex, &syncSampleIndex, findFlags);
3458abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
345920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3460788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        uint32_t sampleTime;
3461788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        if (err == OK) {
3462788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber            err = mSampleTable->getMetaDataForSample(
3463788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber                    sampleIndex, NULL, NULL, &sampleTime);
3464788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber        }
3465788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber
346620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (err != OK) {
34675295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            if (err == ERROR_OUT_OF_RANGE) {
34685295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // An attempt to seek past the end of the stream would
34695295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
34705295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // this all the way to the MediaPlayer would cause abnormal
34715295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // termination. Legacy behaviour appears to be to behave as if
34725295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                // we had seeked to the end of stream, ending normally.
34735295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber                err = ERROR_END_OF_STREAM;
34745295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber            }
347505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("end of stream");
347620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            return err;
347720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
347820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3479abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (mode == ReadOptions::SEEK_CLOSEST) {
3480abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
3481abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3482abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3483abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0
3484abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        uint32_t syncSampleTime;
3485abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
3486abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    syncSampleIndex, NULL, NULL, &syncSampleTime));
3487abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3488df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block        ALOGI("seek to time %lld us => sample at time %lld us, "
3489abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             "sync sample at time %lld us",
3490abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             seekTimeUs,
3491abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             sampleTime * 1000000ll / mTimescale,
3492abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber             syncSampleTime * 1000000ll / mTimescale);
3493abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif
3494abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3495abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        mCurrentSampleIndex = syncSampleIndex;
349620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (mBuffer != NULL) {
349720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
349820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
349920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
350020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
350120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        // fall through
350220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
350320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3504c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t offset;
35050024245e134467d120b40099da16c467dc365e76Andreas Huber    size_t size;
35064678a6dc5f09008481524949a9667af5a6190374Andreas Huber    uint32_t cts;
35078bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber    bool isSyncSample;
3508dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    bool newBuffer = false;
3509dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (mBuffer == NULL) {
3510dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        newBuffer = true;
351120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3512c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber        status_t err =
3513c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber            mSampleTable->getMetaDataForSample(
35144678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample);
351520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3516dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3517dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3518dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3519dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3520dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        err = mGroup->acquire_buffer(&mBuffer);
3521c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber
3522dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (err != OK) {
3523ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber            CHECK(mBuffer == NULL);
3524dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return err;
3525dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
35260024245e134467d120b40099da16c467dc365e76Andreas Huber    }
352720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3528dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    if (!mIsAVC || mWantsNALFragments) {
3529dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (newBuffer) {
3530dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ssize_t num_bytes_read =
353134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
3532dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3533dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            if (num_bytes_read < (ssize_t)size) {
3534dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer->release();
3535dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                mBuffer = NULL;
3536dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3537dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber                return ERROR_IO;
3538dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            }
3539dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
35407b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber            CHECK(mBuffer != NULL);
3541dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->set_range(0, size);
3542dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->meta_data()->clear();
354348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber            mBuffer->meta_data()->setInt64(
35444678a6dc5f09008481524949a9667af5a6190374Andreas Huber                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3545abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3546abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            if (targetSampleTimeUs >= 0) {
3547abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                mBuffer->meta_data()->setInt64(
3548abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                        kKeyTargetTime, targetSampleTimeUs);
3549abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            }
3550abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
35518bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            if (isSyncSample) {
35528bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
35538bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            }
35548bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
3555dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            ++mCurrentSampleIndex;
3556dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3557dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3558dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (!mIsAVC) {
3559dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            *out = mBuffer;
3560dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3561dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3562dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return OK;
3563dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3564dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3565dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Each NAL unit is split up into its constituent fragments and
3566dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // each one of them returned in its own buffer.
3567dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
35686064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        CHECK(mBuffer->range_length() >= mNALLengthSize);
3569dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3570dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        const uint8_t *src =
3571dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
3572dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
35736064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        size_t nal_size = parseNALSize(src);
3574e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
357529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("incomplete NAL unit.");
3576e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3577e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer->release();
3578e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            mBuffer = NULL;
3579e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3580e8a084958c27327b0aca749f69095605d2a21309Andreas Huber            return ERROR_MALFORMED;
3581e8a084958c27327b0aca749f69095605d2a21309Andreas Huber        }
3582dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3583dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        MediaBuffer *clone = mBuffer->clone();
35847b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(clone != NULL);
35856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
3586dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
35877b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber        CHECK(mBuffer != NULL);
3588dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        mBuffer->set_range(
35896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_offset() + mNALLengthSize + nal_size,
35906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber                mBuffer->range_length() - mNALLengthSize - nal_size);
3591dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3592dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        if (mBuffer->range_length() == 0) {
3593dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer->release();
3594dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            mBuffer = NULL;
3595dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3596dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3597dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        *out = clone;
3598dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3599dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        return OK;
3600dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber    } else {
3601dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // Whole NAL units are returned but each fragment is prefixed by
3602dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        // the start code (0x00 00 00 01).
3603dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        ssize_t num_bytes_read = 0;
3604dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        int32_t drm = 0;
3605dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3606dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3607dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read =
3608dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
3609dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3610dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
3611dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
361220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
361320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        if (num_bytes_read < (ssize_t)size) {
361420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer->release();
361520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber            mBuffer = NULL;
361620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3617dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber            return ERROR_IO;
361820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        }
361920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3620dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (usesDRM) {
3621dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3622dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, size);
36236064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber
3624dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
3625dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            uint8_t *dstData = (uint8_t *)mBuffer->data();
3626dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t srcOffset = 0;
3627dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            size_t dstOffset = 0;
3628e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
3629dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            while (srcOffset < size) {
363034fe252c89e33572d01fea981b58d7b115e76164James Dong                bool isMalFormed = (srcOffset + mNALLengthSize > size);
363134fe252c89e33572d01fea981b58d7b115e76164James Dong                size_t nalLength = 0;
363234fe252c89e33572d01fea981b58d7b115e76164James Dong                if (!isMalFormed) {
363334fe252c89e33572d01fea981b58d7b115e76164James Dong                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
363434fe252c89e33572d01fea981b58d7b115e76164James Dong                    srcOffset += mNALLengthSize;
363534fe252c89e33572d01fea981b58d7b115e76164James Dong                    isMalFormed = srcOffset + nalLength > size;
363634fe252c89e33572d01fea981b58d7b115e76164James Dong                }
3637e8a084958c27327b0aca749f69095605d2a21309Andreas Huber
363834fe252c89e33572d01fea981b58d7b115e76164James Dong                if (isMalFormed) {
363929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                    ALOGE("Video is malformed");
3640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer->release();
3641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    mBuffer = NULL;
3642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    return ERROR_MALFORMED;
3643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
3645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                if (nalLength == 0) {
3646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                    continue;
3647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                }
3648dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3649dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                CHECK(dstOffset + 4 <= mBuffer->size());
3650dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
3651dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3652dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3653dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 0;
3654dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstData[dstOffset++] = 1;
3655dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
3656dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                srcOffset += nalLength;
3657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                dstOffset += nalLength;
3658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            }
3659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK_EQ(srcOffset, size);
3660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            CHECK(mBuffer != NULL);
3661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            mBuffer->set_range(0, dstOffset);
3662dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber        }
3663dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber
366420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer->meta_data()->clear();
366548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber        mBuffer->meta_data()->setInt64(
36664678a6dc5f09008481524949a9667af5a6190374Andreas Huber                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3667abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
3668abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        if (targetSampleTimeUs >= 0) {
3669abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber            mBuffer->meta_data()->setInt64(
3670abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber                    kKeyTargetTime, targetSampleTimeUs);
3671abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber        }
3672abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber
36738bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        if (isSyncSample) {
36748bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
36758bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber        }
36768bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber
367720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        ++mCurrentSampleIndex;
367820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
367920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        *out = mBuffer;
368020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        mBuffer = NULL;
368120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
368220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return OK;
368320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
368420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
368520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
368605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead(
368705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer **out, const ReadOptions *options) {
368805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
368905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ALOGV("MPEG4Source::fragmentedRead");
369005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
369105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    CHECK(mStarted);
369205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
369305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    *out = NULL;
369405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
369505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t targetSampleTimeUs = -1;
369605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
369705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    int64_t seekTimeUs;
369805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    ReadOptions::SeekMode mode;
369905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
370005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
370105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int numSidxEntries = mSegments.size();
370205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (numSidxEntries != 0) {
370305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            int64_t totalTime = 0;
370405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t totalOffset = mFirstMoofOffset;
370505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            for (int i = 0; i < numSidxEntries; i++) {
370605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                const SidxEntry *se = &mSegments[i];
370705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (totalTime + se->mDurationUs > seekTimeUs) {
370805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    // The requested time is somewhere in this segment
370905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    if ((mode == ReadOptions::SEEK_NEXT_SYNC) ||
371005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
371105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
371205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // requested next sync, or closest sync and it was closer to the end of
371305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        // this segment
371405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalTime += se->mDurationUs;
371505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        totalOffset += se->mSize;
371605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    }
371705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    break;
371805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
371905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalTime += se->mDurationUs;
372005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                totalOffset += se->mSize;
372105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
372205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentMoofOffset = totalOffset;
372305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSamples.clear();
372405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentSampleIndex = 0;
372505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        parseChunk(&totalOffset);
372605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime = totalTime * mTimescale / 1000000ll;
372705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
372805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
372905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer != NULL) {
373005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
373105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
373205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
373305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
373405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // fall through
373505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
373605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
373705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    off64_t offset = 0;
3738442cc6dc48f8188e097617f7f804c314a9dacd0eAndreas Huber    size_t size = 0;
373905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    uint32_t cts = 0;
374005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool isSyncSample = false;
374105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    bool newBuffer = false;
374205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (mBuffer == NULL) {
374305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        newBuffer = true;
374405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
374505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
374605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            // move to next fragment
374705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            Sample lastSample = mCurrentSamples[mCurrentSamples.size() - 1];
374805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size;
374905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentMoofOffset = nextMoof;
375005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSamples.clear();
375105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mCurrentSampleIndex = 0;
375205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            parseChunk(&nextMoof);
375305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (mCurrentSampleIndex >= mCurrentSamples.size()) {
375405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_END_OF_STREAM;
375505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
375605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
375705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
375805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
375905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        offset = smpl->offset;
376005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size = smpl->size;
376105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        cts = mCurrentTime;
376205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mCurrentTime += smpl->duration;
376305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        isSyncSample = (mCurrentSampleIndex == 0); // XXX
376405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
376505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        status_t err = mGroup->acquire_buffer(&mBuffer);
376605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
376705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (err != OK) {
376805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer == NULL);
376905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("acquire_buffer returned %d", err);
377005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return err;
377105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
377205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
377305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
377448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
377548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    const sp<MetaData> bufmeta = mBuffer->meta_data();
377648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    bufmeta->clear();
377748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    if (smpl->encryptedsizes.size()) {
377848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        // store clear/encrypted lengths in metadata
377948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyPlainSizes, 0,
378048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
378148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyEncryptedSizes, 0,
378248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
378348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
378448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
378548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
378648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
378748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen    }
378848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen
378905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    if (!mIsAVC || mWantsNALFragments) {
379005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (newBuffer) {
379105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ssize_t num_bytes_read =
379205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
379305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
379405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (num_bytes_read < (ssize_t)size) {
379505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->release();
379605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer = NULL;
379705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
379805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                ALOGV("i/o error");
379905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                return ERROR_IO;
380005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
380105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
380205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
380305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
380405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
380505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
380605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
380705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (targetSampleTimeUs >= 0) {
380805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt64(
380905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                        kKeyTargetTime, targetSampleTimeUs);
381005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
381105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
381205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            if (isSyncSample) {
381305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
381405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
381505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
381605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ++mCurrentSampleIndex;
381705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
381805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
381905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (!mIsAVC) {
382005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            *out = mBuffer;
382105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
382205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
382305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return OK;
382405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
382505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
382605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Each NAL unit is split up into its constituent fragments and
382705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // each one of them returned in its own buffer.
382805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
382905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer->range_length() >= mNALLengthSize);
383005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
383105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        const uint8_t *src =
383205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
383305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
383405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        size_t nal_size = parseNALSize(src);
383505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
383605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGE("incomplete NAL unit.");
383705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
383805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
383905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
384005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
384105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_MALFORMED;
384205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
384305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
384405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MediaBuffer *clone = mBuffer->clone();
384505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(clone != NULL);
384605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
384705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
384805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        CHECK(mBuffer != NULL);
384905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->set_range(
385005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_offset() + mNALLengthSize + nal_size,
385105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mBuffer->range_length() - mNALLengthSize - nal_size);
385205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
385305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (mBuffer->range_length() == 0) {
385405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
385505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
385605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
385705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
385805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = clone;
385905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
386005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
386105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    } else {
386205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("whole NAL");
386305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // Whole NAL units are returned but each fragment is prefixed by
386405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        // the start code (0x00 00 00 01).
386505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ssize_t num_bytes_read = 0;
386605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        int32_t drm = 0;
386705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
386805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
386905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read =
387005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
387105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
387205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
387305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
387405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
387505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (num_bytes_read < (ssize_t)size) {
387605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->release();
387705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer = NULL;
387805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
387905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            ALOGV("i/o error");
388005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            return ERROR_IO;
388105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
388205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
388305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (usesDRM) {
388405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
388505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, size);
388605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
388705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        } else {
388805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            uint8_t *dstData = (uint8_t *)mBuffer->data();
388905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t srcOffset = 0;
389005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            size_t dstOffset = 0;
389105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
389205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            while (srcOffset < size) {
389305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                bool isMalFormed = (srcOffset + mNALLengthSize > size);
389405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                size_t nalLength = 0;
389505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (!isMalFormed) {
389605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
389705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    srcOffset += mNALLengthSize;
389805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    isMalFormed = srcOffset + nalLength > size;
389905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
390005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
390105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (isMalFormed) {
390205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    ALOGE("Video is malformed");
390305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer->release();
390405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    mBuffer = NULL;
390505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    return ERROR_MALFORMED;
390605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
390705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
390805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                if (nalLength == 0) {
390905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    continue;
391005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                }
391105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
391205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                CHECK(dstOffset + 4 <= mBuffer->size());
391305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
391405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
391505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
391605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 0;
391705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstData[dstOffset++] = 1;
391805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
391905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                srcOffset += nalLength;
392005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                dstOffset += nalLength;
392105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            }
392205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK_EQ(srcOffset, size);
392305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            CHECK(mBuffer != NULL);
392405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->set_range(0, dstOffset);
392505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
392605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
392705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer->meta_data()->setInt64(
392805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
392905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
393005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (targetSampleTimeUs >= 0) {
393105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt64(
393205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen                    kKeyTargetTime, targetSampleTimeUs);
393305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
393405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
393505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        if (isSyncSample) {
393605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
393705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        }
393805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
393905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ++mCurrentSampleIndex;
394005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
394105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        *out = mBuffer;
394205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        mBuffer = NULL;
394305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
394405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        return OK;
394505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen    }
394605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen}
394705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen
3948bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
3949bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mimePrefix) {
3950bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
3951bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        const char *mime;
3952bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        if (track->meta != NULL
3953bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && track->meta->findCString(kKeyMIMEType, &mime)
3954bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
3955bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber            return track;
3956bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber        }
3957bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    }
3958bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
3959bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber    return NULL;
3960bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber}
3961bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber
39621b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4(
3963693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
396420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    uint8_t header[8];
396520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
396634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber    ssize_t n = source->readAt(4, header, sizeof(header));
396720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (n < (ssize_t)sizeof(header)) {
396820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return false;
396920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
397020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
397120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
3972b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
3973b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
39740dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
3975ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
3976983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
397718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
39785a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        *confidence = 0.4;
397920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
398020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber        return true;
398120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
398220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
398320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    return false;
398420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
398520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
39861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) {
39871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    static const uint32_t kCompatibleBrands[] = {
39881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', 'm'),
39891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('i', 's', 'o', '2'),
39901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('a', 'v', 'c', '1'),
39911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('3', 'g', 'p', '4'),
39921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '1'),
39931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        FOURCC('m', 'p', '4', '2'),
39944cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong
39954cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Won't promise that the following file types can be played.
39964cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        // Just give these file types a chance.
39974cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
39984cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
399958fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber
400058fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
400158fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber        FOURCC('3', 'g', '2', 'b'),
40021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    };
40031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
40041b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    for (size_t i = 0;
40051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
40061b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber         ++i) {
40071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        if (kCompatibleBrands[i] == fourcc) {
40081b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            return true;
40091b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
40101b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
40111b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
40121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
40131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
40141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
40151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable
40161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present.
4017a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends
4018a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of
4019a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata.
40201b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4(
4021a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4022a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4023a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    // We scan up to 128 bytes to identify this file as an MP4.
4024a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    static const off64_t kMaxScanOffset = 128ll;
40251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4026a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t offset = 0ll;
4027a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool foundGoodFileType = false;
4028a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    off64_t moovAtomEndOffset = -1ll;
4029a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    bool done = false;
40301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4031a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    while (!done && offset < kMaxScanOffset) {
4032a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t hdr[2];
4033a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (source->readAt(offset, hdr, 8) < 8) {
4034a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4035a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4036a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4037a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint64_t chunkSize = ntohl(hdr[0]);
4038a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        uint32_t chunkType = ntohl(hdr[1]);
4039a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataOffset = offset + 8;
4040a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4041a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        if (chunkSize == 1) {
4042a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
40431b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                return false;
40441b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
40451b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4046a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkSize = ntoh64(chunkSize);
4047a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            chunkDataOffset += 8;
4048a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4049a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            if (chunkSize < 16) {
4050a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                // The smallest valid chunk is 16 bytes long in this case.
4051a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                return false;
4052a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4053a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        } else if (chunkSize < 8) {
4054a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            // The smallest valid chunk is 8 bytes long.
4055a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            return false;
4056a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        }
4057a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4058a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
4059a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
406005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        char chunkstring[5];
406105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        MakeFourCCString(chunkType, chunkstring);
406205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen        ALOGV("saw chunk type %s, size %lld @ %lld", chunkstring, chunkSize, offset);
4063a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        switch (chunkType) {
4064a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('f', 't', 'y', 'p'):
4065a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4066a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (chunkDataSize < 8) {
4067a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4068a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4069a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4070a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
4071a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
4072a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (i == 1) {
4073a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // Skip this index, it refers to the minorVersion,
4074a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        // not a brand.
4075a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        continue;
4076a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4077a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4078a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    uint32_t brand;
4079a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (source->readAt(
4080a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
4081a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        return false;
4082a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4083a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4084a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    brand = ntohl(brand);
4085a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4086a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    if (isCompatibleBrand(brand)) {
4087a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        foundGoodFileType = true;
4088a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                        break;
4089a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    }
4090a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4091a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4092a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                if (!foundGoodFileType) {
4093a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                    return false;
4094a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                }
4095a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
40961b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber                break;
40971b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber            }
4098a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4099a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            case FOURCC('m', 'o', 'o', 'v'):
4100a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            {
4101a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                moovAtomEndOffset = offset + chunkSize;
4102a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4103a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                done = true;
4104a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
4105a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            }
4106a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4107a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber            default:
4108a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber                break;
41091b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        }
4110a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4111a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        offset += chunkSize;
41121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
41131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4114a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (!foundGoodFileType) {
41151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return false;
41161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
41171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
41181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
41195a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber    *confidence = 0.4f;
41201b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
4121a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (moovAtomEndOffset >= 0) {
4122a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        *meta = new AMessage;
4123a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
4124a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
4125456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber        ALOGV("found metadata size: %lld", moovAtomEndOffset);
4126a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    }
4127a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber
41281b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return true;
41291b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
41301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
41311b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4(
41325a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4133a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber        sp<AMessage> *meta) {
4134a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
41351b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
41361b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
41371b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
41381b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    if (LegacySniffMPEG4(source, mimeType, confidence)) {
41395ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
41401b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber        return true;
41411b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    }
41421b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
41431b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber    return false;
41441b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber}
41451b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber
414620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
4147