MPEG4Extractor.cpp revision 45452ffeb3827dd3c955aca1b4ab3522b70cf8cc
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2009 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden//#define LOG_NDEBUG 0
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define LOG_TAG "MPEG4Extractor"
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn#include <ctype.h>
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <inttypes.h>
22f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn#include <stdint.h>
235b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski#include <stdlib.h>
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h>
2587eac99a21772ae56018cb81db6966557b459554Ruben Brunk
26f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn#include <utils/Log.h>
27853940331ff2be48ed3e63f459845e5e43d0a131Mark Salyzyn
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "include/MPEG4Extractor.h"
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "include/SampleTable.h"
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "include/ESDS.h"
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/stagefright/foundation/ABitReader.h>
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/stagefright/foundation/ABuffer.h>
3406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#include <media/stagefright/foundation/ADebug.h>
3506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#include <media/stagefright/foundation/AMessage.h>
360e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn#include <media/stagefright/MediaBuffer.h>
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/stagefright/MediaBufferGroup.h>
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/stagefright/MediaDefs.h>
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/stagefright/MediaSource.h>
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <media/stagefright/MetaData.h>
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/String8.h>
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <byteswap.h>
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "include/ID3.h"
450e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
460e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornnamespace android {
470e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
480e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornclass MPEG4Source : public MediaSource {
49184293076201ec510898f8d505a8fe50458d9604Dianne Hackbornpublic:
5064770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn    // Caller retains ownership of both "dataSource" and "sampleTable".
517c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    MPEG4Source(const sp<MetaData> &format,
520e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                const sp<DataSource> &dataSource,
530e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                int32_t timeScale,
54184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn                const sp<SampleTable> &sampleTable,
550e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                Vector<SidxEntry> &sidx,
560e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                const Trex *trex,
570e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                off64_t firstMoofOffset);
580e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
590e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    virtual status_t start(MetaData *params = NULL);
600e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    virtual status_t stop();
618884ef4fe80505bc6e41c167b67efbb93e43475dAnwar Ghuloum
6288887d0a53f866e61a7524b0edfc95e6dde57d72Anwar Ghuloum    virtual sp<MetaData> getFormat();
630e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
645b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL);
655b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
665b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
6764770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackbornprotected:
683c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    virtual ~MPEG4Source();
693c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
703c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloumprivate:
713c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    Mutex mLock;
723c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
7325c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier    sp<MetaData> mFormat;
7425c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier    sp<DataSource> mDataSource;
7525c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier    int32_t mTimescale;
760e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    sp<SampleTable> mSampleTable;
770e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    uint32_t mCurrentSampleIndex;
785b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    uint32_t mCurrentFragmentIndex;
790e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    Vector<SidxEntry> &mSegments;
800e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    const Trex *mTrex;
810e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    off64_t mFirstMoofOffset;
820e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    off64_t mCurrentMoofOffset;
830e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    off64_t mNextMoofOffset;
843c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    uint32_t mCurrentTime;
850e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int32_t mLastParsedTrackId;
860e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int32_t mTrackId;
873c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
883a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum    int32_t mCryptoMode;    // passed in from extractor
898883ced18ac25199330843964634fdf70647a127Dianne Hackborn    int32_t mDefaultIVSize; // passed in from extractor
900e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    uint8_t mCryptoKey[16]; // passed in from extractor
910e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    uint32_t mCurrentAuxInfoType;
920e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    uint32_t mCurrentAuxInfoTypeParameter;
930e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    int32_t mCurrentDefaultSampleInfoSize;
943c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    uint32_t mCurrentSampleInfoCount;
950e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    uint32_t mCurrentSampleInfoAllocSize;
960e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    uint8_t* mCurrentSampleInfoSizes;
973c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    uint32_t mCurrentSampleInfoOffsetCount;
983a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum    uint32_t mCurrentSampleInfoOffsetsAllocSize;
998883ced18ac25199330843964634fdf70647a127Dianne Hackborn    uint64_t* mCurrentSampleInfoOffsets;
1000e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
1010e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    bool mIsAVC;
1020e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    bool mIsHEVC;
1030e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    size_t mNALLengthSize;
1040e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
1058883ced18ac25199330843964634fdf70647a127Dianne Hackborn    bool mStarted;
1068883ced18ac25199330843964634fdf70647a127Dianne Hackborn
1078883ced18ac25199330843964634fdf70647a127Dianne Hackborn    MediaBufferGroup *mGroup;
1088883ced18ac25199330843964634fdf70647a127Dianne Hackborn
1098883ced18ac25199330843964634fdf70647a127Dianne Hackborn    MediaBuffer *mBuffer;
1108883ced18ac25199330843964634fdf70647a127Dianne Hackborn
1110e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    bool mWantsNALFragments;
1120e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
1130e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    uint8_t *mSrcBuffer;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1155b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    size_t parseNALSize(const uint8_t *data) const;
1165b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    status_t parseChunk(off64_t *offset);
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t parseTrackFragmentHeader(off64_t offset, off64_t size);
1180e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    status_t parseTrackFragmentRun(off64_t offset, off64_t size);
1193c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
1200e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
1210e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
1223c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    struct TrackFragmentHeaderInfo {
1233a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum        enum Flags {
1248883ced18ac25199330843964634fdf70647a127Dianne Hackborn            kBaseDataOffsetPresent         = 0x01,
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            kSampleDescriptionIndexPresent = 0x02,
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            kDefaultSampleDurationPresent  = 0x08,
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            kDefaultSampleSizePresent      = 0x10,
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            kDefaultSampleFlagsPresent     = 0x20,
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            kDurationIsEmpty               = 0x10000,
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t mTrackID;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t mFlags;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint64_t mBaseDataOffset;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t mSampleDescriptionIndex;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t mDefaultSampleDuration;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t mDefaultSampleSize;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t mDefaultSampleFlags;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint64_t mDataOffset;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    TrackFragmentHeaderInfo mTrackFragmentHeaderInfo;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    struct Sample {
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        off64_t offset;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        size_t size;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint32_t duration;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int32_t compositionOffset;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        uint8_t iv[16];
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Vector<size_t> clearsizes;
1517c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        Vector<size_t> encryptedsizes;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Vector<Sample> mCurrentSamples;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MPEG4Source(const MPEG4Source &);
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    MPEG4Source &operator=(const MPEG4Source &);
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1595b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski// This custom data source wraps an existing one and satisfies requests
1605b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski// falling entirely within a cached range from the cache while forwarding
16137c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn// all remaining requests to the wrapped datasource.
1625b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski// This is used to cache the full sampletable metadata for a single track,
1635b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski// possibly wrapping multiple times to cover all tracks, i.e.
1645b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski// Each MPEG4DataSource caches the sampletable metadata for a single track.
1655b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
16637c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackbornstruct MPEG4DataSource : public DataSource {
1675b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    MPEG4DataSource(const sp<DataSource> &source);
1685b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
1695b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    virtual status_t initCheck() const;
1705b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
171cb4285537b1bf67b5a248e509d5fe41a6f49282eDianne Hackborn    virtual status_t getSize(off64_t *size);
172cb4285537b1bf67b5a248e509d5fe41a6f49282eDianne Hackborn    virtual uint32_t flags();
1735b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
1745b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    status_t setCachedRange(off64_t offset, size_t size);
1755b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
176cb4285537b1bf67b5a248e509d5fe41a6f49282eDianne Hackbornprotected:
1775b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    virtual ~MPEG4DataSource();
17837c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
17937c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackbornprivate:
1805b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    Mutex mLock;
1815b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
1820c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross    sp<DataSource> mSource;
1835b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    off64_t mCachedOffset;
1845b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    size_t mCachedSize;
1855b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    uint8_t *mCache;
18637c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
1875b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    void clearCache();
1885b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
1890c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross    MPEG4DataSource(const MPEG4DataSource &);
1905b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    MPEG4DataSource &operator=(const MPEG4DataSource &);
1915b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski};
1925b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
19337c99432625e2adeb50baf25f471abc8481b2b3eDianne HackbornMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source)
1945b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    : mSource(source),
1955b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski      mCachedOffset(0),
1960c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross      mCachedSize(0),
1975b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski      mCache(NULL) {
1985b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski}
1995b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
20037c99432625e2adeb50baf25f471abc8481b2b3eDianne HackbornMPEG4DataSource::~MPEG4DataSource() {
2015b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    clearCache();
2025b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski}
20337c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
2045b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinskivoid MPEG4DataSource::clearCache() {
2055b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    if (mCache) {
2065b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        free(mCache);
2075b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        mCache = NULL;
2085b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    }
2095b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
2105b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    mCachedOffset = 0;
21137c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn    mCachedSize = 0;
21237c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn}
2135b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
2145b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinskistatus_t MPEG4DataSource::initCheck() const {
215cb4285537b1bf67b5a248e509d5fe41a6f49282eDianne Hackborn    return mSource->initCheck();
2165b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski}
2175b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
21837c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackbornssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
2195b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    Mutex::Autolock autoLock(mLock);
2205b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
2215b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    if (offset >= mCachedOffset
22237c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn            && offset + size <= mCachedOffset + mCachedSize) {
22337c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn        memcpy(data, &mCache[offset - mCachedOffset], size);
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return size;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2270e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    return mSource->readAt(offset, data, size);
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2303c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloumstatus_t MPEG4DataSource::getSize(off64_t *size) {
2313c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    return mSource->getSize(size);
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2348883ced18ac25199330843964634fdf70647a127Dianne Hackbornuint32_t MPEG4DataSource::flags() {
2353c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    return mSource->flags();
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) {
2390c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross    Mutex::Autolock autoLock(mLock);
2400c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross
2410c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross    clearCache();
2420e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
2430e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    mCache = (uint8_t *)malloc(size);
2440e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
2450e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    if (mCache == NULL) {
2463c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        return -ENOMEM;
2470e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2490e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    mCachedOffset = offset;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mCachedSize = size;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2520e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize);
2530e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
2540e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    if (err < (ssize_t)size) {
2553c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        clearCache();
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2573c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        return ERROR_IO;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return OK;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2630c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross////////////////////////////////////////////////////////////////////////////////
2640e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
2650e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstatic void hexdump(const void *_data, size_t size) {
2660e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    const uint8_t *data = (const uint8_t *)_data;
2670e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    size_t offset = 0;
2680e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    while (offset < size) {
2690e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        printf("0x%04zx  ", offset);
2700e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
2710e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        size_t n = size - offset;
27264770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn        if (n > 16) {
2730e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            n = 16;
27464770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn        }
27564770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn
27664770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn        for (size_t i = 0; i < 16; ++i) {
27764770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn            if (i == 8) {
27864770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn                printf(" ");
279eee9764418d13176c9671e453775d476c2206f6cMathieu Chartier            }
28025c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier
281eee9764418d13176c9671e453775d476c2206f6cMathieu Chartier            if (offset + i < size) {
282eee9764418d13176c9671e453775d476c2206f6cMathieu Chartier                printf("%02x ", data[offset + i]);
283eee9764418d13176c9671e453775d476c2206f6cMathieu Chartier            } else {
284eee9764418d13176c9671e453775d476c2206f6cMathieu Chartier                printf("   ");
28564770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn            }
28664770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn        }
28725c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier
28825c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier        printf(" ");
28925c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier
29025c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier        for (size_t i = 0; i < n; ++i) {
29125c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier            if (isprint(data[offset + i])) {
29225c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier                printf("%c", data[offset + i]);
29325c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier            } else {
29425c5e2b12d5d5d06739e3f70a0da968d97935b46Mathieu Chartier                printf(".");
29564770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn            }
29664770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn        }
29764770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn
298eee9764418d13176c9671e453775d476c2206f6cMathieu Chartier        printf("\n");
29964770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn
30064770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn        offset += 16;
30164770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn    }
30264770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn}
30364770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn
30464770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackbornstatic const char *FourCC2MIME(uint32_t fourcc) {
30564770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn    switch (fourcc) {
30664770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn        case FOURCC('m', 'p', '4', 'a'):
307cb4728f247e3793e7fc1baa031290aa732bb77a7Colin Cross            return MEDIA_MIMETYPE_AUDIO_AAC;
3080e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
30964770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn        case FOURCC('s', 'a', 'm', 'r'):
3107c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
31164770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn
312184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn        case FOURCC('s', 'a', 'w', 'b'):
313184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
314184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn
315184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn        case FOURCC('m', 'p', '4', 'v'):
316184293076201ec510898f8d505a8fe50458d9604Dianne Hackborn            return MEDIA_MIMETYPE_VIDEO_MPEG4;
3170e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
3180e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        case FOURCC('s', '2', '6', '3'):
3193c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        case FOURCC('h', '2', '6', '3'):
3200e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        case FOURCC('H', '2', '6', '3'):
3210e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            return MEDIA_MIMETYPE_VIDEO_H263;
3223c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
3230e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        case FOURCC('a', 'v', 'c', '1'):
3240e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            return MEDIA_MIMETYPE_VIDEO_AVC;
3253c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
3260e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        case FOURCC('h', 'v', 'c', '1'):
3270e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        case FOURCC('h', 'e', 'v', '1'):
3283c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum            return MEDIA_MIMETYPE_VIDEO_HEVC;
3299f8589c31f8910a9c3c33a81675822da9f0cf2dfIan Rogers        default:
3309f8589c31f8910a9c3c33a81675822da9f0cf2dfIan Rogers            CHECK(!"should not be here.");
3310e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            return NULL;
3323c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    }
3338884ef4fe80505bc6e41c167b67efbb93e43475dAnwar Ghuloum}
3348884ef4fe80505bc6e41c167b67efbb93e43475dAnwar Ghuloum
3353c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloumstatic bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) {
33688887d0a53f866e61a7524b0edfc95e6dde57d72Anwar Ghuloum    if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) {
33788887d0a53f866e61a7524b0edfc95e6dde57d72Anwar Ghuloum        // AMR NB audio is always mono, 8kHz
3383c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        *channels = 1;
339cb4728f247e3793e7fc1baa031290aa732bb77a7Colin Cross        *rate = 8000;
340cb4728f247e3793e7fc1baa031290aa732bb77a7Colin Cross        return true;
3410e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) {
3420e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        // AMR WB audio is always mono, 16kHz
3430e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        *channels = 1;
3440e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        *rate = 16000;
3450e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        return true;
3460e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return false;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3496215d3ff4b5dfa52a5d8b9a42e343051f31066a5Steve Block
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
3517c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    : mMoofOffset(0),
3528883ced18ac25199330843964634fdf70647a127Dianne Hackborn      mDataSource(source),
3538883ced18ac25199330843964634fdf70647a127Dianne Hackborn      mInitCheck(NO_INIT),
3548883ced18ac25199330843964634fdf70647a127Dianne Hackborn      mHasVideo(false),
3558883ced18ac25199330843964634fdf70647a127Dianne Hackborn      mHeaderTimescale(0),
3568883ced18ac25199330843964634fdf70647a127Dianne Hackborn      mFirstTrack(NULL),
3578883ced18ac25199330843964634fdf70647a127Dianne Hackborn      mLastTrack(NULL),
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mFileMetaData(new MetaData),
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mFirstSINF(NULL),
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project      mIsDrm(false) {
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source ProjectMPEG4Extractor::~MPEG4Extractor() {
3648883ced18ac25199330843964634fdf70647a127Dianne Hackborn    Track *track = mFirstTrack;
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (track) {
3668883ced18ac25199330843964634fdf70647a127Dianne Hackborn        Track *next = track->next;
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3688883ced18ac25199330843964634fdf70647a127Dianne Hackborn        delete track;
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        track = next;
3708883ced18ac25199330843964634fdf70647a127Dianne Hackborn    }
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    mFirstTrack = mLastTrack = NULL;
3728883ced18ac25199330843964634fdf70647a127Dianne Hackborn
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SINF *sinf = mFirstSINF;
3748883ced18ac25199330843964634fdf70647a127Dianne Hackborn    while (sinf) {
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SINF *next = sinf->next;
3768883ced18ac25199330843964634fdf70647a127Dianne Hackborn        delete[] sinf->IPMPData;
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete sinf;
3788883ced18ac25199330843964634fdf70647a127Dianne Hackborn        sinf = next;
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3808883ced18ac25199330843964634fdf70647a127Dianne Hackborn    mFirstSINF = NULL;
3818883ced18ac25199330843964634fdf70647a127Dianne Hackborn
3820c6bc73c5e12dd4caae5bf3acbf1d26c3a9ad130Colin Cross    for (size_t i = 0; i < mPssh.size(); i++) {
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        delete [] mPssh[i].data;
384bd51116a5310683f70a37110bf735252dc7e4e38Grace Kloba    }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectuint32_t MPEG4Extractor::flags() const {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return CAN_PAUSE |
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ((mMoofOffset == 0 || mSidxEntries.size() != 0) ?
3903c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                    (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
3913c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum}
3923c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
3938883ced18ac25199330843964634fdf70647a127Dianne Hackbornsp<MetaData> MPEG4Extractor::getMetaData() {
3948883ced18ac25199330843964634fdf70647a127Dianne Hackborn    status_t err;
3953c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    if ((err = readMetaData()) != OK) {
3963c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        return new MetaData;
3973c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    }
3983c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
3993c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    return mFileMetaData;
4000e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn}
4013c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
4020e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornsize_t MPEG4Extractor::countTracks() {
4030e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    status_t err;
4043c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    if ((err = readMetaData()) != OK) {
4053a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum        ALOGV("MPEG4Extractor::countTracks: no tracks");
4068883ced18ac25199330843964634fdf70647a127Dianne Hackborn        return 0;
40764770d16b0907a8e1ee81ef6c8fa398a6bdbee79Dianne Hackborn    }
4083c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
4093c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    size_t n = 0;
4103c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    Track *track = mFirstTrack;
4113c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    while (track) {
4123c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        ++n;
4133c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        track = track->next;
4148883ced18ac25199330843964634fdf70647a127Dianne Hackborn    }
4153c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ALOGV("MPEG4Extractor::countTracks: %zu tracks", n);
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return n;
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectsp<MetaData> MPEG4Extractor::getTrackMetaData(
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        size_t index, uint32_t flags) {
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    status_t err;
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if ((err = readMetaData()) != OK) {
4247c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        return NULL;
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Track *track = mFirstTrack;
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    while (index > 0) {
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (track == NULL) {
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return NULL;
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4333025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn        track = track->next;
4343025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn        --index;
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4360e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
4370e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    if (track == NULL) {
4387c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        return NULL;
4390e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
4400e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
4415b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski    if ((flags & kIncludeExtensiveMetaData)
4425b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski            && !track->includes_expensive_metadata) {
4435b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        track->includes_expensive_metadata = true;
4445b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
4455b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        const char *mime;
4465b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        CHECK(track->meta->findCString(kKeyMIMEType, &mime));
4475b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski        if (!strncasecmp("video/", mime, 6)) {
4485b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski            if (mMoofOffset > 0) {
4495b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski                int64_t duration;
45037c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                if (track->meta->findInt64(kKeyDuration, &duration)) {
4513c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                    // nothing fancy, just pick a frame near 1/4th of the duration
4520e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                    track->meta->setInt64(
4533c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                            kKeyThumbnailTime, duration / 4);
4540e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                }
4550e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            } else {
4563c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                uint32_t sampleIndex;
4573a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum                uint32_t sampleTime;
4588883ced18ac25199330843964634fdf70647a127Dianne Hackborn                if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK
4590e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                        && track->sampleTable->getMetaDataForSample(
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            sampleIndex, NULL /* offset */, NULL /* size */,
4610e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                            &sampleTime) == OK) {
4620e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                    track->meta->setInt64(
4633c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                            kKeyThumbnailTime,
4640e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                            ((int64_t)sampleTime * 1000000) / track->timescale);
4650e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                }
4663c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum            }
4673a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum        }
4688883ced18ac25199330843964634fdf70647a127Dianne Hackborn    }
4690e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
4707c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers    return track->meta;
4713c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum}
4720e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
4737c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogersstatic void MakeFourCCString(uint32_t x, char *s) {
4740e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    s[0] = x >> 24;
4750e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    s[1] = (x >> 16) & 0xff;
4760e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    s[2] = (x >> 8) & 0xff;
4770e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    s[3] = x & 0xff;
4780e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    s[4] = '\0';
4790e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn}
4800e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn
4810e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackbornstatus_t MPEG4Extractor::readMetaData() {
4823c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum    if (mInitCheck != NO_INIT) {
4830e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        return mInitCheck;
4840e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    }
4853c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
4863a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum    off64_t offset = 0;
4878883ced18ac25199330843964634fdf70647a127Dianne Hackborn    status_t err;
4880e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn    while (true) {
4890e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        off64_t orig_offset = offset;
4900e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        err = parseChunk(&offset, 0);
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (err != OK && err != UNKNOWN_ERROR) {
4933025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn            break;
4943025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn        } else if (offset <= orig_offset) {
4953025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn            // only continue parsing if the offset was advanced,
4963025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn            // otherwise we might end up in an infinite loop
4973025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn            ALOGE("did not advance: 0x%lld->0x%lld", orig_offset, offset);
4981a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn            err = ERROR_MALFORMED;
4991a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn            break;
500b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        } else if (err == OK) {
501b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn            continue;
502b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        }
503c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn
5041a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn        uint32_t hdr[2];
505b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        if (mDataSource->readAt(offset, hdr, 8) < 8) {
506b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn            break;
507b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        }
508b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        uint32_t chunk_type = ntohl(hdr[1]);
509b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
5105b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski            // store the offset of the first segment
5115b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski            mMoofOffset = offset;
5121a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn        } else if (chunk_type != FOURCC('m', 'd', 'a', 't')) {
5135b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski            // keep parsing until we get to the data
51437c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn            continue;
515b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        }
516b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        break;
517b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    }
51837c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
51937c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn    if (mInitCheck == OK) {
52037c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn        if (mHasVideo) {
52137c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn            mFileMetaData->setCString(
52237c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn                    kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
523b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        } else {
52437c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn            mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
52537c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn        }
52637c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn    } else {
52737c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn        mInitCheck = err;
52837c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn    }
52937c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn
53037c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn    CHECK_NE(err, (status_t)NO_INIT);
53145838de942b87150fc3b03a8b943841a8647fd81Iliyan Malchev
53245838de942b87150fc3b03a8b943841a8647fd81Iliyan Malchev    // copy pssh data into file metadata
53337c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn    int psshsize = 0;
53437c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn    for (size_t i = 0; i < mPssh.size(); i++) {
53537c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn        psshsize += 20 + mPssh[i].datalen;
53637c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn    }
53737c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn    if (psshsize) {
538c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn        char *buf = (char*)malloc(psshsize);
539cfc837f7fa43362b5049f648fe1bfdf5a010cc1cDianne Hackborn        char *ptr = buf;
540b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        for (size_t i = 0; i < mPssh.size(); i++) {
541b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn            memcpy(ptr, mPssh[i].uuid, 20); // uuid + length
54237c99432625e2adeb50baf25f471abc8481b2b3eDianne Hackborn            memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen);
543b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn            ptr += (20 + mPssh[i].datalen);
544b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        }
545c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn        mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize);
546c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn        free(buf);
547c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn    }
548c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn    return mInitCheck;
549c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn}
550c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn
551c8230519728b14065effd3b7d4eca273ff86160cDianne Hackbornchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) {
552c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn    if (mFirstSINF == NULL) {
553c8230519728b14065effd3b7d4eca273ff86160cDianne Hackborn        return NULL;
554b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    }
5551a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn
5561a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn    SINF *sinf = mFirstSINF;
5571a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn    while (sinf && (trackID != sinf->trackID)) {
5581a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn        sinf = sinf->next;
5591a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn    }
5601a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn
5611a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn    if (sinf == NULL) {
5621a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn        return NULL;
5631a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn    }
5641a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn
565b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    *len = sinf->len;
566b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    return sinf->IPMPData;
567b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn}
568b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn
569b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn// Reads an encoded integer 7 bits at a time until it encounters the high bit clear.
5701a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackbornstatic int32_t readSize(off64_t offset,
571b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn        const sp<DataSource> DataSource, uint8_t *numOfBytes) {
572b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn    uint32_t size = 0;
573cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    uint8_t data;
574cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    bool moreData = true;
575cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    *numOfBytes = 0;
576cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn
577cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    while (moreData) {
578cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        if (DataSource->readAt(offset, &data, 1) < 1) {
579cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            return -1;
580cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        }
581cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        offset ++;
582cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        moreData = (data >= 128) ? true : false;
583b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn        size = (size << 7) | (data & 0x7f); // Take last 7 bits
584b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn        (*numOfBytes) ++;
585b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn    }
586b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn
587cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    return size;
588cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn}
589cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn
5908e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackbornstatus_t MPEG4Extractor::parseDrmSINF(
5918e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        off64_t * /* offset */, off64_t data_offset) {
5928e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    uint8_t updateIdTag;
5938e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
5948e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        return ERROR_IO;
5958e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
5968e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    data_offset ++;
5978e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
5988e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
5998e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        return ERROR_MALFORMED;
6008e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
6018e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6028e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    uint8_t numOfBytes;
603cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    int32_t size = readSize(data_offset, mDataSource, &numOfBytes);
6048e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    if (size < 0) {
6058e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        return ERROR_IO;
6068e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
607cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn    int32_t classSize = size;
6088e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    data_offset += numOfBytes;
6098e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6108e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    while(size >= 11 ) {
611cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        uint8_t descriptorTag;
6128e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) {
6138e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            return ERROR_IO;
6148e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        }
6158e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        data_offset ++;
6168e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6178e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) {
6188e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            return ERROR_MALFORMED;
6198e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        }
6208e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6218e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        uint8_t buffer[8];
6228e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        //ObjectDescriptorID and ObjectDescriptor url flag
623cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        if (mDataSource->readAt(data_offset, buffer, 2) < 2) {
624cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            return ERROR_IO;
625b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn        }
626b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn        data_offset += 2;
627b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn
628b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn        if ((buffer[1] >> 5) & 0x0001) { //url flag is set
629b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn            return ERROR_MALFORMED;
6308e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        }
6318e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6328e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        if (mDataSource->readAt(data_offset, buffer, 8) < 8) {
6338e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            return ERROR_IO;
6348e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        }
6358e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        data_offset += 8;
6368e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6378e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1])
6388e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) {
639cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            return ERROR_MALFORMED;
640cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        }
641b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn
642b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn        SINF *sinf = new SINF;
643b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn        sinf->trackID = U16_AT(&buffer[3]);
644b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn        sinf->IPMPDescriptorID = buffer[7];
645b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn        sinf->next = mFirstSINF;
6468e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        mFirstSINF = sinf;
6478e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
648b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn        size -= (8 + 2 + 1);
6498e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
6508e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
651b3af4ec6bae4fe93d40f021e54cbbce10cc7b4c6Dianne Hackborn    if (size != 0) {
6528e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        return ERROR_MALFORMED;
6538e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
6548e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6558e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) {
6568e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        return ERROR_IO;
6578e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
6588e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    data_offset ++;
6598e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6608e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) {
6618e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        return ERROR_MALFORMED;
6628e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
6638e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6648e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    size = readSize(data_offset, mDataSource, &numOfBytes);
6658e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    if (size < 0) {
6668e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        return ERROR_IO;
6678e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    }
6688e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    classSize = size;
6698e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    data_offset += numOfBytes;
6708e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6718e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn    while (size > 0) {
6728e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        uint8_t tag;
6738e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        int32_t dataLen;
6748e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn        if (mDataSource->readAt(data_offset, &tag, 1) < 1) {
675cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            return ERROR_IO;
676cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        }
677cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        data_offset ++;
678cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn
679cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn        if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) {
680cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            uint8_t id;
681cb4285537b1bf67b5a248e509d5fe41a6f49282eDianne Hackborn            dataLen = readSize(data_offset, mDataSource, &numOfBytes);
682cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            if (dataLen < 0) {
683cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn                return ERROR_IO;
684cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            } else if (dataLen < 4) {
6858e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                return ERROR_MALFORMED;
686cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            }
687cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn            data_offset += numOfBytes;
688cbd9a52f256087426feb19ac6e51eff772e81375Dianne Hackborn
6898e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            if (mDataSource->readAt(data_offset, &id, 1) < 1) {
6908e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                return ERROR_IO;
691cb4285537b1bf67b5a248e509d5fe41a6f49282eDianne Hackborn            }
6928e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            data_offset ++;
6938e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn
6948e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            SINF *sinf = mFirstSINF;
6958e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn            while (sinf && (sinf->IPMPDescriptorID != id)) {
696b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn                sinf = sinf->next;
697b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn            }
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sinf == NULL) {
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return ERROR_MALFORMED;
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sinf->len = dataLen - 3;
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sinf->IPMPData = new (std::nothrow) char[sinf->len];
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sinf->IPMPData == NULL) {
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return ERROR_MALFORMED;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            data_offset += 2;
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) {
7097c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers                return ERROR_IO;
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            data_offset += sinf->len;
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
713c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes            size -= (dataLen + numOfBytes + 1);
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    if (size != 0) {
7187c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        return ERROR_MALFORMED;
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7207c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return UNKNOWN_ERROR;  // Return a dummy error.
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
723c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct PathAdder {
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    PathAdder(Vector<uint32_t> *path, uint32_t chunkType)
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        : mPath(path) {
7277c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        mPath->push(chunkType);
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
730c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes    ~PathAdder() {
731c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes        mPath->pop();
732c367d48c55e5a3fa0df14fd62889e4bb6b63cb01Elliott Hughes    }
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectprivate:
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Vector<uint32_t> *mPath;
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    PathAdder(const PathAdder &);
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    PathAdder &operator=(const PathAdder &);
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project};
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic bool underMetaDataPath(const Vector<uint32_t> &path) {
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    return path.size() >= 5
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        && path[0] == FOURCC('m', 'o', 'o', 'v')
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        && path[1] == FOURCC('u', 'd', 't', 'a')
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        && path[2] == FOURCC('m', 'e', 't', 'a')
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        && path[3] == FOURCC('i', 'l', 's', 't');
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project// Given a time in seconds since Jan 1 1904, produce a human-readable string.
75006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatic void convertTimeToDate(int64_t time_1904, String8 *s) {
75106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600);
75206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
75306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    char tmp[32];
75406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970));
75506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
75606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    s->setTo(tmp);
75706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden}
75806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
75906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFaddenstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
76006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    ALOGV("entering parseChunk %lld/%d", *offset, depth);
76106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    uint32_t hdr[2];
76206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
76306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return ERROR_IO;
76406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
76506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    uint64_t chunk_size = ntohl(hdr[0]);
76606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    uint32_t chunk_type = ntohl(hdr[1]);
76706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    off64_t data_offset = *offset + 8;
76806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
76906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (chunk_size == 1) {
77006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
77106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            return ERROR_IO;
77206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
77306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        chunk_size = ntoh64(chunk_size);
77406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        data_offset += 8;
77506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
77606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        if (chunk_size < 16) {
77706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            // The smallest valid chunk is 16 bytes long in this case.
77806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            return ERROR_MALFORMED;
77906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
78006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    } else if (chunk_size == 0) {
78106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        if (depth == 0) {
78206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            // atom extends to end of file
78306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            off64_t sourceSize;
78406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            if (mDataSource->getSize(&sourceSize) == OK) {
78506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                chunk_size = (sourceSize - *offset);
78606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            } else {
78706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                // XXX could we just pick a "sufficiently large" value here?
78806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                ALOGE("atom size is 0, and data source has no size");
78906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                return ERROR_MALFORMED;
79006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            }
79106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        } else {
79206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            // not allowed for non-toplevel atoms, skip it
79306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            *offset += 4;
79406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            return OK;
79506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
79606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    } else if (chunk_size < 8) {
79706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        // The smallest valid chunk is 8 bytes long.
79806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        ALOGE("invalid chunk size: %" PRIu64, chunk_size);
79906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return ERROR_MALFORMED;
80006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
80106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
80206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    char chunk[5];
80306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    MakeFourCCString(chunk_type, chunk);
80406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth);
80506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
80606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#if 0
80706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    static const char kWhitespace[] = "                                        ";
80806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
80906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    printf("%sfound chunk '%s' of size %" PRIu64 "\n", indent, chunk, chunk_size);
81006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
81106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    char buffer[256];
81206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    size_t n = chunk_size;
81306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (n > sizeof(buffer)) {
81406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        n = sizeof(buffer);
81506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
81606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (mDataSource->readAt(*offset, buffer, n)
81706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            < (ssize_t)n) {
81806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return ERROR_IO;
81906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
82006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
82106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    hexdump(buffer, n);
82206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden#endif
82306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
82406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    PathAdder autoAdder(&mPath, chunk_type);
82506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
82606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    off64_t chunk_data_size = *offset + chunk_size - data_offset;
82706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
82806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    if (chunk_type != FOURCC('c', 'p', 'r', 't')
82906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            && chunk_type != FOURCC('c', 'o', 'v', 'r')
83006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            && mPath.size() == 5 && underMetaDataPath(mPath)) {
83106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        off64_t stop_offset = *offset + chunk_size;
83206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        *offset = data_offset;
83306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        while (*offset < stop_offset) {
83406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            status_t err = parseChunk(offset, depth + 1);
83506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            if (err != OK) {
83606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                return err;
83706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            }
838f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat        }
83906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
84006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        if (*offset != stop_offset) {
84106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            return ERROR_MALFORMED;
84206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        }
84306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
84406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        return OK;
84506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    }
84606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
84706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden    switch(chunk_type) {
84806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('m', 'o', 'o', 'v'):
84906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('t', 'r', 'a', 'k'):
85006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('m', 'd', 'i', 'a'):
85106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('m', 'i', 'n', 'f'):
85206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('d', 'i', 'n', 'f'):
85306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('s', 't', 'b', 'l'):
85406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('m', 'v', 'e', 'x'):
85506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('m', 'o', 'o', 'f'):
85606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('t', 'r', 'a', 'f'):
85706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('m', 'f', 'r', 'a'):
85806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('u', 'd', 't', 'a'):
85906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('i', 'l', 's', 't'):
86006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden        case FOURCC('s', 'i', 'n', 'f'):
861f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat        case FOURCC('s', 'c', 'h', 'i'):
862853940331ff2be48ed3e63f459845e5e43d0a131Mark Salyzyn        case FOURCC('e', 'd', 't', 's'):
863f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat        {
864853940331ff2be48ed3e63f459845e5e43d0a131Mark Salyzyn            if (chunk_type == FOURCC('s', 't', 'b', 'l')) {
865f5df700e6ce056ebfa322314d970e52d6facc35aAshok Bhat                ALOGV("sampleTable chunk is %" PRIu64 " bytes long.", chunk_size);
86606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
86706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                if (mDataSource->flags()
86806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                        & (DataSource::kWantsPrefetching
86906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                            | DataSource::kIsCachingDataSource)) {
87006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    sp<MPEG4DataSource> cachedSource =
87106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                        new MPEG4DataSource(mDataSource);
87206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
87306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    if (cachedSource->setCachedRange(*offset, chunk_size) == OK) {
874393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom                        mDataSource = cachedSource;
875393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom                    }
876393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom                }
877393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom
878393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom                mLastTrack->sampleTable = new SampleTable(mDataSource);
879393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom            }
880393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom
881393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom            bool isTrack = false;
882393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom            if (chunk_type == FOURCC('t', 'r', 'a', 'k')) {
883393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom                isTrack = true;
884393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom
885393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom                Track *track = new Track;
886393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom                track->next = NULL;
887393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom                if (mLastTrack) {
888393b84c137fe52f42205cef7e63b7a04b4bfd789Brian Carlstrom                    mLastTrack->next = track;
88906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                } else {
89006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    mFirstTrack = track;
89106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                }
89206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                mLastTrack = track;
89306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
89406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                track->meta = new MetaData;
89506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                track->includes_expensive_metadata = false;
89606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                track->skipTrack = false;
89706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                track->timescale = 0;
89806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                track->meta->setCString(kKeyMIMEType, "application/octet-stream");
8997c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers            }
90006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
90106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            off64_t stop_offset = *offset + chunk_size;
90206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            *offset = data_offset;
90306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            while (*offset < stop_offset) {
90406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                status_t err = parseChunk(offset, depth + 1);
90506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                if (err != OK) {
90606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    return err;
90706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                }
90806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            }
90906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
91006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            if (*offset != stop_offset) {
9118564c8da817a845353d213acd8636b76f567b234Steve Block                return ERROR_MALFORMED;
91206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            }
91306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
91406a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            if (isTrack) {
91506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                if (mLastTrack->skipTrack) {
91606a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    Track *cur = mFirstTrack;
91706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
9188564c8da817a845353d213acd8636b76f567b234Steve Block                    if (cur == mLastTrack) {
91906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                        delete cur;
92006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                        mFirstTrack = mLastTrack = NULL;
92106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    } else {
92206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                        while (cur && cur->next != mLastTrack) {
92306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                            cur = cur->next;
9245baa3a62a97544669fba6d65a11c07f252e654ddSteve Block                        }
92506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                        cur->next = NULL;
9265baa3a62a97544669fba6d65a11c07f252e654ddSteve Block                        delete mLastTrack;
92706a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                        mLastTrack = cur;
92806a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    }
92906a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden
93006a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    return OK;
93106a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                }
932f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
933f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn                status_t err = verifyTrack(mLastTrack);
934f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
935f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn                if (err != OK) {
9367c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers                    return err;
937f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn                }
938f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn            } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
939f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn                mInitCheck = OK;
940f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
941f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn                if (!mIsDrm) {
942f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn                    return UNKNOWN_ERROR;  // Return a dummy error.
943f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn                } else {
944f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn                    return OK;
945f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn                }
946f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn            }
947f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn            break;
948f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        }
949f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
950f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        case FOURCC('e', 'l', 's', 't'):
951f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn        {
952f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn            *offset += chunk_size;
953f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
954f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn            // See 14496-12 8.6.6
955f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn            uint8_t version;
956f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
957f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn                return ERROR_IO;
958f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn            }
959f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn
960f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn            uint32_t entry_count;
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) {
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return ERROR_IO;
9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (entry_count != 1) {
9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // we only support a single entry at the moment, for gapless playback
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ALOGW("ignoring edit list with %d entries", entry_count);
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (mHeaderTimescale == 0) {
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ALOGW("ignoring edit list because timescale is 0");
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                off64_t entriesoffset = data_offset + 8;
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                uint64_t segment_duration;
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int64_t media_time;
9743025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn
9753025ef332c29e255388f74b2afefe05f64bce07cDianne Hackborn                if (version == 1) {
976b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn                    if (!mDataSource->getUInt64(entriesoffset, &segment_duration) ||
977b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn                            !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) {
9781a4b5a4f02e7d8ff8ff645377d97e6062d36aeaaDianne Hackborn                        return ERROR_IO;
979b437e090ec03a2bab10bdfcb9484577a7f34e157Dianne Hackborn                    }
9808e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                } else if (version == 0) {
9818e69257a9c7e9c1781e1f53d8856358ada38921dDianne Hackborn                    uint32_t sd;
98206a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    int32_t mt;
98306a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden                    if (!mDataSource->getUInt32(entriesoffset, &sd) ||
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) {
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return ERROR_IO;
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    segment_duration = sd;
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    media_time = mt;
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return ERROR_IO;
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                uint64_t halfscale = mHeaderTimescale / 2;
994f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn                segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale;
995f72467ad9843bf5d4b75fb308386e77ebb5c3447Dianne Hackborn                media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale;
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int64_t duration;
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int32_t samplerate;
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mLastTrack->meta->findInt64(kKeyDuration, &duration) &&
10005b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski                        mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) {
10015b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
10025b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski                    int64_t delay = (media_time  * samplerate + 500000) / 1000000;
10035b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski                    mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
10045b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski
10055b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski                    int64_t paddingus = duration - (segment_duration + media_time);
10065b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski                    if (paddingus < 0) {
10075b4ef81f2b79dd5d597b1681de4d0311d46693aaAdam Lesinski                        // track duration from media header (which is what kKeyDuration is) might
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be slightly shorter than the segment duration, which would make the
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // padding negative. Clamp to zero.
10107c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers                        paddingus = 0;
10117c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers                    }
10127c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers                    int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000;
10133c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                    mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples);
10143c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                }
10157c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers            }
10163c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum            break;
10177c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        }
10183c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum
10193c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum        case FOURCC('f', 'r', 'm', 'a'):
10207c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers        {
10217c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers            *offset += chunk_size;
10227c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers
10237c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers            uint32_t original_fourcc;
10247c9f30bfb361ccb864e6d130e0f4f2af53fc1c32Ian Rogers            if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) {
10250e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                return ERROR_IO;
10260e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            }
10270e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            original_fourcc = ntohl(original_fourcc);
10283c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum            ALOGV("read original format: %d", original_fourcc);
10293c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc));
10300e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            uint32_t num_channels = 0;
10310e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            uint32_t sample_rate = 0;
10320e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) {
10330e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn                mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
10343c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum                mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
10353c61506b7147e13b9d39fc07fb189504fcab4541Anwar Ghuloum            }
10363a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum            break;
10373a8ce1bec819c9b104880493a6862fd2a9546132Anwar Ghuloum        }
10388883ced18ac25199330843964634fdf70647a127Dianne Hackborn
10398883ced18ac25199330843964634fdf70647a127Dianne Hackborn        case FOURCC('t', 'e', 'n', 'c'):
10400e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn        {
10410e3328fbdd3845b0e2bec364e951498eaee6b079Dianne Hackborn            *offset += chunk_size;
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (chunk_size < 32) {
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return ERROR_MALFORMED;
104506a6b558bd03d8f0fed8f94f1dcfc03c5a51bd1cAndy McFadden            }
1046
1047            // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte
1048            // default IV size, 16 bytes default KeyID
1049            // (ISO 23001-7)
1050            char buf[4];
1051            memset(buf, 0, 4);
1052            if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) {
1053                return ERROR_IO;
1054            }
1055            uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf));
1056            if (defaultAlgorithmId > 1) {
1057                // only 0 (clear) and 1 (AES-128) are valid
1058                return ERROR_MALFORMED;
1059            }
1060
1061            memset(buf, 0, 4);
1062            if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) {
1063                return ERROR_IO;
1064            }
1065            uint32_t defaultIVSize = ntohl(*((int32_t*)buf));
1066
1067            if ((defaultAlgorithmId == 0 && defaultIVSize != 0) ||
1068                    (defaultAlgorithmId != 0 && defaultIVSize == 0)) {
1069                // only unencrypted data must have 0 IV size
1070                return ERROR_MALFORMED;
1071            } else if (defaultIVSize != 0 &&
1072                    defaultIVSize != 8 &&
1073                    defaultIVSize != 16) {
1074                // only supported sizes are 0, 8 and 16
1075                return ERROR_MALFORMED;
1076            }
1077
1078            uint8_t defaultKeyId[16];
1079
1080            if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) {
1081                return ERROR_IO;
1082            }
1083
1084            mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId);
1085            mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize);
1086            mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16);
1087            break;
1088        }
1089
1090        case FOURCC('t', 'k', 'h', 'd'):
1091        {
1092            *offset += chunk_size;
1093
1094            status_t err;
1095            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
1096                return err;
1097            }
1098
1099            break;
1100        }
1101
1102        case FOURCC('p', 's', 's', 'h'):
1103        {
1104            *offset += chunk_size;
1105
1106            PsshInfo pssh;
1107
1108            if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) {
1109                return ERROR_IO;
1110            }
1111
1112            uint32_t psshdatalen = 0;
1113            if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) {
1114                return ERROR_IO;
1115            }
1116            pssh.datalen = ntohl(psshdatalen);
1117            ALOGV("pssh data size: %d", pssh.datalen);
1118            if (pssh.datalen + 20 > chunk_size) {
1119                // pssh data length exceeds size of containing box
1120                return ERROR_MALFORMED;
1121            }
1122
1123            pssh.data = new (std::nothrow) uint8_t[pssh.datalen];
1124            if (pssh.data == NULL) {
1125                return ERROR_MALFORMED;
1126            }
1127            ALOGV("allocated pssh @ %p", pssh.data);
1128            ssize_t requested = (ssize_t) pssh.datalen;
1129            if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) {
1130                return ERROR_IO;
1131            }
1132            mPssh.push_back(pssh);
1133
1134            break;
1135        }
1136
1137        case FOURCC('m', 'd', 'h', 'd'):
1138        {
1139            *offset += chunk_size;
1140
1141            if (chunk_data_size < 4) {
1142                return ERROR_MALFORMED;
1143            }
1144
1145            uint8_t version;
1146            if (mDataSource->readAt(
1147                        data_offset, &version, sizeof(version))
1148                    < (ssize_t)sizeof(version)) {
1149                return ERROR_IO;
1150            }
1151
1152            off64_t timescale_offset;
1153
1154            if (version == 1) {
1155                timescale_offset = data_offset + 4 + 16;
1156            } else if (version == 0) {
1157                timescale_offset = data_offset + 4 + 8;
1158            } else {
1159                return ERROR_IO;
1160            }
1161
1162            uint32_t timescale;
1163            if (mDataSource->readAt(
1164                        timescale_offset, &timescale, sizeof(timescale))
1165                    < (ssize_t)sizeof(timescale)) {
1166                return ERROR_IO;
1167            }
1168
1169            mLastTrack->timescale = ntohl(timescale);
1170
1171            // 14496-12 says all ones means indeterminate, but some files seem to use
1172            // 0 instead. We treat both the same.
1173            int64_t duration = 0;
1174            if (version == 1) {
1175                if (mDataSource->readAt(
1176                            timescale_offset + 4, &duration, sizeof(duration))
1177                        < (ssize_t)sizeof(duration)) {
1178                    return ERROR_IO;
1179                }
1180                if (duration != -1) {
1181                    duration = ntoh64(duration);
1182                }
1183            } else {
1184                uint32_t duration32;
1185                if (mDataSource->readAt(
1186                            timescale_offset + 4, &duration32, sizeof(duration32))
1187                        < (ssize_t)sizeof(duration32)) {
1188                    return ERROR_IO;
1189                }
1190                if (duration32 != 0xffffffff) {
1191                    duration = ntohl(duration32);
1192                }
1193            }
1194            if (duration != 0) {
1195                mLastTrack->meta->setInt64(
1196                        kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
1197            }
1198
1199            uint8_t lang[2];
1200            off64_t lang_offset;
1201            if (version == 1) {
1202                lang_offset = timescale_offset + 4 + 8;
1203            } else if (version == 0) {
1204                lang_offset = timescale_offset + 4 + 4;
1205            } else {
1206                return ERROR_IO;
1207            }
1208
1209            if (mDataSource->readAt(lang_offset, &lang, sizeof(lang))
1210                    < (ssize_t)sizeof(lang)) {
1211                return ERROR_IO;
1212            }
1213
1214            // To get the ISO-639-2/T three character language code
1215            // 1 bit pad followed by 3 5-bits characters. Each character
1216            // is packed as the difference between its ASCII value and 0x60.
1217            char lang_code[4];
1218            lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60;
1219            lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60;
1220            lang_code[2] = (lang[1] & 0x1f) + 0x60;
1221            lang_code[3] = '\0';
1222
1223            mLastTrack->meta->setCString(
1224                    kKeyMediaLanguage, lang_code);
1225
1226            break;
1227        }
1228
1229        case FOURCC('s', 't', 's', 'd'):
1230        {
1231            if (chunk_data_size < 8) {
1232                return ERROR_MALFORMED;
1233            }
1234
1235            uint8_t buffer[8];
1236            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1237                return ERROR_MALFORMED;
1238            }
1239
1240            if (mDataSource->readAt(
1241                        data_offset, buffer, 8) < 8) {
1242                return ERROR_IO;
1243            }
1244
1245            if (U32_AT(buffer) != 0) {
1246                // Should be version 0, flags 0.
1247                return ERROR_MALFORMED;
1248            }
1249
1250            uint32_t entry_count = U32_AT(&buffer[4]);
1251
1252            if (entry_count > 1) {
1253                // For 3GPP timed text, there could be multiple tx3g boxes contain
1254                // multiple text display formats. These formats will be used to
1255                // display the timed text.
1256                // For encrypted files, there may also be more than one entry.
1257                const char *mime;
1258                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1259                if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) &&
1260                        strcasecmp(mime, "application/octet-stream")) {
1261                    // For now we only support a single type of media per track.
1262                    mLastTrack->skipTrack = true;
1263                    *offset += chunk_size;
1264                    break;
1265                }
1266            }
1267            off64_t stop_offset = *offset + chunk_size;
1268            *offset = data_offset + 8;
1269            for (uint32_t i = 0; i < entry_count; ++i) {
1270                status_t err = parseChunk(offset, depth + 1);
1271                if (err != OK) {
1272                    return err;
1273                }
1274            }
1275
1276            if (*offset != stop_offset) {
1277                return ERROR_MALFORMED;
1278            }
1279            break;
1280        }
1281
1282        case FOURCC('m', 'p', '4', 'a'):
1283        case FOURCC('e', 'n', 'c', 'a'):
1284        case FOURCC('s', 'a', 'm', 'r'):
1285        case FOURCC('s', 'a', 'w', 'b'):
1286        {
1287            uint8_t buffer[8 + 20];
1288            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
1289                // Basic AudioSampleEntry size.
1290                return ERROR_MALFORMED;
1291            }
1292
1293            if (mDataSource->readAt(
1294                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
1295                return ERROR_IO;
1296            }
1297
1298            uint16_t data_ref_index = U16_AT(&buffer[6]);
1299            uint32_t num_channels = U16_AT(&buffer[16]);
1300
1301            uint16_t sample_size = U16_AT(&buffer[18]);
1302            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
1303
1304            if (chunk_type != FOURCC('e', 'n', 'c', 'a')) {
1305                // if the chunk type is enca, we'll get the type from the sinf/frma box later
1306                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1307                AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
1308            }
1309            ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
1310                   chunk, num_channels, sample_size, sample_rate);
1311            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
1312            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
1313
1314            off64_t stop_offset = *offset + chunk_size;
1315            *offset = data_offset + sizeof(buffer);
1316            while (*offset < stop_offset) {
1317                status_t err = parseChunk(offset, depth + 1);
1318                if (err != OK) {
1319                    return err;
1320                }
1321            }
1322
1323            if (*offset != stop_offset) {
1324                return ERROR_MALFORMED;
1325            }
1326            break;
1327        }
1328
1329        case FOURCC('m', 'p', '4', 'v'):
1330        case FOURCC('e', 'n', 'c', 'v'):
1331        case FOURCC('s', '2', '6', '3'):
1332        case FOURCC('H', '2', '6', '3'):
1333        case FOURCC('h', '2', '6', '3'):
1334        case FOURCC('a', 'v', 'c', '1'):
1335        case FOURCC('h', 'v', 'c', '1'):
1336        case FOURCC('h', 'e', 'v', '1'):
1337        {
1338            mHasVideo = true;
1339
1340            uint8_t buffer[78];
1341            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
1342                // Basic VideoSampleEntry size.
1343                return ERROR_MALFORMED;
1344            }
1345
1346            if (mDataSource->readAt(
1347                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
1348                return ERROR_IO;
1349            }
1350
1351            uint16_t data_ref_index = U16_AT(&buffer[6]);
1352            uint16_t width = U16_AT(&buffer[6 + 18]);
1353            uint16_t height = U16_AT(&buffer[6 + 20]);
1354
1355            // The video sample is not standard-compliant if it has invalid dimension.
1356            // Use some default width and height value, and
1357            // let the decoder figure out the actual width and height (and thus
1358            // be prepared for INFO_FOMRAT_CHANGED event).
1359            if (width == 0)  width  = 352;
1360            if (height == 0) height = 288;
1361
1362            // printf("*** coding='%s' width=%d height=%d\n",
1363            //        chunk, width, height);
1364
1365            if (chunk_type != FOURCC('e', 'n', 'c', 'v')) {
1366                // if the chunk type is encv, we'll get the type from the sinf/frma box later
1367                mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
1368            }
1369            mLastTrack->meta->setInt32(kKeyWidth, width);
1370            mLastTrack->meta->setInt32(kKeyHeight, height);
1371
1372            off64_t stop_offset = *offset + chunk_size;
1373            *offset = data_offset + sizeof(buffer);
1374            while (*offset < stop_offset) {
1375                status_t err = parseChunk(offset, depth + 1);
1376                if (err != OK) {
1377                    return err;
1378                }
1379            }
1380
1381            if (*offset != stop_offset) {
1382                return ERROR_MALFORMED;
1383            }
1384            break;
1385        }
1386
1387        case FOURCC('s', 't', 'c', 'o'):
1388        case FOURCC('c', 'o', '6', '4'):
1389        {
1390            status_t err =
1391                mLastTrack->sampleTable->setChunkOffsetParams(
1392                        chunk_type, data_offset, chunk_data_size);
1393
1394            *offset += chunk_size;
1395
1396            if (err != OK) {
1397                return err;
1398            }
1399
1400            break;
1401        }
1402
1403        case FOURCC('s', 't', 's', 'c'):
1404        {
1405            status_t err =
1406                mLastTrack->sampleTable->setSampleToChunkParams(
1407                        data_offset, chunk_data_size);
1408
1409            *offset += chunk_size;
1410
1411            if (err != OK) {
1412                return err;
1413            }
1414
1415            break;
1416        }
1417
1418        case FOURCC('s', 't', 's', 'z'):
1419        case FOURCC('s', 't', 'z', '2'):
1420        {
1421            status_t err =
1422                mLastTrack->sampleTable->setSampleSizeParams(
1423                        chunk_type, data_offset, chunk_data_size);
1424
1425            *offset += chunk_size;
1426
1427            if (err != OK) {
1428                return err;
1429            }
1430
1431            size_t max_size;
1432            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
1433
1434            if (err != OK) {
1435                return err;
1436            }
1437
1438            if (max_size != 0) {
1439                // Assume that a given buffer only contains at most 10 chunks,
1440                // each chunk originally prefixed with a 2 byte length will
1441                // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
1442                // and thus will grow by 2 bytes per chunk.
1443                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2);
1444            } else {
1445                // No size was specified. Pick a conservatively large size.
1446                int32_t width, height;
1447                if (!mLastTrack->meta->findInt32(kKeyWidth, &width) ||
1448                    !mLastTrack->meta->findInt32(kKeyHeight, &height)) {
1449                    ALOGE("No width or height, assuming worst case 1080p");
1450                    width = 1920;
1451                    height = 1080;
1452                }
1453
1454                const char *mime;
1455                CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1456                if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1457                    // AVC requires compression ratio of at least 2, and uses
1458                    // macroblocks
1459                    max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192;
1460                } else {
1461                    // For all other formats there is no minimum compression
1462                    // ratio. Use compression ratio of 1.
1463                    max_size = width * height * 3 / 2;
1464                }
1465                mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size);
1466            }
1467
1468            // NOTE: setting another piece of metadata invalidates any pointers (such as the
1469            // mimetype) previously obtained, so don't cache them.
1470            const char *mime;
1471            CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime));
1472            // Calculate average frame rate.
1473            if (!strncasecmp("video/", mime, 6)) {
1474                size_t nSamples = mLastTrack->sampleTable->countSamples();
1475                int64_t durationUs;
1476                if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) {
1477                    if (durationUs > 0) {
1478                        int32_t frameRate = (nSamples * 1000000LL +
1479                                    (durationUs >> 1)) / durationUs;
1480                        mLastTrack->meta->setInt32(kKeyFrameRate, frameRate);
1481                    }
1482                }
1483            }
1484
1485            break;
1486        }
1487
1488        case FOURCC('s', 't', 't', 's'):
1489        {
1490            *offset += chunk_size;
1491
1492            status_t err =
1493                mLastTrack->sampleTable->setTimeToSampleParams(
1494                        data_offset, chunk_data_size);
1495
1496            if (err != OK) {
1497                return err;
1498            }
1499
1500            break;
1501        }
1502
1503        case FOURCC('c', 't', 't', 's'):
1504        {
1505            *offset += chunk_size;
1506
1507            status_t err =
1508                mLastTrack->sampleTable->setCompositionTimeToSampleParams(
1509                        data_offset, chunk_data_size);
1510
1511            if (err != OK) {
1512                return err;
1513            }
1514
1515            break;
1516        }
1517
1518        case FOURCC('s', 't', 's', 's'):
1519        {
1520            *offset += chunk_size;
1521
1522            status_t err =
1523                mLastTrack->sampleTable->setSyncSampleParams(
1524                        data_offset, chunk_data_size);
1525
1526            if (err != OK) {
1527                return err;
1528            }
1529
1530            break;
1531        }
1532
1533        // @xyz
1534        case FOURCC('\xA9', 'x', 'y', 'z'):
1535        {
1536            *offset += chunk_size;
1537
1538            // Best case the total data length inside "@xyz" box
1539            // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/",
1540            // where "\x00\x04" is the text string length with value = 4,
1541            // "\0x15\xc7" is the language code = en, and "0+0" is a
1542            // location (string) value with longitude = 0 and latitude = 0.
1543            if (chunk_data_size < 8) {
1544                return ERROR_MALFORMED;
1545            }
1546
1547            // Worst case the location string length would be 18,
1548            // for instance +90.0000-180.0000, without the trailing "/" and
1549            // the string length + language code.
1550            char buffer[18];
1551
1552            // Substracting 5 from the data size is because the text string length +
1553            // language code takes 4 bytes, and the trailing slash "/" takes 1 byte.
1554            off64_t location_length = chunk_data_size - 5;
1555            if (location_length >= (off64_t) sizeof(buffer)) {
1556                return ERROR_MALFORMED;
1557            }
1558
1559            if (mDataSource->readAt(
1560                        data_offset + 4, buffer, location_length) < location_length) {
1561                return ERROR_IO;
1562            }
1563
1564            buffer[location_length] = '\0';
1565            mFileMetaData->setCString(kKeyLocation, buffer);
1566            break;
1567        }
1568
1569        case FOURCC('e', 's', 'd', 's'):
1570        {
1571            *offset += chunk_size;
1572
1573            if (chunk_data_size < 4) {
1574                return ERROR_MALFORMED;
1575            }
1576
1577            uint8_t buffer[256];
1578            if (chunk_data_size > (off64_t)sizeof(buffer)) {
1579                return ERROR_BUFFER_TOO_SMALL;
1580            }
1581
1582            if (mDataSource->readAt(
1583                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
1584                return ERROR_IO;
1585            }
1586
1587            if (U32_AT(buffer) != 0) {
1588                // Should be version 0, flags 0.
1589                return ERROR_MALFORMED;
1590            }
1591
1592            mLastTrack->meta->setData(
1593                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
1594
1595            if (mPath.size() >= 2
1596                    && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) {
1597                // Information from the ESDS must be relied on for proper
1598                // setup of sample rate and channel count for MPEG4 Audio.
1599                // The generic header appears to only contain generic
1600                // information...
1601
1602                status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio(
1603                        &buffer[4], chunk_data_size - 4);
1604
1605                if (err != OK) {
1606                    return err;
1607                }
1608            }
1609
1610            break;
1611        }
1612
1613        case FOURCC('a', 'v', 'c', 'C'):
1614        {
1615            *offset += chunk_size;
1616
1617            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
1618
1619            if (mDataSource->readAt(
1620                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
1621                return ERROR_IO;
1622            }
1623
1624            mLastTrack->meta->setData(
1625                    kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size);
1626
1627            break;
1628        }
1629        case FOURCC('h', 'v', 'c', 'C'):
1630        {
1631            sp<ABuffer> buffer = new ABuffer(chunk_data_size);
1632
1633            if (mDataSource->readAt(
1634                        data_offset, buffer->data(), chunk_data_size) < chunk_data_size) {
1635                return ERROR_IO;
1636            }
1637
1638            mLastTrack->meta->setData(
1639                    kKeyHVCC, kTypeHVCC, buffer->data(), chunk_data_size);
1640
1641            *offset += chunk_size;
1642            break;
1643        }
1644
1645        case FOURCC('d', '2', '6', '3'):
1646        {
1647            *offset += chunk_size;
1648            /*
1649             * d263 contains a fixed 7 bytes part:
1650             *   vendor - 4 bytes
1651             *   version - 1 byte
1652             *   level - 1 byte
1653             *   profile - 1 byte
1654             * optionally, "d263" box itself may contain a 16-byte
1655             * bit rate box (bitr)
1656             *   average bit rate - 4 bytes
1657             *   max bit rate - 4 bytes
1658             */
1659            char buffer[23];
1660            if (chunk_data_size != 7 &&
1661                chunk_data_size != 23) {
1662                ALOGE("Incorrect D263 box size %lld", chunk_data_size);
1663                return ERROR_MALFORMED;
1664            }
1665
1666            if (mDataSource->readAt(
1667                    data_offset, buffer, chunk_data_size) < chunk_data_size) {
1668                return ERROR_IO;
1669            }
1670
1671            mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size);
1672
1673            break;
1674        }
1675
1676        case FOURCC('m', 'e', 't', 'a'):
1677        {
1678            uint8_t buffer[4];
1679            if (chunk_data_size < (off64_t)sizeof(buffer)) {
1680                *offset += chunk_size;
1681                return ERROR_MALFORMED;
1682            }
1683
1684            if (mDataSource->readAt(
1685                        data_offset, buffer, 4) < 4) {
1686                *offset += chunk_size;
1687                return ERROR_IO;
1688            }
1689
1690            if (U32_AT(buffer) != 0) {
1691                // Should be version 0, flags 0.
1692
1693                // If it's not, let's assume this is one of those
1694                // apparently malformed chunks that don't have flags
1695                // and completely different semantics than what's
1696                // in the MPEG4 specs and skip it.
1697                *offset += chunk_size;
1698                return OK;
1699            }
1700
1701            off64_t stop_offset = *offset + chunk_size;
1702            *offset = data_offset + sizeof(buffer);
1703            while (*offset < stop_offset) {
1704                status_t err = parseChunk(offset, depth + 1);
1705                if (err != OK) {
1706                    return err;
1707                }
1708            }
1709
1710            if (*offset != stop_offset) {
1711                return ERROR_MALFORMED;
1712            }
1713            break;
1714        }
1715
1716        case FOURCC('m', 'e', 'a', 'n'):
1717        case FOURCC('n', 'a', 'm', 'e'):
1718        case FOURCC('d', 'a', 't', 'a'):
1719        {
1720            *offset += chunk_size;
1721
1722            if (mPath.size() == 6 && underMetaDataPath(mPath)) {
1723                status_t err = parseITunesMetaData(data_offset, chunk_data_size);
1724
1725                if (err != OK) {
1726                    return err;
1727                }
1728            }
1729
1730            break;
1731        }
1732
1733        case FOURCC('m', 'v', 'h', 'd'):
1734        {
1735            *offset += chunk_size;
1736
1737            if (chunk_data_size < 32) {
1738                return ERROR_MALFORMED;
1739            }
1740
1741            uint8_t header[32];
1742            if (mDataSource->readAt(
1743                        data_offset, header, sizeof(header))
1744                    < (ssize_t)sizeof(header)) {
1745                return ERROR_IO;
1746            }
1747
1748            uint64_t creationTime;
1749            uint64_t duration = 0;
1750            if (header[0] == 1) {
1751                creationTime = U64_AT(&header[4]);
1752                mHeaderTimescale = U32_AT(&header[20]);
1753                duration = U64_AT(&header[24]);
1754                if (duration == 0xffffffffffffffff) {
1755                    duration = 0;
1756                }
1757            } else if (header[0] != 0) {
1758                return ERROR_MALFORMED;
1759            } else {
1760                creationTime = U32_AT(&header[4]);
1761                mHeaderTimescale = U32_AT(&header[12]);
1762                uint32_t d32 = U32_AT(&header[16]);
1763                if (d32 == 0xffffffff) {
1764                    d32 = 0;
1765                }
1766                duration = d32;
1767            }
1768            if (duration != 0) {
1769                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
1770            }
1771
1772            String8 s;
1773            convertTimeToDate(creationTime, &s);
1774
1775            mFileMetaData->setCString(kKeyDate, s.string());
1776
1777            break;
1778        }
1779
1780        case FOURCC('m', 'e', 'h', 'd'):
1781        {
1782            *offset += chunk_size;
1783
1784            if (chunk_data_size < 8) {
1785                return ERROR_MALFORMED;
1786            }
1787
1788            uint8_t flags[4];
1789            if (mDataSource->readAt(
1790                        data_offset, flags, sizeof(flags))
1791                    < (ssize_t)sizeof(flags)) {
1792                return ERROR_IO;
1793            }
1794
1795            uint64_t duration = 0;
1796            if (flags[0] == 1) {
1797                // 64 bit
1798                if (chunk_data_size < 12) {
1799                    return ERROR_MALFORMED;
1800                }
1801                mDataSource->getUInt64(data_offset + 4, &duration);
1802                if (duration == 0xffffffffffffffff) {
1803                    duration = 0;
1804                }
1805            } else if (flags[0] == 0) {
1806                // 32 bit
1807                uint32_t d32;
1808                mDataSource->getUInt32(data_offset + 4, &d32);
1809                if (d32 == 0xffffffff) {
1810                    d32 = 0;
1811                }
1812                duration = d32;
1813            } else {
1814                return ERROR_MALFORMED;
1815            }
1816
1817            if (duration != 0) {
1818                mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale);
1819            }
1820
1821            break;
1822        }
1823
1824        case FOURCC('m', 'd', 'a', 't'):
1825        {
1826            ALOGV("mdat chunk, drm: %d", mIsDrm);
1827            if (!mIsDrm) {
1828                *offset += chunk_size;
1829                break;
1830            }
1831
1832            if (chunk_size < 8) {
1833                return ERROR_MALFORMED;
1834            }
1835
1836            return parseDrmSINF(offset, data_offset);
1837        }
1838
1839        case FOURCC('h', 'd', 'l', 'r'):
1840        {
1841            *offset += chunk_size;
1842
1843            uint32_t buffer;
1844            if (mDataSource->readAt(
1845                        data_offset + 8, &buffer, 4) < 4) {
1846                return ERROR_IO;
1847            }
1848
1849            uint32_t type = ntohl(buffer);
1850            // For the 3GPP file format, the handler-type within the 'hdlr' box
1851            // shall be 'text'. We also want to support 'sbtl' handler type
1852            // for a practical reason as various MPEG4 containers use it.
1853            if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) {
1854                mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP);
1855            }
1856
1857            break;
1858        }
1859
1860        case FOURCC('t', 'r', 'e', 'x'):
1861        {
1862            *offset += chunk_size;
1863
1864            if (chunk_data_size < 24) {
1865                return ERROR_IO;
1866            }
1867            uint32_t duration;
1868            Trex trex;
1869            if (!mDataSource->getUInt32(data_offset + 4, &trex.track_ID) ||
1870                !mDataSource->getUInt32(data_offset + 8, &trex.default_sample_description_index) ||
1871                !mDataSource->getUInt32(data_offset + 12, &trex.default_sample_duration) ||
1872                !mDataSource->getUInt32(data_offset + 16, &trex.default_sample_size) ||
1873                !mDataSource->getUInt32(data_offset + 20, &trex.default_sample_flags)) {
1874                return ERROR_IO;
1875            }
1876            mTrex.add(trex);
1877            break;
1878        }
1879
1880        case FOURCC('t', 'x', '3', 'g'):
1881        {
1882            uint32_t type;
1883            const void *data;
1884            size_t size = 0;
1885            if (!mLastTrack->meta->findData(
1886                    kKeyTextFormatData, &type, &data, &size)) {
1887                size = 0;
1888            }
1889
1890            uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size];
1891            if (buffer == NULL) {
1892                return ERROR_MALFORMED;
1893            }
1894
1895            if (size > 0) {
1896                memcpy(buffer, data, size);
1897            }
1898
1899            if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size))
1900                    < chunk_size) {
1901                delete[] buffer;
1902                buffer = NULL;
1903
1904                // advance read pointer so we don't end up reading this again
1905                *offset += chunk_size;
1906                return ERROR_IO;
1907            }
1908
1909            mLastTrack->meta->setData(
1910                    kKeyTextFormatData, 0, buffer, size + chunk_size);
1911
1912            delete[] buffer;
1913
1914            *offset += chunk_size;
1915            break;
1916        }
1917
1918        case FOURCC('c', 'o', 'v', 'r'):
1919        {
1920            *offset += chunk_size;
1921
1922            if (mFileMetaData != NULL) {
1923                ALOGV("chunk_data_size = %lld and data_offset = %lld",
1924                        chunk_data_size, data_offset);
1925                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
1926                if (mDataSource->readAt(
1927                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
1928                    return ERROR_IO;
1929                }
1930                const int kSkipBytesOfDataBox = 16;
1931                mFileMetaData->setData(
1932                    kKeyAlbumArt, MetaData::TYPE_NONE,
1933                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
1934            }
1935
1936            break;
1937        }
1938
1939        case FOURCC('t', 'i', 't', 'l'):
1940        case FOURCC('p', 'e', 'r', 'f'):
1941        case FOURCC('a', 'u', 't', 'h'):
1942        case FOURCC('g', 'n', 'r', 'e'):
1943        case FOURCC('a', 'l', 'b', 'm'):
1944        case FOURCC('y', 'r', 'r', 'c'):
1945        {
1946            *offset += chunk_size;
1947
1948            status_t err = parse3GPPMetaData(data_offset, chunk_data_size, depth);
1949
1950            if (err != OK) {
1951                return err;
1952            }
1953
1954            break;
1955        }
1956
1957        case FOURCC('I', 'D', '3', '2'):
1958        {
1959            *offset += chunk_size;
1960
1961            if (chunk_data_size < 6) {
1962                return ERROR_MALFORMED;
1963            }
1964
1965            parseID3v2MetaData(data_offset + 6);
1966
1967            break;
1968        }
1969
1970        case FOURCC('-', '-', '-', '-'):
1971        {
1972            mLastCommentMean.clear();
1973            mLastCommentName.clear();
1974            mLastCommentData.clear();
1975            *offset += chunk_size;
1976            break;
1977        }
1978
1979        case FOURCC('s', 'i', 'd', 'x'):
1980        {
1981            parseSegmentIndex(data_offset, chunk_data_size);
1982            *offset += chunk_size;
1983            return UNKNOWN_ERROR; // stop parsing after sidx
1984        }
1985
1986        default:
1987        {
1988            *offset += chunk_size;
1989            break;
1990        }
1991    }
1992
1993    return OK;
1994}
1995
1996status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) {
1997  ALOGV("MPEG4Extractor::parseSegmentIndex");
1998
1999    if (size < 12) {
2000      return -EINVAL;
2001    }
2002
2003    uint32_t flags;
2004    if (!mDataSource->getUInt32(offset, &flags)) {
2005        return ERROR_MALFORMED;
2006    }
2007
2008    uint32_t version = flags >> 24;
2009    flags &= 0xffffff;
2010
2011    ALOGV("sidx version %d", version);
2012
2013    uint32_t referenceId;
2014    if (!mDataSource->getUInt32(offset + 4, &referenceId)) {
2015        return ERROR_MALFORMED;
2016    }
2017
2018    uint32_t timeScale;
2019    if (!mDataSource->getUInt32(offset + 8, &timeScale)) {
2020        return ERROR_MALFORMED;
2021    }
2022    ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale);
2023
2024    uint64_t earliestPresentationTime;
2025    uint64_t firstOffset;
2026
2027    offset += 12;
2028    size -= 12;
2029
2030    if (version == 0) {
2031        if (size < 8) {
2032            return -EINVAL;
2033        }
2034        uint32_t tmp;
2035        if (!mDataSource->getUInt32(offset, &tmp)) {
2036            return ERROR_MALFORMED;
2037        }
2038        earliestPresentationTime = tmp;
2039        if (!mDataSource->getUInt32(offset + 4, &tmp)) {
2040            return ERROR_MALFORMED;
2041        }
2042        firstOffset = tmp;
2043        offset += 8;
2044        size -= 8;
2045    } else {
2046        if (size < 16) {
2047            return -EINVAL;
2048        }
2049        if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) {
2050            return ERROR_MALFORMED;
2051        }
2052        if (!mDataSource->getUInt64(offset + 8, &firstOffset)) {
2053            return ERROR_MALFORMED;
2054        }
2055        offset += 16;
2056        size -= 16;
2057    }
2058    ALOGV("sidx pres/off: %" PRIu64 "/%" PRIu64, earliestPresentationTime, firstOffset);
2059
2060    if (size < 4) {
2061        return -EINVAL;
2062    }
2063
2064    uint16_t referenceCount;
2065    if (!mDataSource->getUInt16(offset + 2, &referenceCount)) {
2066        return ERROR_MALFORMED;
2067    }
2068    offset += 4;
2069    size -= 4;
2070    ALOGV("refcount: %d", referenceCount);
2071
2072    if (size < referenceCount * 12) {
2073        return -EINVAL;
2074    }
2075
2076    uint64_t total_duration = 0;
2077    for (unsigned int i = 0; i < referenceCount; i++) {
2078        uint32_t d1, d2, d3;
2079
2080        if (!mDataSource->getUInt32(offset, &d1) ||     // size
2081            !mDataSource->getUInt32(offset + 4, &d2) || // duration
2082            !mDataSource->getUInt32(offset + 8, &d3)) { // flags
2083            return ERROR_MALFORMED;
2084        }
2085
2086        if (d1 & 0x80000000) {
2087            ALOGW("sub-sidx boxes not supported yet");
2088        }
2089        bool sap = d3 & 0x80000000;
2090        uint32_t saptype = (d3 >> 28) & 7;
2091        if (!sap || (saptype != 1 && saptype != 2)) {
2092            // type 1 and 2 are sync samples
2093            ALOGW("not a stream access point, or unsupported type: %08x", d3);
2094        }
2095        total_duration += d2;
2096        offset += 12;
2097        ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3);
2098        SidxEntry se;
2099        se.mSize = d1 & 0x7fffffff;
2100        se.mDurationUs = 1000000LL * d2 / timeScale;
2101        mSidxEntries.add(se);
2102    }
2103
2104    uint64_t sidxDuration = total_duration * 1000000 / timeScale;
2105
2106    int64_t metaDuration;
2107    if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) {
2108        mLastTrack->meta->setInt64(kKeyDuration, sidxDuration);
2109    }
2110    return OK;
2111}
2112
2113
2114
2115status_t MPEG4Extractor::parseTrackHeader(
2116        off64_t data_offset, off64_t data_size) {
2117    if (data_size < 4) {
2118        return ERROR_MALFORMED;
2119    }
2120
2121    uint8_t version;
2122    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
2123        return ERROR_IO;
2124    }
2125
2126    size_t dynSize = (version == 1) ? 36 : 24;
2127
2128    uint8_t buffer[36 + 60];
2129
2130    if (data_size != (off64_t)dynSize + 60) {
2131        return ERROR_MALFORMED;
2132    }
2133
2134    if (mDataSource->readAt(
2135                data_offset, buffer, data_size) < (ssize_t)data_size) {
2136        return ERROR_IO;
2137    }
2138
2139    uint64_t ctime, mtime, duration;
2140    int32_t id;
2141
2142    if (version == 1) {
2143        ctime = U64_AT(&buffer[4]);
2144        mtime = U64_AT(&buffer[12]);
2145        id = U32_AT(&buffer[20]);
2146        duration = U64_AT(&buffer[28]);
2147    } else if (version == 0) {
2148        ctime = U32_AT(&buffer[4]);
2149        mtime = U32_AT(&buffer[8]);
2150        id = U32_AT(&buffer[12]);
2151        duration = U32_AT(&buffer[20]);
2152    } else {
2153        return ERROR_UNSUPPORTED;
2154    }
2155
2156    mLastTrack->meta->setInt32(kKeyTrackID, id);
2157
2158    size_t matrixOffset = dynSize + 16;
2159    int32_t a00 = U32_AT(&buffer[matrixOffset]);
2160    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
2161    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
2162    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
2163    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
2164    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);
2165
2166#if 0
2167    ALOGI("x' = %.2f * x + %.2f * y + %.2f",
2168         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
2169    ALOGI("y' = %.2f * x + %.2f * y + %.2f",
2170         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
2171#endif
2172
2173    uint32_t rotationDegrees;
2174
2175    static const int32_t kFixedOne = 0x10000;
2176    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
2177        // Identity, no rotation
2178        rotationDegrees = 0;
2179    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
2180        rotationDegrees = 90;
2181    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
2182        rotationDegrees = 270;
2183    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
2184        rotationDegrees = 180;
2185    } else {
2186        ALOGW("We only support 0,90,180,270 degree rotation matrices");
2187        rotationDegrees = 0;
2188    }
2189
2190    if (rotationDegrees != 0) {
2191        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
2192    }
2193
2194    // Handle presentation display size, which could be different
2195    // from the image size indicated by kKeyWidth and kKeyHeight.
2196    uint32_t width = U32_AT(&buffer[dynSize + 52]);
2197    uint32_t height = U32_AT(&buffer[dynSize + 56]);
2198    mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16);
2199    mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16);
2200
2201    return OK;
2202}
2203
2204status_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) {
2205    if (size < 4) {
2206        return ERROR_MALFORMED;
2207    }
2208
2209    uint8_t *buffer = new (std::nothrow) uint8_t[size + 1];
2210    if (buffer == NULL) {
2211        return ERROR_MALFORMED;
2212    }
2213    if (mDataSource->readAt(
2214                offset, buffer, size) != (ssize_t)size) {
2215        delete[] buffer;
2216        buffer = NULL;
2217
2218        return ERROR_IO;
2219    }
2220
2221    uint32_t flags = U32_AT(buffer);
2222
2223    uint32_t metadataKey = 0;
2224    char chunk[5];
2225    MakeFourCCString(mPath[4], chunk);
2226    ALOGV("meta: %s @ %lld", chunk, offset);
2227    switch (mPath[4]) {
2228        case FOURCC(0xa9, 'a', 'l', 'b'):
2229        {
2230            metadataKey = kKeyAlbum;
2231            break;
2232        }
2233        case FOURCC(0xa9, 'A', 'R', 'T'):
2234        {
2235            metadataKey = kKeyArtist;
2236            break;
2237        }
2238        case FOURCC('a', 'A', 'R', 'T'):
2239        {
2240            metadataKey = kKeyAlbumArtist;
2241            break;
2242        }
2243        case FOURCC(0xa9, 'd', 'a', 'y'):
2244        {
2245            metadataKey = kKeyYear;
2246            break;
2247        }
2248        case FOURCC(0xa9, 'n', 'a', 'm'):
2249        {
2250            metadataKey = kKeyTitle;
2251            break;
2252        }
2253        case FOURCC(0xa9, 'w', 'r', 't'):
2254        {
2255            metadataKey = kKeyWriter;
2256            break;
2257        }
2258        case FOURCC('c', 'o', 'v', 'r'):
2259        {
2260            metadataKey = kKeyAlbumArt;
2261            break;
2262        }
2263        case FOURCC('g', 'n', 'r', 'e'):
2264        {
2265            metadataKey = kKeyGenre;
2266            break;
2267        }
2268        case FOURCC(0xa9, 'g', 'e', 'n'):
2269        {
2270            metadataKey = kKeyGenre;
2271            break;
2272        }
2273        case FOURCC('c', 'p', 'i', 'l'):
2274        {
2275            if (size == 9 && flags == 21) {
2276                char tmp[16];
2277                sprintf(tmp, "%d",
2278                        (int)buffer[size - 1]);
2279
2280                mFileMetaData->setCString(kKeyCompilation, tmp);
2281            }
2282            break;
2283        }
2284        case FOURCC('t', 'r', 'k', 'n'):
2285        {
2286            if (size == 16 && flags == 0) {
2287                char tmp[16];
2288                uint16_t* pTrack = (uint16_t*)&buffer[10];
2289                uint16_t* pTotalTracks = (uint16_t*)&buffer[12];
2290                sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks));
2291
2292                mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
2293            }
2294            break;
2295        }
2296        case FOURCC('d', 'i', 's', 'k'):
2297        {
2298            if ((size == 14 || size == 16) && flags == 0) {
2299                char tmp[16];
2300                uint16_t* pDisc = (uint16_t*)&buffer[10];
2301                uint16_t* pTotalDiscs = (uint16_t*)&buffer[12];
2302                sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs));
2303
2304                mFileMetaData->setCString(kKeyDiscNumber, tmp);
2305            }
2306            break;
2307        }
2308        case FOURCC('-', '-', '-', '-'):
2309        {
2310            buffer[size] = '\0';
2311            switch (mPath[5]) {
2312                case FOURCC('m', 'e', 'a', 'n'):
2313                    mLastCommentMean.setTo((const char *)buffer + 4);
2314                    break;
2315                case FOURCC('n', 'a', 'm', 'e'):
2316                    mLastCommentName.setTo((const char *)buffer + 4);
2317                    break;
2318                case FOURCC('d', 'a', 't', 'a'):
2319                    mLastCommentData.setTo((const char *)buffer + 8);
2320                    break;
2321            }
2322
2323            // Once we have a set of mean/name/data info, go ahead and process
2324            // it to see if its something we are interested in.  Whether or not
2325            // were are interested in the specific tag, make sure to clear out
2326            // the set so we can be ready to process another tuple should one
2327            // show up later in the file.
2328            if ((mLastCommentMean.length() != 0) &&
2329                (mLastCommentName.length() != 0) &&
2330                (mLastCommentData.length() != 0)) {
2331
2332                if (mLastCommentMean == "com.apple.iTunes"
2333                        && mLastCommentName == "iTunSMPB") {
2334                    int32_t delay, padding;
2335                    if (sscanf(mLastCommentData,
2336                               " %*x %x %x %*x", &delay, &padding) == 2) {
2337                        mLastTrack->meta->setInt32(kKeyEncoderDelay, delay);
2338                        mLastTrack->meta->setInt32(kKeyEncoderPadding, padding);
2339                    }
2340                }
2341
2342                mLastCommentMean.clear();
2343                mLastCommentName.clear();
2344                mLastCommentData.clear();
2345            }
2346            break;
2347        }
2348
2349        default:
2350            break;
2351    }
2352
2353    if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) {
2354        if (metadataKey == kKeyAlbumArt) {
2355            mFileMetaData->setData(
2356                    kKeyAlbumArt, MetaData::TYPE_NONE,
2357                    buffer + 8, size - 8);
2358        } else if (metadataKey == kKeyGenre) {
2359            if (flags == 0) {
2360                // uint8_t genre code, iTunes genre codes are
2361                // the standard id3 codes, except they start
2362                // at 1 instead of 0 (e.g. Pop is 14, not 13)
2363                // We use standard id3 numbering, so subtract 1.
2364                int genrecode = (int)buffer[size - 1];
2365                genrecode--;
2366                if (genrecode < 0) {
2367                    genrecode = 255; // reserved for 'unknown genre'
2368                }
2369                char genre[10];
2370                sprintf(genre, "%d", genrecode);
2371
2372                mFileMetaData->setCString(metadataKey, genre);
2373            } else if (flags == 1) {
2374                // custom genre string
2375                buffer[size] = '\0';
2376
2377                mFileMetaData->setCString(
2378                        metadataKey, (const char *)buffer + 8);
2379            }
2380        } else {
2381            buffer[size] = '\0';
2382
2383            mFileMetaData->setCString(
2384                    metadataKey, (const char *)buffer + 8);
2385        }
2386    }
2387
2388    delete[] buffer;
2389    buffer = NULL;
2390
2391    return OK;
2392}
2393
2394status_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) {
2395    if (size < 4) {
2396        return ERROR_MALFORMED;
2397    }
2398
2399    uint8_t *buffer = new (std::nothrow) uint8_t[size];
2400    if (buffer == NULL) {
2401        return ERROR_MALFORMED;
2402    }
2403    if (mDataSource->readAt(
2404                offset, buffer, size) != (ssize_t)size) {
2405        delete[] buffer;
2406        buffer = NULL;
2407
2408        return ERROR_IO;
2409    }
2410
2411    uint32_t metadataKey = 0;
2412    switch (mPath[depth]) {
2413        case FOURCC('t', 'i', 't', 'l'):
2414        {
2415            metadataKey = kKeyTitle;
2416            break;
2417        }
2418        case FOURCC('p', 'e', 'r', 'f'):
2419        {
2420            metadataKey = kKeyArtist;
2421            break;
2422        }
2423        case FOURCC('a', 'u', 't', 'h'):
2424        {
2425            metadataKey = kKeyWriter;
2426            break;
2427        }
2428        case FOURCC('g', 'n', 'r', 'e'):
2429        {
2430            metadataKey = kKeyGenre;
2431            break;
2432        }
2433        case FOURCC('a', 'l', 'b', 'm'):
2434        {
2435            if (buffer[size - 1] != '\0') {
2436              char tmp[4];
2437              sprintf(tmp, "%u", buffer[size - 1]);
2438
2439              mFileMetaData->setCString(kKeyCDTrackNumber, tmp);
2440            }
2441
2442            metadataKey = kKeyAlbum;
2443            break;
2444        }
2445        case FOURCC('y', 'r', 'r', 'c'):
2446        {
2447            char tmp[5];
2448            uint16_t year = U16_AT(&buffer[4]);
2449
2450            if (year < 10000) {
2451                sprintf(tmp, "%u", year);
2452
2453                mFileMetaData->setCString(kKeyYear, tmp);
2454            }
2455            break;
2456        }
2457
2458        default:
2459            break;
2460    }
2461
2462    if (metadataKey > 0) {
2463        bool isUTF8 = true; // Common case
2464        char16_t *framedata = NULL;
2465        int len16 = 0; // Number of UTF-16 characters
2466
2467        // smallest possible valid UTF-16 string w BOM: 0xfe 0xff 0x00 0x00
2468        if (size - 6 >= 4) {
2469            len16 = ((size - 6) / 2) - 1; // don't include 0x0000 terminator
2470            framedata = (char16_t *)(buffer + 6);
2471            if (0xfffe == *framedata) {
2472                // endianness marker (BOM) doesn't match host endianness
2473                for (int i = 0; i < len16; i++) {
2474                    framedata[i] = bswap_16(framedata[i]);
2475                }
2476                // BOM is now swapped to 0xfeff, we will execute next block too
2477            }
2478
2479            if (0xfeff == *framedata) {
2480                // Remove the BOM
2481                framedata++;
2482                len16--;
2483                isUTF8 = false;
2484            }
2485            // else normal non-zero-length UTF-8 string
2486            // we can't handle UTF-16 without BOM as there is no other
2487            // indication of encoding.
2488        }
2489
2490        if (isUTF8) {
2491            mFileMetaData->setCString(metadataKey, (const char *)buffer + 6);
2492        } else {
2493            // Convert from UTF-16 string to UTF-8 string.
2494            String8 tmpUTF8str(framedata, len16);
2495            mFileMetaData->setCString(metadataKey, tmpUTF8str.string());
2496        }
2497    }
2498
2499    delete[] buffer;
2500    buffer = NULL;
2501
2502    return OK;
2503}
2504
2505void MPEG4Extractor::parseID3v2MetaData(off64_t offset) {
2506    ID3 id3(mDataSource, true /* ignorev1 */, offset);
2507
2508    if (id3.isValid()) {
2509        struct Map {
2510            int key;
2511            const char *tag1;
2512            const char *tag2;
2513        };
2514        static const Map kMap[] = {
2515            { kKeyAlbum, "TALB", "TAL" },
2516            { kKeyArtist, "TPE1", "TP1" },
2517            { kKeyAlbumArtist, "TPE2", "TP2" },
2518            { kKeyComposer, "TCOM", "TCM" },
2519            { kKeyGenre, "TCON", "TCO" },
2520            { kKeyTitle, "TIT2", "TT2" },
2521            { kKeyYear, "TYE", "TYER" },
2522            { kKeyAuthor, "TXT", "TEXT" },
2523            { kKeyCDTrackNumber, "TRK", "TRCK" },
2524            { kKeyDiscNumber, "TPA", "TPOS" },
2525            { kKeyCompilation, "TCP", "TCMP" },
2526        };
2527        static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]);
2528
2529        for (size_t i = 0; i < kNumMapEntries; ++i) {
2530            if (!mFileMetaData->hasData(kMap[i].key)) {
2531                ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1);
2532                if (it->done()) {
2533                    delete it;
2534                    it = new ID3::Iterator(id3, kMap[i].tag2);
2535                }
2536
2537                if (it->done()) {
2538                    delete it;
2539                    continue;
2540                }
2541
2542                String8 s;
2543                it->getString(&s);
2544                delete it;
2545
2546                mFileMetaData->setCString(kMap[i].key, s);
2547            }
2548        }
2549
2550        size_t dataSize;
2551        String8 mime;
2552        const void *data = id3.getAlbumArt(&dataSize, &mime);
2553
2554        if (data) {
2555            mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize);
2556            mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string());
2557        }
2558    }
2559}
2560
2561sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
2562    status_t err;
2563    if ((err = readMetaData()) != OK) {
2564        return NULL;
2565    }
2566
2567    Track *track = mFirstTrack;
2568    while (index > 0) {
2569        if (track == NULL) {
2570            return NULL;
2571        }
2572
2573        track = track->next;
2574        --index;
2575    }
2576
2577    if (track == NULL) {
2578        return NULL;
2579    }
2580
2581
2582    Trex *trex = NULL;
2583    int32_t trackId;
2584    if (track->meta->findInt32(kKeyTrackID, &trackId)) {
2585        for (size_t i = 0; i < mTrex.size(); i++) {
2586            Trex *t = &mTrex.editItemAt(index);
2587            if (t->track_ID == (uint32_t) trackId) {
2588                trex = t;
2589                break;
2590            }
2591        }
2592    }
2593
2594    ALOGV("getTrack called, pssh: %zu", mPssh.size());
2595
2596    return new MPEG4Source(
2597            track->meta, mDataSource, track->timescale, track->sampleTable,
2598            mSidxEntries, trex, mMoofOffset);
2599}
2600
2601// static
2602status_t MPEG4Extractor::verifyTrack(Track *track) {
2603    const char *mime;
2604    CHECK(track->meta->findCString(kKeyMIMEType, &mime));
2605
2606    uint32_t type;
2607    const void *data;
2608    size_t size;
2609    if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
2610        if (!track->meta->findData(kKeyAVCC, &type, &data, &size)
2611                || type != kTypeAVCC) {
2612            return ERROR_MALFORMED;
2613        }
2614    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) {
2615        if (!track->meta->findData(kKeyHVCC, &type, &data, &size)
2616                    || type != kTypeHVCC) {
2617            return ERROR_MALFORMED;
2618        }
2619    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4)
2620            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
2621        if (!track->meta->findData(kKeyESDS, &type, &data, &size)
2622                || type != kTypeESDS) {
2623            return ERROR_MALFORMED;
2624        }
2625    }
2626
2627    if (track->sampleTable == NULL || !track->sampleTable->isValid()) {
2628        // Make sure we have all the metadata we need.
2629        ALOGE("stbl atom missing/invalid.");
2630        return ERROR_MALFORMED;
2631    }
2632
2633    return OK;
2634}
2635
2636typedef enum {
2637    //AOT_NONE             = -1,
2638    //AOT_NULL_OBJECT      = 0,
2639    //AOT_AAC_MAIN         = 1, /**< Main profile                              */
2640    AOT_AAC_LC           = 2,   /**< Low Complexity object                     */
2641    //AOT_AAC_SSR          = 3,
2642    //AOT_AAC_LTP          = 4,
2643    AOT_SBR              = 5,
2644    //AOT_AAC_SCAL         = 6,
2645    //AOT_TWIN_VQ          = 7,
2646    //AOT_CELP             = 8,
2647    //AOT_HVXC             = 9,
2648    //AOT_RSVD_10          = 10, /**< (reserved)                                */
2649    //AOT_RSVD_11          = 11, /**< (reserved)                                */
2650    //AOT_TTSI             = 12, /**< TTSI Object                               */
2651    //AOT_MAIN_SYNTH       = 13, /**< Main Synthetic object                     */
2652    //AOT_WAV_TAB_SYNTH    = 14, /**< Wavetable Synthesis object                */
2653    //AOT_GEN_MIDI         = 15, /**< General MIDI object                       */
2654    //AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */
2655    AOT_ER_AAC_LC        = 17,   /**< Error Resilient(ER) AAC Low Complexity    */
2656    //AOT_RSVD_18          = 18, /**< (reserved)                                */
2657    //AOT_ER_AAC_LTP       = 19, /**< Error Resilient(ER) AAC LTP object        */
2658    AOT_ER_AAC_SCAL      = 20,   /**< Error Resilient(ER) AAC Scalable object   */
2659    //AOT_ER_TWIN_VQ       = 21, /**< Error Resilient(ER) TwinVQ object         */
2660    AOT_ER_BSAC          = 22,   /**< Error Resilient(ER) BSAC object           */
2661    AOT_ER_AAC_LD        = 23,   /**< Error Resilient(ER) AAC LowDelay object   */
2662    //AOT_ER_CELP          = 24, /**< Error Resilient(ER) CELP object           */
2663    //AOT_ER_HVXC          = 25, /**< Error Resilient(ER) HVXC object           */
2664    //AOT_ER_HILN          = 26, /**< Error Resilient(ER) HILN object           */
2665    //AOT_ER_PARA          = 27, /**< Error Resilient(ER) Parametric object     */
2666    //AOT_RSVD_28          = 28, /**< might become SSC                          */
2667    AOT_PS               = 29,   /**< PS, Parametric Stereo (includes SBR)      */
2668    //AOT_MPEGS            = 30, /**< MPEG Surround                             */
2669
2670    AOT_ESCAPE           = 31,   /**< Signal AOT uses more than 5 bits          */
2671
2672    //AOT_MP3ONMP4_L1      = 32, /**< MPEG-Layer1 in mp4                        */
2673    //AOT_MP3ONMP4_L2      = 33, /**< MPEG-Layer2 in mp4                        */
2674    //AOT_MP3ONMP4_L3      = 34, /**< MPEG-Layer3 in mp4                        */
2675    //AOT_RSVD_35          = 35, /**< might become DST                          */
2676    //AOT_RSVD_36          = 36, /**< might become ALS                          */
2677    //AOT_AAC_SLS          = 37, /**< AAC + SLS                                 */
2678    //AOT_SLS              = 38, /**< SLS                                       */
2679    //AOT_ER_AAC_ELD       = 39, /**< AAC Enhanced Low Delay                    */
2680
2681    //AOT_USAC             = 42, /**< USAC                                      */
2682    //AOT_SAOC             = 43, /**< SAOC                                      */
2683    //AOT_LD_MPEGS         = 44, /**< Low Delay MPEG Surround                   */
2684
2685    //AOT_RSVD50           = 50,  /**< Interim AOT for Rsvd50                   */
2686} AUDIO_OBJECT_TYPE;
2687
2688status_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio(
2689        const void *esds_data, size_t esds_size) {
2690    ESDS esds(esds_data, esds_size);
2691
2692    uint8_t objectTypeIndication;
2693    if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) {
2694        return ERROR_MALFORMED;
2695    }
2696
2697    if (objectTypeIndication == 0xe1) {
2698        // This isn't MPEG4 audio at all, it's QCELP 14k...
2699        mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP);
2700        return OK;
2701    }
2702
2703    if (objectTypeIndication  == 0x6b) {
2704        // The media subtype is MP3 audio
2705        // Our software MP3 audio decoder may not be able to handle
2706        // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED
2707        ALOGE("MP3 track in MP4/3GPP file is not supported");
2708        return ERROR_UNSUPPORTED;
2709    }
2710
2711    const uint8_t *csd;
2712    size_t csd_size;
2713    if (esds.getCodecSpecificInfo(
2714                (const void **)&csd, &csd_size) != OK) {
2715        return ERROR_MALFORMED;
2716    }
2717
2718#if 0
2719    printf("ESD of size %d\n", csd_size);
2720    hexdump(csd, csd_size);
2721#endif
2722
2723    if (csd_size == 0) {
2724        // There's no further information, i.e. no codec specific data
2725        // Let's assume that the information provided in the mpeg4 headers
2726        // is accurate and hope for the best.
2727
2728        return OK;
2729    }
2730
2731    if (csd_size < 2) {
2732        return ERROR_MALFORMED;
2733    }
2734
2735    static uint32_t kSamplingRate[] = {
2736        96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
2737        16000, 12000, 11025, 8000, 7350
2738    };
2739
2740    ABitReader br(csd, csd_size);
2741    uint32_t objectType = br.getBits(5);
2742
2743    if (objectType == 31) {  // AAC-ELD => additional 6 bits
2744        objectType = 32 + br.getBits(6);
2745    }
2746
2747    //keep AOT type
2748    mLastTrack->meta->setInt32(kKeyAACAOT, objectType);
2749
2750    uint32_t freqIndex = br.getBits(4);
2751
2752    int32_t sampleRate = 0;
2753    int32_t numChannels = 0;
2754    if (freqIndex == 15) {
2755        if (csd_size < 5) {
2756            return ERROR_MALFORMED;
2757        }
2758        sampleRate = br.getBits(24);
2759        numChannels = br.getBits(4);
2760    } else {
2761        numChannels = br.getBits(4);
2762
2763        if (freqIndex == 13 || freqIndex == 14) {
2764            return ERROR_MALFORMED;
2765        }
2766
2767        sampleRate = kSamplingRate[freqIndex];
2768    }
2769
2770    if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13
2771        uint32_t extFreqIndex = br.getBits(4);
2772        int32_t extSampleRate;
2773        if (extFreqIndex == 15) {
2774            if (csd_size < 8) {
2775                return ERROR_MALFORMED;
2776            }
2777            extSampleRate = br.getBits(24);
2778        } else {
2779            if (extFreqIndex == 13 || extFreqIndex == 14) {
2780                return ERROR_MALFORMED;
2781            }
2782            extSampleRate = kSamplingRate[extFreqIndex];
2783        }
2784        //TODO: save the extension sampling rate value in meta data =>
2785        //      mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate);
2786    }
2787
2788    switch (numChannels) {
2789        // values defined in 14496-3_2009 amendment-4 Table 1.19 - Channel Configuration
2790        case 0:
2791        case 1:// FC
2792        case 2:// FL FR
2793        case 3:// FC, FL FR
2794        case 4:// FC, FL FR, RC
2795        case 5:// FC, FL FR, SL SR
2796        case 6:// FC, FL FR, SL SR, LFE
2797            //numChannels already contains the right value
2798            break;
2799        case 11:// FC, FL FR, SL SR, RC, LFE
2800            numChannels = 7;
2801            break;
2802        case 7: // FC, FCL FCR, FL FR, SL SR, LFE
2803        case 12:// FC, FL  FR,  SL SR, RL RR, LFE
2804        case 14:// FC, FL  FR,  SL SR, LFE, FHL FHR
2805            numChannels = 8;
2806            break;
2807        default:
2808            return ERROR_UNSUPPORTED;
2809    }
2810
2811    {
2812        if (objectType == AOT_SBR || objectType == AOT_PS) {
2813            objectType = br.getBits(5);
2814
2815            if (objectType == AOT_ESCAPE) {
2816                objectType = 32 + br.getBits(6);
2817            }
2818        }
2819        if (objectType == AOT_AAC_LC || objectType == AOT_ER_AAC_LC ||
2820                objectType == AOT_ER_AAC_LD || objectType == AOT_ER_AAC_SCAL ||
2821                objectType == AOT_ER_BSAC) {
2822            const int32_t frameLengthFlag = br.getBits(1);
2823
2824            const int32_t dependsOnCoreCoder = br.getBits(1);
2825
2826            if (dependsOnCoreCoder ) {
2827                const int32_t coreCoderDelay = br.getBits(14);
2828            }
2829
2830            int32_t extensionFlag = -1;
2831            if (br.numBitsLeft() > 0) {
2832                extensionFlag = br.getBits(1);
2833            } else {
2834                switch (objectType) {
2835                // 14496-3 4.5.1.1 extensionFlag
2836                case AOT_AAC_LC:
2837                    extensionFlag = 0;
2838                    break;
2839                case AOT_ER_AAC_LC:
2840                case AOT_ER_AAC_SCAL:
2841                case AOT_ER_BSAC:
2842                case AOT_ER_AAC_LD:
2843                    extensionFlag = 1;
2844                    break;
2845                default:
2846                    TRESPASS();
2847                    break;
2848                }
2849                ALOGW("csd missing extension flag; assuming %d for object type %u.",
2850                        extensionFlag, objectType);
2851            }
2852
2853            if (numChannels == 0) {
2854                int32_t channelsEffectiveNum = 0;
2855                int32_t channelsNum = 0;
2856                const int32_t ElementInstanceTag = br.getBits(4);
2857                const int32_t Profile = br.getBits(2);
2858                const int32_t SamplingFrequencyIndex = br.getBits(4);
2859                const int32_t NumFrontChannelElements = br.getBits(4);
2860                const int32_t NumSideChannelElements = br.getBits(4);
2861                const int32_t NumBackChannelElements = br.getBits(4);
2862                const int32_t NumLfeChannelElements = br.getBits(2);
2863                const int32_t NumAssocDataElements = br.getBits(3);
2864                const int32_t NumValidCcElements = br.getBits(4);
2865
2866                const int32_t MonoMixdownPresent = br.getBits(1);
2867                if (MonoMixdownPresent != 0) {
2868                    const int32_t MonoMixdownElementNumber = br.getBits(4);
2869                }
2870
2871                const int32_t StereoMixdownPresent = br.getBits(1);
2872                if (StereoMixdownPresent != 0) {
2873                    const int32_t StereoMixdownElementNumber = br.getBits(4);
2874                }
2875
2876                const int32_t MatrixMixdownIndexPresent = br.getBits(1);
2877                if (MatrixMixdownIndexPresent != 0) {
2878                    const int32_t MatrixMixdownIndex = br.getBits(2);
2879                    const int32_t PseudoSurroundEnable = br.getBits(1);
2880                }
2881
2882                int i;
2883                for (i=0; i < NumFrontChannelElements; i++) {
2884                    const int32_t FrontElementIsCpe = br.getBits(1);
2885                    const int32_t FrontElementTagSelect = br.getBits(4);
2886                    channelsNum += FrontElementIsCpe ? 2 : 1;
2887                }
2888
2889                for (i=0; i < NumSideChannelElements; i++) {
2890                    const int32_t SideElementIsCpe = br.getBits(1);
2891                    const int32_t SideElementTagSelect = br.getBits(4);
2892                    channelsNum += SideElementIsCpe ? 2 : 1;
2893                }
2894
2895                for (i=0; i < NumBackChannelElements; i++) {
2896                    const int32_t BackElementIsCpe = br.getBits(1);
2897                    const int32_t BackElementTagSelect = br.getBits(4);
2898                    channelsNum += BackElementIsCpe ? 2 : 1;
2899                }
2900                channelsEffectiveNum = channelsNum;
2901
2902                for (i=0; i < NumLfeChannelElements; i++) {
2903                    const int32_t LfeElementTagSelect = br.getBits(4);
2904                    channelsNum += 1;
2905                }
2906                ALOGV("mpeg4 audio channelsNum = %d", channelsNum);
2907                ALOGV("mpeg4 audio channelsEffectiveNum = %d", channelsEffectiveNum);
2908                numChannels = channelsNum;
2909            }
2910        }
2911    }
2912
2913    if (numChannels == 0) {
2914        return ERROR_UNSUPPORTED;
2915    }
2916
2917    int32_t prevSampleRate;
2918    CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate));
2919
2920    if (prevSampleRate != sampleRate) {
2921        ALOGV("mpeg4 audio sample rate different from previous setting. "
2922             "was: %d, now: %d", prevSampleRate, sampleRate);
2923    }
2924
2925    mLastTrack->meta->setInt32(kKeySampleRate, sampleRate);
2926
2927    int32_t prevChannelCount;
2928    CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount));
2929
2930    if (prevChannelCount != numChannels) {
2931        ALOGV("mpeg4 audio channel count different from previous setting. "
2932             "was: %d, now: %d", prevChannelCount, numChannels);
2933    }
2934
2935    mLastTrack->meta->setInt32(kKeyChannelCount, numChannels);
2936
2937    return OK;
2938}
2939
2940////////////////////////////////////////////////////////////////////////////////
2941
2942MPEG4Source::MPEG4Source(
2943        const sp<MetaData> &format,
2944        const sp<DataSource> &dataSource,
2945        int32_t timeScale,
2946        const sp<SampleTable> &sampleTable,
2947        Vector<SidxEntry> &sidx,
2948        const Trex *trex,
2949        off64_t firstMoofOffset)
2950    : mFormat(format),
2951      mDataSource(dataSource),
2952      mTimescale(timeScale),
2953      mSampleTable(sampleTable),
2954      mCurrentSampleIndex(0),
2955      mCurrentFragmentIndex(0),
2956      mSegments(sidx),
2957      mTrex(trex),
2958      mFirstMoofOffset(firstMoofOffset),
2959      mCurrentMoofOffset(firstMoofOffset),
2960      mCurrentTime(0),
2961      mCurrentSampleInfoAllocSize(0),
2962      mCurrentSampleInfoSizes(NULL),
2963      mCurrentSampleInfoOffsetsAllocSize(0),
2964      mCurrentSampleInfoOffsets(NULL),
2965      mIsAVC(false),
2966      mIsHEVC(false),
2967      mNALLengthSize(0),
2968      mStarted(false),
2969      mGroup(NULL),
2970      mBuffer(NULL),
2971      mWantsNALFragments(false),
2972      mSrcBuffer(NULL) {
2973
2974    memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo));
2975
2976    mFormat->findInt32(kKeyCryptoMode, &mCryptoMode);
2977    mDefaultIVSize = 0;
2978    mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize);
2979    uint32_t keytype;
2980    const void *key;
2981    size_t keysize;
2982    if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) {
2983        CHECK(keysize <= 16);
2984        memset(mCryptoKey, 0, 16);
2985        memcpy(mCryptoKey, key, keysize);
2986    }
2987
2988    const char *mime;
2989    bool success = mFormat->findCString(kKeyMIMEType, &mime);
2990    CHECK(success);
2991
2992    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
2993    mIsHEVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC);
2994
2995    if (mIsAVC) {
2996        uint32_t type;
2997        const void *data;
2998        size_t size;
2999        CHECK(format->findData(kKeyAVCC, &type, &data, &size));
3000
3001        const uint8_t *ptr = (const uint8_t *)data;
3002
3003        CHECK(size >= 7);
3004        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
3005
3006        // The number of bytes used to encode the length of a NAL unit.
3007        mNALLengthSize = 1 + (ptr[4] & 3);
3008    } else if (mIsHEVC) {
3009        uint32_t type;
3010        const void *data;
3011        size_t size;
3012        CHECK(format->findData(kKeyHVCC, &type, &data, &size));
3013
3014        const uint8_t *ptr = (const uint8_t *)data;
3015
3016        CHECK(size >= 7);
3017        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1
3018
3019        mNALLengthSize = 1 + (ptr[14 + 7] & 3);
3020    }
3021
3022    CHECK(format->findInt32(kKeyTrackID, &mTrackId));
3023
3024    if (mFirstMoofOffset != 0) {
3025        off64_t offset = mFirstMoofOffset;
3026        parseChunk(&offset);
3027    }
3028}
3029
3030MPEG4Source::~MPEG4Source() {
3031    if (mStarted) {
3032        stop();
3033    }
3034    free(mCurrentSampleInfoSizes);
3035    free(mCurrentSampleInfoOffsets);
3036}
3037
3038status_t MPEG4Source::start(MetaData *params) {
3039    Mutex::Autolock autoLock(mLock);
3040
3041    CHECK(!mStarted);
3042
3043    int32_t val;
3044    if (params && params->findInt32(kKeyWantsNALFragments, &val)
3045        && val != 0) {
3046        mWantsNALFragments = true;
3047    } else {
3048        mWantsNALFragments = false;
3049    }
3050
3051    mGroup = new MediaBufferGroup;
3052
3053    int32_t max_size;
3054    CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
3055
3056    mGroup->add_buffer(new MediaBuffer(max_size));
3057
3058    mSrcBuffer = new (std::nothrow) uint8_t[max_size];
3059    if (mSrcBuffer == NULL) {
3060        // file probably specified a bad max size
3061        return ERROR_MALFORMED;
3062    }
3063
3064    mStarted = true;
3065
3066    return OK;
3067}
3068
3069status_t MPEG4Source::stop() {
3070    Mutex::Autolock autoLock(mLock);
3071
3072    CHECK(mStarted);
3073
3074    if (mBuffer != NULL) {
3075        mBuffer->release();
3076        mBuffer = NULL;
3077    }
3078
3079    delete[] mSrcBuffer;
3080    mSrcBuffer = NULL;
3081
3082    delete mGroup;
3083    mGroup = NULL;
3084
3085    mStarted = false;
3086    mCurrentSampleIndex = 0;
3087
3088    return OK;
3089}
3090
3091status_t MPEG4Source::parseChunk(off64_t *offset) {
3092    uint32_t hdr[2];
3093    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
3094        return ERROR_IO;
3095    }
3096    uint64_t chunk_size = ntohl(hdr[0]);
3097    uint32_t chunk_type = ntohl(hdr[1]);
3098    off64_t data_offset = *offset + 8;
3099
3100    if (chunk_size == 1) {
3101        if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) {
3102            return ERROR_IO;
3103        }
3104        chunk_size = ntoh64(chunk_size);
3105        data_offset += 8;
3106
3107        if (chunk_size < 16) {
3108            // The smallest valid chunk is 16 bytes long in this case.
3109            return ERROR_MALFORMED;
3110        }
3111    } else if (chunk_size < 8) {
3112        // The smallest valid chunk is 8 bytes long.
3113        return ERROR_MALFORMED;
3114    }
3115
3116    char chunk[5];
3117    MakeFourCCString(chunk_type, chunk);
3118    ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset);
3119
3120    off64_t chunk_data_size = *offset + chunk_size - data_offset;
3121
3122    switch(chunk_type) {
3123
3124        case FOURCC('t', 'r', 'a', 'f'):
3125        case FOURCC('m', 'o', 'o', 'f'): {
3126            off64_t stop_offset = *offset + chunk_size;
3127            *offset = data_offset;
3128            while (*offset < stop_offset) {
3129                status_t err = parseChunk(offset);
3130                if (err != OK) {
3131                    return err;
3132                }
3133            }
3134            if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
3135                // *offset points to the box following this moof. Find the next moof from there.
3136
3137                while (true) {
3138                    if (mDataSource->readAt(*offset, hdr, 8) < 8) {
3139                        return ERROR_END_OF_STREAM;
3140                    }
3141                    chunk_size = ntohl(hdr[0]);
3142                    chunk_type = ntohl(hdr[1]);
3143                    if (chunk_type == FOURCC('m', 'o', 'o', 'f')) {
3144                        mNextMoofOffset = *offset;
3145                        break;
3146                    }
3147                    *offset += chunk_size;
3148                }
3149            }
3150            break;
3151        }
3152
3153        case FOURCC('t', 'f', 'h', 'd'): {
3154                status_t err;
3155                if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) {
3156                    return err;
3157                }
3158                *offset += chunk_size;
3159                break;
3160        }
3161
3162        case FOURCC('t', 'r', 'u', 'n'): {
3163                status_t err;
3164                if (mLastParsedTrackId == mTrackId) {
3165                    if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) {
3166                        return err;
3167                    }
3168                }
3169
3170                *offset += chunk_size;
3171                break;
3172        }
3173
3174        case FOURCC('s', 'a', 'i', 'z'): {
3175            status_t err;
3176            if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) {
3177                return err;
3178            }
3179            *offset += chunk_size;
3180            break;
3181        }
3182        case FOURCC('s', 'a', 'i', 'o'): {
3183            status_t err;
3184            if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) {
3185                return err;
3186            }
3187            *offset += chunk_size;
3188            break;
3189        }
3190
3191        case FOURCC('m', 'd', 'a', 't'): {
3192            // parse DRM info if present
3193            ALOGV("MPEG4Source::parseChunk mdat");
3194            // if saiz/saoi was previously observed, do something with the sampleinfos
3195            *offset += chunk_size;
3196            break;
3197        }
3198
3199        default: {
3200            *offset += chunk_size;
3201            break;
3202        }
3203    }
3204    return OK;
3205}
3206
3207status_t MPEG4Source::parseSampleAuxiliaryInformationSizes(
3208        off64_t offset, off64_t /* size */) {
3209    ALOGV("parseSampleAuxiliaryInformationSizes");
3210    // 14496-12 8.7.12
3211    uint8_t version;
3212    if (mDataSource->readAt(
3213            offset, &version, sizeof(version))
3214            < (ssize_t)sizeof(version)) {
3215        return ERROR_IO;
3216    }
3217
3218    if (version != 0) {
3219        return ERROR_UNSUPPORTED;
3220    }
3221    offset++;
3222
3223    uint32_t flags;
3224    if (!mDataSource->getUInt24(offset, &flags)) {
3225        return ERROR_IO;
3226    }
3227    offset += 3;
3228
3229    if (flags & 1) {
3230        uint32_t tmp;
3231        if (!mDataSource->getUInt32(offset, &tmp)) {
3232            return ERROR_MALFORMED;
3233        }
3234        mCurrentAuxInfoType = tmp;
3235        offset += 4;
3236        if (!mDataSource->getUInt32(offset, &tmp)) {
3237            return ERROR_MALFORMED;
3238        }
3239        mCurrentAuxInfoTypeParameter = tmp;
3240        offset += 4;
3241    }
3242
3243    uint8_t defsize;
3244    if (mDataSource->readAt(offset, &defsize, 1) != 1) {
3245        return ERROR_MALFORMED;
3246    }
3247    mCurrentDefaultSampleInfoSize = defsize;
3248    offset++;
3249
3250    uint32_t smplcnt;
3251    if (!mDataSource->getUInt32(offset, &smplcnt)) {
3252        return ERROR_MALFORMED;
3253    }
3254    mCurrentSampleInfoCount = smplcnt;
3255    offset += 4;
3256
3257    if (mCurrentDefaultSampleInfoSize != 0) {
3258        ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize);
3259        return OK;
3260    }
3261    if (smplcnt > mCurrentSampleInfoAllocSize) {
3262        mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt);
3263        mCurrentSampleInfoAllocSize = smplcnt;
3264    }
3265
3266    mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt);
3267    return OK;
3268}
3269
3270status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
3271        off64_t offset, off64_t /* size */) {
3272    ALOGV("parseSampleAuxiliaryInformationOffsets");
3273    // 14496-12 8.7.13
3274    uint8_t version;
3275    if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) {
3276        return ERROR_IO;
3277    }
3278    offset++;
3279
3280    uint32_t flags;
3281    if (!mDataSource->getUInt24(offset, &flags)) {
3282        return ERROR_IO;
3283    }
3284    offset += 3;
3285
3286    uint32_t entrycount;
3287    if (!mDataSource->getUInt32(offset, &entrycount)) {
3288        return ERROR_IO;
3289    }
3290    offset += 4;
3291
3292    if (entrycount > mCurrentSampleInfoOffsetsAllocSize) {
3293        mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8);
3294        mCurrentSampleInfoOffsetsAllocSize = entrycount;
3295    }
3296    mCurrentSampleInfoOffsetCount = entrycount;
3297
3298    for (size_t i = 0; i < entrycount; i++) {
3299        if (version == 0) {
3300            uint32_t tmp;
3301            if (!mDataSource->getUInt32(offset, &tmp)) {
3302                return ERROR_IO;
3303            }
3304            mCurrentSampleInfoOffsets[i] = tmp;
3305            offset += 4;
3306        } else {
3307            uint64_t tmp;
3308            if (!mDataSource->getUInt64(offset, &tmp)) {
3309                return ERROR_IO;
3310            }
3311            mCurrentSampleInfoOffsets[i] = tmp;
3312            offset += 8;
3313        }
3314    }
3315
3316    // parse clear/encrypted data
3317
3318    off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof
3319
3320    drmoffset += mCurrentMoofOffset;
3321    int ivlength;
3322    CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength));
3323
3324    // read CencSampleAuxiliaryDataFormats
3325    for (size_t i = 0; i < mCurrentSampleInfoCount; i++) {
3326        Sample *smpl = &mCurrentSamples.editItemAt(i);
3327
3328        memset(smpl->iv, 0, 16);
3329        if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) {
3330            return ERROR_IO;
3331        }
3332
3333        drmoffset += ivlength;
3334
3335        int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
3336        if (smplinfosize == 0) {
3337            smplinfosize = mCurrentSampleInfoSizes[i];
3338        }
3339        if (smplinfosize > ivlength) {
3340            uint16_t numsubsamples;
3341            if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) {
3342                return ERROR_IO;
3343            }
3344            drmoffset += 2;
3345            for (size_t j = 0; j < numsubsamples; j++) {
3346                uint16_t numclear;
3347                uint32_t numencrypted;
3348                if (!mDataSource->getUInt16(drmoffset, &numclear)) {
3349                    return ERROR_IO;
3350                }
3351                drmoffset += 2;
3352                if (!mDataSource->getUInt32(drmoffset, &numencrypted)) {
3353                    return ERROR_IO;
3354                }
3355                drmoffset += 4;
3356                smpl->clearsizes.add(numclear);
3357                smpl->encryptedsizes.add(numencrypted);
3358            }
3359        } else {
3360            smpl->clearsizes.add(0);
3361            smpl->encryptedsizes.add(smpl->size);
3362        }
3363    }
3364
3365
3366    return OK;
3367}
3368
3369status_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
3370
3371    if (size < 8) {
3372        return -EINVAL;
3373    }
3374
3375    uint32_t flags;
3376    if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
3377        return ERROR_MALFORMED;
3378    }
3379
3380    if (flags & 0xff000000) {
3381        return -EINVAL;
3382    }
3383
3384    if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) {
3385        return ERROR_MALFORMED;
3386    }
3387
3388    if (mLastParsedTrackId != mTrackId) {
3389        // this is not the right track, skip it
3390        return OK;
3391    }
3392
3393    mTrackFragmentHeaderInfo.mFlags = flags;
3394    mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId;
3395    offset += 8;
3396    size -= 8;
3397
3398    ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID);
3399
3400    if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) {
3401        if (size < 8) {
3402            return -EINVAL;
3403        }
3404
3405        if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) {
3406            return ERROR_MALFORMED;
3407        }
3408        offset += 8;
3409        size -= 8;
3410    }
3411
3412    if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) {
3413        if (size < 4) {
3414            return -EINVAL;
3415        }
3416
3417        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) {
3418            return ERROR_MALFORMED;
3419        }
3420        offset += 4;
3421        size -= 4;
3422    }
3423
3424    if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
3425        if (size < 4) {
3426            return -EINVAL;
3427        }
3428
3429        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) {
3430            return ERROR_MALFORMED;
3431        }
3432        offset += 4;
3433        size -= 4;
3434    }
3435
3436    if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
3437        if (size < 4) {
3438            return -EINVAL;
3439        }
3440
3441        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) {
3442            return ERROR_MALFORMED;
3443        }
3444        offset += 4;
3445        size -= 4;
3446    }
3447
3448    if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
3449        if (size < 4) {
3450            return -EINVAL;
3451        }
3452
3453        if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) {
3454            return ERROR_MALFORMED;
3455        }
3456        offset += 4;
3457        size -= 4;
3458    }
3459
3460    if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) {
3461        mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset;
3462    }
3463
3464    mTrackFragmentHeaderInfo.mDataOffset = 0;
3465    return OK;
3466}
3467
3468status_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) {
3469
3470    ALOGV("MPEG4Extractor::parseTrackFragmentRun");
3471    if (size < 8) {
3472        return -EINVAL;
3473    }
3474
3475    enum {
3476        kDataOffsetPresent                  = 0x01,
3477        kFirstSampleFlagsPresent            = 0x04,
3478        kSampleDurationPresent              = 0x100,
3479        kSampleSizePresent                  = 0x200,
3480        kSampleFlagsPresent                 = 0x400,
3481        kSampleCompositionTimeOffsetPresent = 0x800,
3482    };
3483
3484    uint32_t flags;
3485    if (!mDataSource->getUInt32(offset, &flags)) {
3486        return ERROR_MALFORMED;
3487    }
3488    ALOGV("fragment run flags: %08x", flags);
3489
3490    if (flags & 0xff000000) {
3491        return -EINVAL;
3492    }
3493
3494    if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) {
3495        // These two shall not be used together.
3496        return -EINVAL;
3497    }
3498
3499    uint32_t sampleCount;
3500    if (!mDataSource->getUInt32(offset + 4, &sampleCount)) {
3501        return ERROR_MALFORMED;
3502    }
3503    offset += 8;
3504    size -= 8;
3505
3506    uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset;
3507
3508    uint32_t firstSampleFlags = 0;
3509
3510    if (flags & kDataOffsetPresent) {
3511        if (size < 4) {
3512            return -EINVAL;
3513        }
3514
3515        int32_t dataOffsetDelta;
3516        if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) {
3517            return ERROR_MALFORMED;
3518        }
3519
3520        dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta;
3521
3522        offset += 4;
3523        size -= 4;
3524    }
3525
3526    if (flags & kFirstSampleFlagsPresent) {
3527        if (size < 4) {
3528            return -EINVAL;
3529        }
3530
3531        if (!mDataSource->getUInt32(offset, &firstSampleFlags)) {
3532            return ERROR_MALFORMED;
3533        }
3534        offset += 4;
3535        size -= 4;
3536    }
3537
3538    uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0,
3539             sampleCtsOffset = 0;
3540
3541    size_t bytesPerSample = 0;
3542    if (flags & kSampleDurationPresent) {
3543        bytesPerSample += 4;
3544    } else if (mTrackFragmentHeaderInfo.mFlags
3545            & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) {
3546        sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration;
3547    } else if (mTrex) {
3548        sampleDuration = mTrex->default_sample_duration;
3549    }
3550
3551    if (flags & kSampleSizePresent) {
3552        bytesPerSample += 4;
3553    } else if (mTrackFragmentHeaderInfo.mFlags
3554            & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) {
3555        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
3556    } else {
3557        sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize;
3558    }
3559
3560    if (flags & kSampleFlagsPresent) {
3561        bytesPerSample += 4;
3562    } else if (mTrackFragmentHeaderInfo.mFlags
3563            & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) {
3564        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
3565    } else {
3566        sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags;
3567    }
3568
3569    if (flags & kSampleCompositionTimeOffsetPresent) {
3570        bytesPerSample += 4;
3571    } else {
3572        sampleCtsOffset = 0;
3573    }
3574
3575    if (size < (off64_t)sampleCount * bytesPerSample) {
3576        return -EINVAL;
3577    }
3578
3579    Sample tmp;
3580    for (uint32_t i = 0; i < sampleCount; ++i) {
3581        if (flags & kSampleDurationPresent) {
3582            if (!mDataSource->getUInt32(offset, &sampleDuration)) {
3583                return ERROR_MALFORMED;
3584            }
3585            offset += 4;
3586        }
3587
3588        if (flags & kSampleSizePresent) {
3589            if (!mDataSource->getUInt32(offset, &sampleSize)) {
3590                return ERROR_MALFORMED;
3591            }
3592            offset += 4;
3593        }
3594
3595        if (flags & kSampleFlagsPresent) {
3596            if (!mDataSource->getUInt32(offset, &sampleFlags)) {
3597                return ERROR_MALFORMED;
3598            }
3599            offset += 4;
3600        }
3601
3602        if (flags & kSampleCompositionTimeOffsetPresent) {
3603            if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) {
3604                return ERROR_MALFORMED;
3605            }
3606            offset += 4;
3607        }
3608
3609        ALOGV("adding sample %d at offset 0x%08" PRIx64 ", size %u, duration %u, "
3610              " flags 0x%08x", i + 1,
3611                dataOffset, sampleSize, sampleDuration,
3612                (flags & kFirstSampleFlagsPresent) && i == 0
3613                    ? firstSampleFlags : sampleFlags);
3614        tmp.offset = dataOffset;
3615        tmp.size = sampleSize;
3616        tmp.duration = sampleDuration;
3617        tmp.compositionOffset = sampleCtsOffset;
3618        mCurrentSamples.add(tmp);
3619
3620        dataOffset += sampleSize;
3621    }
3622
3623    mTrackFragmentHeaderInfo.mDataOffset = dataOffset;
3624
3625    return OK;
3626}
3627
3628sp<MetaData> MPEG4Source::getFormat() {
3629    Mutex::Autolock autoLock(mLock);
3630
3631    return mFormat;
3632}
3633
3634size_t MPEG4Source::parseNALSize(const uint8_t *data) const {
3635    switch (mNALLengthSize) {
3636        case 1:
3637            return *data;
3638        case 2:
3639            return U16_AT(data);
3640        case 3:
3641            return ((size_t)data[0] << 16) | U16_AT(&data[1]);
3642        case 4:
3643            return U32_AT(data);
3644    }
3645
3646    // This cannot happen, mNALLengthSize springs to life by adding 1 to
3647    // a 2-bit integer.
3648    CHECK(!"Should not be here.");
3649
3650    return 0;
3651}
3652
3653status_t MPEG4Source::read(
3654        MediaBuffer **out, const ReadOptions *options) {
3655    Mutex::Autolock autoLock(mLock);
3656
3657    CHECK(mStarted);
3658
3659    if (mFirstMoofOffset > 0) {
3660        return fragmentedRead(out, options);
3661    }
3662
3663    *out = NULL;
3664
3665    int64_t targetSampleTimeUs = -1;
3666
3667    int64_t seekTimeUs;
3668    ReadOptions::SeekMode mode;
3669    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3670        uint32_t findFlags = 0;
3671        switch (mode) {
3672            case ReadOptions::SEEK_PREVIOUS_SYNC:
3673                findFlags = SampleTable::kFlagBefore;
3674                break;
3675            case ReadOptions::SEEK_NEXT_SYNC:
3676                findFlags = SampleTable::kFlagAfter;
3677                break;
3678            case ReadOptions::SEEK_CLOSEST_SYNC:
3679            case ReadOptions::SEEK_CLOSEST:
3680                findFlags = SampleTable::kFlagClosest;
3681                break;
3682            default:
3683                CHECK(!"Should not be here.");
3684                break;
3685        }
3686
3687        uint32_t sampleIndex;
3688        status_t err = mSampleTable->findSampleAtTime(
3689                seekTimeUs, 1000000, mTimescale,
3690                &sampleIndex, findFlags);
3691
3692        if (mode == ReadOptions::SEEK_CLOSEST) {
3693            // We found the closest sample already, now we want the sync
3694            // sample preceding it (or the sample itself of course), even
3695            // if the subsequent sync sample is closer.
3696            findFlags = SampleTable::kFlagBefore;
3697        }
3698
3699        uint32_t syncSampleIndex;
3700        if (err == OK) {
3701            err = mSampleTable->findSyncSampleNear(
3702                    sampleIndex, &syncSampleIndex, findFlags);
3703        }
3704
3705        uint32_t sampleTime;
3706        if (err == OK) {
3707            err = mSampleTable->getMetaDataForSample(
3708                    sampleIndex, NULL, NULL, &sampleTime);
3709        }
3710
3711        if (err != OK) {
3712            if (err == ERROR_OUT_OF_RANGE) {
3713                // An attempt to seek past the end of the stream would
3714                // normally cause this ERROR_OUT_OF_RANGE error. Propagating
3715                // this all the way to the MediaPlayer would cause abnormal
3716                // termination. Legacy behaviour appears to be to behave as if
3717                // we had seeked to the end of stream, ending normally.
3718                err = ERROR_END_OF_STREAM;
3719            }
3720            ALOGV("end of stream");
3721            return err;
3722        }
3723
3724        if (mode == ReadOptions::SEEK_CLOSEST) {
3725            targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale;
3726        }
3727
3728#if 0
3729        uint32_t syncSampleTime;
3730        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
3731                    syncSampleIndex, NULL, NULL, &syncSampleTime));
3732
3733        ALOGI("seek to time %lld us => sample at time %lld us, "
3734             "sync sample at time %lld us",
3735             seekTimeUs,
3736             sampleTime * 1000000ll / mTimescale,
3737             syncSampleTime * 1000000ll / mTimescale);
3738#endif
3739
3740        mCurrentSampleIndex = syncSampleIndex;
3741        if (mBuffer != NULL) {
3742            mBuffer->release();
3743            mBuffer = NULL;
3744        }
3745
3746        // fall through
3747    }
3748
3749    off64_t offset;
3750    size_t size;
3751    uint32_t cts, stts;
3752    bool isSyncSample;
3753    bool newBuffer = false;
3754    if (mBuffer == NULL) {
3755        newBuffer = true;
3756
3757        status_t err =
3758            mSampleTable->getMetaDataForSample(
3759                    mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample, &stts);
3760
3761        if (err != OK) {
3762            return err;
3763        }
3764
3765        err = mGroup->acquire_buffer(&mBuffer);
3766
3767        if (err != OK) {
3768            CHECK(mBuffer == NULL);
3769            return err;
3770        }
3771    }
3772
3773    if ((!mIsAVC && !mIsHEVC) || mWantsNALFragments) {
3774        if (newBuffer) {
3775            ssize_t num_bytes_read =
3776                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
3777
3778            if (num_bytes_read < (ssize_t)size) {
3779                mBuffer->release();
3780                mBuffer = NULL;
3781
3782                return ERROR_IO;
3783            }
3784
3785            CHECK(mBuffer != NULL);
3786            mBuffer->set_range(0, size);
3787            mBuffer->meta_data()->clear();
3788            mBuffer->meta_data()->setInt64(
3789                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3790            mBuffer->meta_data()->setInt64(
3791                    kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
3792
3793            if (targetSampleTimeUs >= 0) {
3794                mBuffer->meta_data()->setInt64(
3795                        kKeyTargetTime, targetSampleTimeUs);
3796            }
3797
3798            if (isSyncSample) {
3799                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
3800            }
3801
3802            ++mCurrentSampleIndex;
3803        }
3804
3805        if (!mIsAVC && !mIsHEVC) {
3806            *out = mBuffer;
3807            mBuffer = NULL;
3808
3809            return OK;
3810        }
3811
3812        // Each NAL unit is split up into its constituent fragments and
3813        // each one of them returned in its own buffer.
3814
3815        CHECK(mBuffer->range_length() >= mNALLengthSize);
3816
3817        const uint8_t *src =
3818            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
3819
3820        size_t nal_size = parseNALSize(src);
3821        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
3822            ALOGE("incomplete NAL unit.");
3823
3824            mBuffer->release();
3825            mBuffer = NULL;
3826
3827            return ERROR_MALFORMED;
3828        }
3829
3830        MediaBuffer *clone = mBuffer->clone();
3831        CHECK(clone != NULL);
3832        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
3833
3834        CHECK(mBuffer != NULL);
3835        mBuffer->set_range(
3836                mBuffer->range_offset() + mNALLengthSize + nal_size,
3837                mBuffer->range_length() - mNALLengthSize - nal_size);
3838
3839        if (mBuffer->range_length() == 0) {
3840            mBuffer->release();
3841            mBuffer = NULL;
3842        }
3843
3844        *out = clone;
3845
3846        return OK;
3847    } else {
3848        // Whole NAL units are returned but each fragment is prefixed by
3849        // the start code (0x00 00 00 01).
3850        ssize_t num_bytes_read = 0;
3851        int32_t drm = 0;
3852        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
3853        if (usesDRM) {
3854            num_bytes_read =
3855                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
3856        } else {
3857            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
3858        }
3859
3860        if (num_bytes_read < (ssize_t)size) {
3861            mBuffer->release();
3862            mBuffer = NULL;
3863
3864            return ERROR_IO;
3865        }
3866
3867        if (usesDRM) {
3868            CHECK(mBuffer != NULL);
3869            mBuffer->set_range(0, size);
3870
3871        } else {
3872            uint8_t *dstData = (uint8_t *)mBuffer->data();
3873            size_t srcOffset = 0;
3874            size_t dstOffset = 0;
3875
3876            while (srcOffset < size) {
3877                bool isMalFormed = (srcOffset + mNALLengthSize > size);
3878                size_t nalLength = 0;
3879                if (!isMalFormed) {
3880                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
3881                    srcOffset += mNALLengthSize;
3882                    isMalFormed = srcOffset + nalLength > size;
3883                }
3884
3885                if (isMalFormed) {
3886                    ALOGE("Video is malformed");
3887                    mBuffer->release();
3888                    mBuffer = NULL;
3889                    return ERROR_MALFORMED;
3890                }
3891
3892                if (nalLength == 0) {
3893                    continue;
3894                }
3895
3896                CHECK(dstOffset + 4 <= mBuffer->size());
3897
3898                dstData[dstOffset++] = 0;
3899                dstData[dstOffset++] = 0;
3900                dstData[dstOffset++] = 0;
3901                dstData[dstOffset++] = 1;
3902                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
3903                srcOffset += nalLength;
3904                dstOffset += nalLength;
3905            }
3906            CHECK_EQ(srcOffset, size);
3907            CHECK(mBuffer != NULL);
3908            mBuffer->set_range(0, dstOffset);
3909        }
3910
3911        mBuffer->meta_data()->clear();
3912        mBuffer->meta_data()->setInt64(
3913                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
3914        mBuffer->meta_data()->setInt64(
3915                kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
3916
3917        if (targetSampleTimeUs >= 0) {
3918            mBuffer->meta_data()->setInt64(
3919                    kKeyTargetTime, targetSampleTimeUs);
3920        }
3921
3922        if (isSyncSample) {
3923            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
3924        }
3925
3926        ++mCurrentSampleIndex;
3927
3928        *out = mBuffer;
3929        mBuffer = NULL;
3930
3931        return OK;
3932    }
3933}
3934
3935status_t MPEG4Source::fragmentedRead(
3936        MediaBuffer **out, const ReadOptions *options) {
3937
3938    ALOGV("MPEG4Source::fragmentedRead");
3939
3940    CHECK(mStarted);
3941
3942    *out = NULL;
3943
3944    int64_t targetSampleTimeUs = -1;
3945
3946    int64_t seekTimeUs;
3947    ReadOptions::SeekMode mode;
3948    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
3949
3950        int numSidxEntries = mSegments.size();
3951        if (numSidxEntries != 0) {
3952            int64_t totalTime = 0;
3953            off64_t totalOffset = mFirstMoofOffset;
3954            for (int i = 0; i < numSidxEntries; i++) {
3955                const SidxEntry *se = &mSegments[i];
3956                if (totalTime + se->mDurationUs > seekTimeUs) {
3957                    // The requested time is somewhere in this segment
3958                    if ((mode == ReadOptions::SEEK_NEXT_SYNC && seekTimeUs > totalTime) ||
3959                        (mode == ReadOptions::SEEK_CLOSEST_SYNC &&
3960                        (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) {
3961                        // requested next sync, or closest sync and it was closer to the end of
3962                        // this segment
3963                        totalTime += se->mDurationUs;
3964                        totalOffset += se->mSize;
3965                    }
3966                    break;
3967                }
3968                totalTime += se->mDurationUs;
3969                totalOffset += se->mSize;
3970            }
3971            mCurrentMoofOffset = totalOffset;
3972            mCurrentSamples.clear();
3973            mCurrentSampleIndex = 0;
3974            parseChunk(&totalOffset);
3975            mCurrentTime = totalTime * mTimescale / 1000000ll;
3976        } else {
3977            // without sidx boxes, we can only seek to 0
3978            mCurrentMoofOffset = mFirstMoofOffset;
3979            mCurrentSamples.clear();
3980            mCurrentSampleIndex = 0;
3981            off64_t tmp = mCurrentMoofOffset;
3982            parseChunk(&tmp);
3983            mCurrentTime = 0;
3984        }
3985
3986        if (mBuffer != NULL) {
3987            mBuffer->release();
3988            mBuffer = NULL;
3989        }
3990
3991        // fall through
3992    }
3993
3994    off64_t offset = 0;
3995    size_t size = 0;
3996    uint32_t cts = 0;
3997    bool isSyncSample = false;
3998    bool newBuffer = false;
3999    if (mBuffer == NULL) {
4000        newBuffer = true;
4001
4002        if (mCurrentSampleIndex >= mCurrentSamples.size()) {
4003            // move to next fragment if there is one
4004            if (mNextMoofOffset <= mCurrentMoofOffset) {
4005                return ERROR_END_OF_STREAM;
4006            }
4007            off64_t nextMoof = mNextMoofOffset;
4008            mCurrentMoofOffset = nextMoof;
4009            mCurrentSamples.clear();
4010            mCurrentSampleIndex = 0;
4011            parseChunk(&nextMoof);
4012            if (mCurrentSampleIndex >= mCurrentSamples.size()) {
4013                return ERROR_END_OF_STREAM;
4014            }
4015        }
4016
4017        const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
4018        offset = smpl->offset;
4019        size = smpl->size;
4020        cts = mCurrentTime + smpl->compositionOffset;
4021        mCurrentTime += smpl->duration;
4022        isSyncSample = (mCurrentSampleIndex == 0); // XXX
4023
4024        status_t err = mGroup->acquire_buffer(&mBuffer);
4025
4026        if (err != OK) {
4027            CHECK(mBuffer == NULL);
4028            ALOGV("acquire_buffer returned %d", err);
4029            return err;
4030        }
4031    }
4032
4033    const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex];
4034    const sp<MetaData> bufmeta = mBuffer->meta_data();
4035    bufmeta->clear();
4036    if (smpl->encryptedsizes.size()) {
4037        // store clear/encrypted lengths in metadata
4038        bufmeta->setData(kKeyPlainSizes, 0,
4039                smpl->clearsizes.array(), smpl->clearsizes.size() * 4);
4040        bufmeta->setData(kKeyEncryptedSizes, 0,
4041                smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4);
4042        bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size?
4043        bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
4044        bufmeta->setInt32(kKeyCryptoMode, mCryptoMode);
4045        bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
4046    }
4047
4048    if ((!mIsAVC && !mIsHEVC)|| mWantsNALFragments) {
4049        if (newBuffer) {
4050            ssize_t num_bytes_read =
4051                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
4052
4053            if (num_bytes_read < (ssize_t)size) {
4054                mBuffer->release();
4055                mBuffer = NULL;
4056
4057                ALOGV("i/o error");
4058                return ERROR_IO;
4059            }
4060
4061            CHECK(mBuffer != NULL);
4062            mBuffer->set_range(0, size);
4063            mBuffer->meta_data()->setInt64(
4064                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4065            mBuffer->meta_data()->setInt64(
4066                    kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
4067
4068            if (targetSampleTimeUs >= 0) {
4069                mBuffer->meta_data()->setInt64(
4070                        kKeyTargetTime, targetSampleTimeUs);
4071            }
4072
4073            if (isSyncSample) {
4074                mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
4075            }
4076
4077            ++mCurrentSampleIndex;
4078        }
4079
4080        if (!mIsAVC && !mIsHEVC) {
4081            *out = mBuffer;
4082            mBuffer = NULL;
4083
4084            return OK;
4085        }
4086
4087        // Each NAL unit is split up into its constituent fragments and
4088        // each one of them returned in its own buffer.
4089
4090        CHECK(mBuffer->range_length() >= mNALLengthSize);
4091
4092        const uint8_t *src =
4093            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
4094
4095        size_t nal_size = parseNALSize(src);
4096        if (mBuffer->range_length() < mNALLengthSize + nal_size) {
4097            ALOGE("incomplete NAL unit.");
4098
4099            mBuffer->release();
4100            mBuffer = NULL;
4101
4102            return ERROR_MALFORMED;
4103        }
4104
4105        MediaBuffer *clone = mBuffer->clone();
4106        CHECK(clone != NULL);
4107        clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size);
4108
4109        CHECK(mBuffer != NULL);
4110        mBuffer->set_range(
4111                mBuffer->range_offset() + mNALLengthSize + nal_size,
4112                mBuffer->range_length() - mNALLengthSize - nal_size);
4113
4114        if (mBuffer->range_length() == 0) {
4115            mBuffer->release();
4116            mBuffer = NULL;
4117        }
4118
4119        *out = clone;
4120
4121        return OK;
4122    } else {
4123        ALOGV("whole NAL");
4124        // Whole NAL units are returned but each fragment is prefixed by
4125        // the start code (0x00 00 00 01).
4126        ssize_t num_bytes_read = 0;
4127        int32_t drm = 0;
4128        bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0);
4129        if (usesDRM) {
4130            num_bytes_read =
4131                mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size);
4132        } else {
4133            num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size);
4134        }
4135
4136        if (num_bytes_read < (ssize_t)size) {
4137            mBuffer->release();
4138            mBuffer = NULL;
4139
4140            ALOGV("i/o error");
4141            return ERROR_IO;
4142        }
4143
4144        if (usesDRM) {
4145            CHECK(mBuffer != NULL);
4146            mBuffer->set_range(0, size);
4147
4148        } else {
4149            uint8_t *dstData = (uint8_t *)mBuffer->data();
4150            size_t srcOffset = 0;
4151            size_t dstOffset = 0;
4152
4153            while (srcOffset < size) {
4154                bool isMalFormed = (srcOffset + mNALLengthSize > size);
4155                size_t nalLength = 0;
4156                if (!isMalFormed) {
4157                    nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
4158                    srcOffset += mNALLengthSize;
4159                    isMalFormed = srcOffset + nalLength > size;
4160                }
4161
4162                if (isMalFormed) {
4163                    ALOGE("Video is malformed");
4164                    mBuffer->release();
4165                    mBuffer = NULL;
4166                    return ERROR_MALFORMED;
4167                }
4168
4169                if (nalLength == 0) {
4170                    continue;
4171                }
4172
4173                CHECK(dstOffset + 4 <= mBuffer->size());
4174
4175                dstData[dstOffset++] = 0;
4176                dstData[dstOffset++] = 0;
4177                dstData[dstOffset++] = 0;
4178                dstData[dstOffset++] = 1;
4179                memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
4180                srcOffset += nalLength;
4181                dstOffset += nalLength;
4182            }
4183            CHECK_EQ(srcOffset, size);
4184            CHECK(mBuffer != NULL);
4185            mBuffer->set_range(0, dstOffset);
4186        }
4187
4188        mBuffer->meta_data()->setInt64(
4189                kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
4190        mBuffer->meta_data()->setInt64(
4191                kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale);
4192
4193        if (targetSampleTimeUs >= 0) {
4194            mBuffer->meta_data()->setInt64(
4195                    kKeyTargetTime, targetSampleTimeUs);
4196        }
4197
4198        if (isSyncSample) {
4199            mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
4200        }
4201
4202        ++mCurrentSampleIndex;
4203
4204        *out = mBuffer;
4205        mBuffer = NULL;
4206
4207        return OK;
4208    }
4209}
4210
4211MPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix(
4212        const char *mimePrefix) {
4213    for (Track *track = mFirstTrack; track != NULL; track = track->next) {
4214        const char *mime;
4215        if (track->meta != NULL
4216                && track->meta->findCString(kKeyMIMEType, &mime)
4217                && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) {
4218            return track;
4219        }
4220    }
4221
4222    return NULL;
4223}
4224
4225static bool LegacySniffMPEG4(
4226        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
4227    uint8_t header[8];
4228
4229    ssize_t n = source->readAt(4, header, sizeof(header));
4230    if (n < (ssize_t)sizeof(header)) {
4231        return false;
4232    }
4233
4234    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
4235        || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8)
4236        || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8)
4237        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)
4238        || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
4239        || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
4240        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
4241        *confidence = 0.4;
4242
4243        return true;
4244    }
4245
4246    return false;
4247}
4248
4249static bool isCompatibleBrand(uint32_t fourcc) {
4250    static const uint32_t kCompatibleBrands[] = {
4251        FOURCC('i', 's', 'o', 'm'),
4252        FOURCC('i', 's', 'o', '2'),
4253        FOURCC('a', 'v', 'c', '1'),
4254        FOURCC('h', 'v', 'c', '1'),
4255        FOURCC('h', 'e', 'v', '1'),
4256        FOURCC('3', 'g', 'p', '4'),
4257        FOURCC('m', 'p', '4', '1'),
4258        FOURCC('m', 'p', '4', '2'),
4259
4260        // Won't promise that the following file types can be played.
4261        // Just give these file types a chance.
4262        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
4263        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
4264
4265        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
4266        FOURCC('3', 'g', '2', 'b'),
4267    };
4268
4269    for (size_t i = 0;
4270         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
4271         ++i) {
4272        if (kCompatibleBrands[i] == fourcc) {
4273            return true;
4274        }
4275    }
4276
4277    return false;
4278}
4279
4280// Attempt to actually parse the 'ftyp' atom and determine if a suitable
4281// compatible brand is present.
4282// Also try to identify where this file's metadata ends
4283// (end of the 'moov' atom) and report it to the caller as part of
4284// the metadata.
4285static bool BetterSniffMPEG4(
4286        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4287        sp<AMessage> *meta) {
4288    // We scan up to 128 bytes to identify this file as an MP4.
4289    static const off64_t kMaxScanOffset = 128ll;
4290
4291    off64_t offset = 0ll;
4292    bool foundGoodFileType = false;
4293    off64_t moovAtomEndOffset = -1ll;
4294    bool done = false;
4295
4296    while (!done && offset < kMaxScanOffset) {
4297        uint32_t hdr[2];
4298        if (source->readAt(offset, hdr, 8) < 8) {
4299            return false;
4300        }
4301
4302        uint64_t chunkSize = ntohl(hdr[0]);
4303        uint32_t chunkType = ntohl(hdr[1]);
4304        off64_t chunkDataOffset = offset + 8;
4305
4306        if (chunkSize == 1) {
4307            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
4308                return false;
4309            }
4310
4311            chunkSize = ntoh64(chunkSize);
4312            chunkDataOffset += 8;
4313
4314            if (chunkSize < 16) {
4315                // The smallest valid chunk is 16 bytes long in this case.
4316                return false;
4317            }
4318        } else if (chunkSize < 8) {
4319            // The smallest valid chunk is 8 bytes long.
4320            return false;
4321        }
4322
4323        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
4324
4325        char chunkstring[5];
4326        MakeFourCCString(chunkType, chunkstring);
4327        ALOGV("saw chunk type %s, size %" PRIu64 " @ %lld", chunkstring, chunkSize, offset);
4328        switch (chunkType) {
4329            case FOURCC('f', 't', 'y', 'p'):
4330            {
4331                if (chunkDataSize < 8) {
4332                    return false;
4333                }
4334
4335                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
4336                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
4337                    if (i == 1) {
4338                        // Skip this index, it refers to the minorVersion,
4339                        // not a brand.
4340                        continue;
4341                    }
4342
4343                    uint32_t brand;
4344                    if (source->readAt(
4345                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
4346                        return false;
4347                    }
4348
4349                    brand = ntohl(brand);
4350
4351                    if (isCompatibleBrand(brand)) {
4352                        foundGoodFileType = true;
4353                        break;
4354                    }
4355                }
4356
4357                if (!foundGoodFileType) {
4358                    return false;
4359                }
4360
4361                break;
4362            }
4363
4364            case FOURCC('m', 'o', 'o', 'v'):
4365            {
4366                moovAtomEndOffset = offset + chunkSize;
4367
4368                done = true;
4369                break;
4370            }
4371
4372            default:
4373                break;
4374        }
4375
4376        offset += chunkSize;
4377    }
4378
4379    if (!foundGoodFileType) {
4380        return false;
4381    }
4382
4383    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
4384    *confidence = 0.4f;
4385
4386    if (moovAtomEndOffset >= 0) {
4387        *meta = new AMessage;
4388        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
4389
4390        ALOGV("found metadata size: %lld", moovAtomEndOffset);
4391    }
4392
4393    return true;
4394}
4395
4396bool SniffMPEG4(
4397        const sp<DataSource> &source, String8 *mimeType, float *confidence,
4398        sp<AMessage> *meta) {
4399    if (BetterSniffMPEG4(source, mimeType, confidence, meta)) {
4400        return true;
4401    }
4402
4403    if (LegacySniffMPEG4(source, mimeType, confidence)) {
4404        ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
4405        return true;
4406    }
4407
4408    return false;
4409}
4410
4411}  // namespace android
4412