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, ×cale, 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