MPEG4Extractor.cpp revision 0a69bd281c76bf777ddb51d0c6c08519634b192d
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/* 220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project 320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License. 620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at 720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * 1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software 1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and 1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License. 1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */ 1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen//#define LOG_NDEBUG 0 1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define LOG_TAG "MPEG4Extractor" 1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h> 2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2166326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber#include "include/MPEG4Extractor.h" 2289e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber#include "include/SampleTable.h" 237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include "include/ESDS.h" 2489e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber 2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h> 2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdint.h> 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdlib.h> 2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <string.h> 2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#include <media/stagefright/foundation/ABitReader.h> 31d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson#include <media/stagefright/foundation/ABuffer.h> 32ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#include <media/stagefright/foundation/ADebug.h> 33a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber#include <media/stagefright/foundation/AMessage.h> 3420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h> 3618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h> 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource { 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Caller retains ownership of both "dataSource" and "sampleTable". 46693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber MPEG4Source(const sp<MetaData> &format, 47693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &dataSource, 4848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int32_t timeScale, 4905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const sp<SampleTable> &sampleTable, 5005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<SidxEntry> &sidx, 5105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t firstMoofOffset); 5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual status_t start(MetaData *params = NULL); 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual status_t stop(); 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual sp<MetaData> getFormat(); 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL); 5905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL); 6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 61693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected: 62693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber virtual ~MPEG4Source(); 63693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 657b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex mLock; 667b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mFormat; 68693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<DataSource> mDataSource; 6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t mTimescale; 70693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<SampleTable> mSampleTable; 7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t mCurrentSampleIndex; 7205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mCurrentFragmentIndex; 7305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<SidxEntry> &mSegments; 7405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t mFirstMoofOffset; 7505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t mCurrentMoofOffset; 7605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t mNextMoofOffset; 7705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mCurrentTime; 7805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t mLastParsedTrackId; 7905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t mTrackId; 8020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int32_t mCryptoMode; // passed in from extractor 82ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int32_t mDefaultIVSize; // passed in from extractor 83ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t mCryptoKey[16]; // passed in from extractor 84ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentAuxInfoType; 85ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentAuxInfoTypeParameter; 8648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen int32_t mCurrentDefaultSampleInfoSize; 87ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentSampleInfoCount; 88ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentSampleInfoAllocSize; 89ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t* mCurrentSampleInfoSizes; 90ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentSampleInfoOffsetCount; 91ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentSampleInfoOffsetsAllocSize; 92ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint64_t* mCurrentSampleInfoOffsets; 93ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 9420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool mIsAVC; 956064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t mNALLengthSize; 966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool mStarted; 9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBufferGroup *mGroup; 10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *mBuffer; 10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 103dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber bool mWantsNALFragments; 10420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1050024245e134467d120b40099da16c467dc365e76Andreas Huber uint8_t *mSrcBuffer; 1060024245e134467d120b40099da16c467dc365e76Andreas Huber 1076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t parseNALSize(const uint8_t *data) const; 10805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t parseChunk(off64_t *offset); 10905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t parseTrackFragmentHeader(off64_t offset, off64_t size); 11005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t parseTrackFragmentRun(off64_t offset, off64_t size); 111ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size); 112ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size); 11305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 11405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen struct TrackFragmentHeaderInfo { 11505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen enum Flags { 11605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kBaseDataOffsetPresent = 0x01, 11705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleDescriptionIndexPresent = 0x02, 11805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDefaultSampleDurationPresent = 0x08, 11905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDefaultSampleSizePresent = 0x10, 12005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDefaultSampleFlagsPresent = 0x20, 12105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDurationIsEmpty = 0x10000, 12205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 12305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 12405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mTrackID; 12505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mFlags; 12605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t mBaseDataOffset; 12705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mSampleDescriptionIndex; 12805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mDefaultSampleDuration; 12905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mDefaultSampleSize; 13005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mDefaultSampleFlags; 13105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 13205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t mDataOffset; 13305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen TrackFragmentHeaderInfo mTrackFragmentHeaderInfo; 13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen struct Sample { 13705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t offset; 13805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t size; 13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t duration; 140ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t iv[16]; 141ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen Vector<size_t> clearsizes; 142ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen Vector<size_t> encryptedsizes; 14305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 14405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<Sample> mCurrentSamples; 1456064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 14620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Source(const MPEG4Source &); 14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Source &operator=(const MPEG4Source &); 14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests 15150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding 15250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource. 15350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track, 15450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e. 15550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track. 15650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 15750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource { 15850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber MPEG4DataSource(const sp<DataSource> &source); 15950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 16050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual status_t initCheck() const; 161c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong virtual ssize_t readAt(off64_t offset, void *data, size_t size); 162c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong virtual status_t getSize(off64_t *size); 16350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual uint32_t flags(); 16450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 165c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong status_t setCachedRange(off64_t offset, size_t size); 16650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected: 16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual ~MPEG4DataSource(); 16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate: 17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber Mutex mLock; 17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber sp<DataSource> mSource; 174c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t mCachedOffset; 17550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber size_t mCachedSize; 17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber uint8_t *mCache; 17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber void clearCache(); 17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber MPEG4DataSource(const MPEG4DataSource &); 18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber MPEG4DataSource &operator=(const MPEG4DataSource &); 18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}; 18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source) 18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber : mSource(source), 18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedOffset(0), 18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedSize(0), 18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCache(NULL) { 18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() { 19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber clearCache(); 19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() { 19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (mCache) { 19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber free(mCache); 19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCache = NULL; 19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 20150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedOffset = 0; 20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedSize = 0; 20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const { 20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->initCheck(); 20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 209c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) { 21050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber Mutex::Autolock autoLock(mLock); 21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 21250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (offset >= mCachedOffset 21350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber && offset + size <= mCachedOffset + mCachedSize) { 21450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber memcpy(data, &mCache[offset - mCachedOffset], size); 21550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return size; 21650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 21750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 21850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->readAt(offset, data, size); 21950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 22050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 221c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::getSize(off64_t *size) { 22250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->getSize(size); 22350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 22450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 22550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() { 22650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->flags(); 22750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 22850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 229c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) { 23050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber Mutex::Autolock autoLock(mLock); 23150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 23250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber clearCache(); 23350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 23450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCache = (uint8_t *)malloc(size); 23550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 23650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (mCache == NULL) { 23750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return -ENOMEM; 23850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 23950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 24050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedOffset = offset; 24150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedSize = size; 24250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 24350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize); 24450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 24550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (err < (ssize_t)size) { 24650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber clearCache(); 24750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 24850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return ERROR_IO; 24950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 25050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 25150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return OK; 25250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 25350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 25450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber//////////////////////////////////////////////////////////////////////////////// 25550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 25620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) { 25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *data = (const uint8_t *)_data; 25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t offset = 0; 25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (offset < size) { 26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("0x%04x ", offset); 26120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = size - offset; 26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (n > 16) { 26420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber n = 16; 26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 26620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (size_t i = 0; i < 16; ++i) { 26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (i == 8) { 26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf(" "); 27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (offset + i < size) { 27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("%02x ", data[offset + i]); 27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf(" "); 27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf(" "); 28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (size_t i = 0; i < n; ++i) { 28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (isprint(data[offset + i])) { 28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("%c", data[offset + i]); 28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("."); 28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("\n"); 29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber offset += 16; 29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) { 29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber switch (fourcc) { 29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'a'): 29818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_AUDIO_AAC; 29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 30118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_AUDIO_AMR_NB; 30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 303371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber case FOURCC('s', 'a', 'w', 'b'): 30418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_AUDIO_AMR_WB; 305371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber 30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'v'): 30718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_VIDEO_MPEG4; 30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', '2', '6', '3'): 310e071b055cee301d71335519601474c62b10af411James Dong case FOURCC('h', '2', '6', '3'): 311e071b055cee301d71335519601474c62b10af411James Dong case FOURCC('H', '2', '6', '3'): 31218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_VIDEO_H263; 31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', '1'): 31518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_VIDEO_AVC; 31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber default: 318dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(!"should not be here."); 31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) { 32448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) { 32548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // AMR NB audio is always mono, 8kHz 32648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen *channels = 1; 32748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen *rate = 8000; 32848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return true; 32948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) { 33048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // AMR WB audio is always mono, 16kHz 33148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen *channels = 1; 33248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen *rate = 16000; 33348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return true; 33448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 33548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return false; 33648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen} 33748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 338693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source) 33905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen : mSidxDuration(0), 34005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mMoofOffset(0), 34105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mDataSource(source), 342bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber mInitCheck(NO_INIT), 3437be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber mHasVideo(false), 34420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFirstTrack(NULL), 34572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mLastTrack(NULL), 346dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mFileMetaData(new MetaData), 347dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mFirstSINF(NULL), 348dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mIsDrm(false) { 34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() { 35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (track) { 35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *next = track->next; 35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete track; 35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = next; 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFirstTrack = mLastTrack = NULL; 360dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 361dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *sinf = mFirstSINF; 362dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (sinf) { 363dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *next = sinf->next; 364dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang delete sinf->IPMPData; 365dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang delete sinf; 366dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf = next; 367dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 368dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mFirstSINF = NULL; 369ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 370ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mPssh.size(); i++) { 371ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen delete [] mPssh[i].data; 372ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenuint32_t MPEG4Extractor::flags() const { 37605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return CAN_PAUSE | 37705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ((mMoofOffset == 0 || mSidxEntries.size() != 0) ? 37805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0); 37905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 38005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 3817be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() { 3827be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber status_t err; 3837be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber if ((err = readMetaData()) != OK) { 38472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return new MetaData; 3857be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber } 3867be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 38772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return mFileMetaData; 3887be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber} 3897be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 390693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() { 39120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 393ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("MPEG4Extractor::countTracks: no tracks"); 394693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return 0; 39520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 397693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber size_t n = 0; 39820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (track) { 400693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber ++n; 40120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 404ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("MPEG4Extractor::countTracks: %d tracks", n); 405693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return n; 40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4087e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData( 4097e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber size_t index, uint32_t flags) { 41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (index > 0) { 41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (track == NULL) { 41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber --index; 42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 425371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber if (track == NULL) { 426371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber return NULL; 427371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber } 428371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber 4297e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber if ((flags & kIncludeExtensiveMetaData) 4307e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber && !track->includes_expensive_metadata) { 4317e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber track->includes_expensive_metadata = true; 4327e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 4337e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber const char *mime; 4347e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 4357e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber if (!strncasecmp("video/", mime, 6)) { 43605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mMoofOffset > 0) { 43705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t duration; 43805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (track->meta->findInt64(kKeyDuration, &duration)) { 43905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // nothing fancy, just pick a frame near 1/4th of the duration 44005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen track->meta->setInt64( 44105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyThumbnailTime, duration / 4); 44205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 44305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 44405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleIndex; 44505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleTime; 44605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK 44705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen && track->sampleTable->getMetaDataForSample( 44805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleIndex, NULL /* offset */, NULL /* size */, 44905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen &sampleTime) == OK) { 45005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen track->meta->setInt64( 45105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyThumbnailTime, 45205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ((int64_t)sampleTime * 1000000) / track->timescale); 45305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 4547e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 4557e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 4567e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 4577e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 45820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return track->meta; 45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 46148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) { 46248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[0] = x >> 24; 46348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[1] = (x >> 16) & 0xff; 46448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[2] = (x >> 8) & 0xff; 46548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[3] = x & 0xff; 46648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[4] = '\0'; 46748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen} 46848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 46920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() { 470bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber if (mInitCheck != NO_INIT) { 471bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return mInitCheck; 47220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 474c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = 0; 47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 47605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen while (true) { 47705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen err = parseChunk(&offset, 0); 47805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (err == OK) { 47905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen continue; 48005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 48105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 48205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t hdr[2]; 48305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mDataSource->readAt(offset, hdr, 8) < 8) { 48405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 48505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 48605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t chunk_type = ntohl(hdr[1]); 48705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_type == FOURCC('s', 'i', 'd', 'x')) { 48805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // parse the sidx box too 48905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen continue; 49005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (chunk_type == FOURCC('m', 'o', 'o', 'f')) { 49105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // store the offset of the first segment 49205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mMoofOffset = offset; 49305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 49405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 49520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 4967be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 497bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber if (mInitCheck == OK) { 49872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mHasVideo) { 499bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber mFileMetaData->setCString( 500bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4); 50172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 50272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyMIMEType, "audio/mp4"); 50372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 50472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 5054678a6dc5f09008481524949a9667af5a6190374Andreas Huber mInitCheck = OK; 506bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber } else { 507bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber mInitCheck = err; 50820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 510bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber CHECK_NE(err, (status_t)NO_INIT); 511ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 512ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // copy pssh data into file metadata 513ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int psshsize = 0; 514ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mPssh.size(); i++) { 515ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen psshsize += 20 + mPssh[i].datalen; 516ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 517ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (psshsize) { 518ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen char *buf = (char*)malloc(psshsize); 519ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen char *ptr = buf; 520ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mPssh.size(); i++) { 521ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memcpy(ptr, mPssh[i].uuid, 20); // uuid + length 522ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen); 523ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ptr += (20 + mPssh[i].datalen); 524ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 525ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize); 526ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen free(buf); 527ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 528bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return mInitCheck; 52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 531dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) { 532dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mFirstSINF == NULL) { 533dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return NULL; 534dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 535dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 536dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *sinf = mFirstSINF; 537dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (sinf && (trackID != sinf->trackID)) { 538dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf = sinf->next; 539dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 540dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 541dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (sinf == NULL) { 542dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return NULL; 543dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 544dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 545dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang *len = sinf->len; 546dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return sinf->IPMPData; 547dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang} 548dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 549dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear. 55056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic int32_t readSize(off64_t offset, 551dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang const sp<DataSource> DataSource, uint8_t *numOfBytes) { 552dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint32_t size = 0; 553dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t data; 554dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang bool moreData = true; 555dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang *numOfBytes = 0; 556dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 557dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (moreData) { 558dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (DataSource->readAt(offset, &data, 1) < 1) { 559dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return -1; 560dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 561dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang offset ++; 562dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang moreData = (data >= 128) ? true : false; 563dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size = (size << 7) | (data & 0x7f); // Take last 7 bits 564dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang (*numOfBytes) ++; 565dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 566dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 567dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return size; 568dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang} 569dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 570c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) { 571dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t updateIdTag; 572dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) { 573dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 574dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 575dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 576dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 577dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) { 578dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 579dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 580dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 581dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t numOfBytes; 582dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t size = readSize(data_offset, mDataSource, &numOfBytes); 583dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (size < 0) { 584dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 585dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 586dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t classSize = size; 587dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += numOfBytes; 588dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 589dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while(size >= 11 ) { 590dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t descriptorTag; 591dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) { 592dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 593dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 594dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 595dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 596dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) { 597dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 598dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 599dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 600dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t buffer[8]; 601dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang //ObjectDescriptorID and ObjectDescriptor url flag 602dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, buffer, 2) < 2) { 603dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 604dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 605dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += 2; 606dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 607dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if ((buffer[1] >> 5) & 0x0001) { //url flag is set 608dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 609dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 610dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 611dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, buffer, 8) < 8) { 612dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 613dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 614dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += 8; 615dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 616dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1]) 617dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) { 618dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 619dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 620dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 621dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *sinf = new SINF; 622dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->trackID = U16_AT(&buffer[3]); 623dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->IPMPDescriptorID = buffer[7]; 624dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->next = mFirstSINF; 625dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mFirstSINF = sinf; 626dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 627dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size -= (8 + 2 + 1); 628dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 629dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 630dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (size != 0) { 631dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 632dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 633dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 634dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) { 635dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 636dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 637dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 638dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 639dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) { 640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size = readSize(data_offset, mDataSource, &numOfBytes); 644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (size < 0) { 645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang classSize = size; 648dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += numOfBytes; 649dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 650dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (size > 0) { 651dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t tag; 652dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t dataLen; 653dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &tag, 1) < 1) { 654dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 655dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 656dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) { 659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t id; 660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dataLen = readSize(data_offset, mDataSource, &numOfBytes); 661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (dataLen < 0) { 662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else if (dataLen < 4) { 664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += numOfBytes; 667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &id, 1) < 1) { 669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 672dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 673dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *sinf = mFirstSINF; 674dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (sinf && (sinf->IPMPDescriptorID != id)) { 675dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf = sinf->next; 676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (sinf == NULL) { 678dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->len = dataLen - 3; 681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->IPMPData = new char[sinf->len]; 682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) { 684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += sinf->len; 687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size -= (dataLen + numOfBytes + 1); 689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (size != 0) { 693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return UNKNOWN_ERROR; // Return a dummy error. 697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang} 698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 69972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder { 70072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder(Vector<uint32_t> *path, uint32_t chunkType) 70172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber : mPath(path) { 70272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mPath->push(chunkType); 70372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 70472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 70572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber ~PathAdder() { 70672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mPath->pop(); 70772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 70872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 70972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate: 71072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber Vector<uint32_t> *mPath; 71172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 71272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder(const PathAdder &); 71372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder &operator=(const PathAdder &); 71472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}; 71572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 71672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) { 71772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return path.size() >= 5 71872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[0] == FOURCC('m', 'o', 'o', 'v') 71972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[1] == FOURCC('u', 'd', 't', 'a') 72072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[2] == FOURCC('m', 'e', 't', 'a') 72172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[3] == FOURCC('i', 'l', 's', 't'); 72272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 72372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 72472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string. 72572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) { 72672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600); 72772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 72872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char tmp[32]; 72972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970)); 73072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 73172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber s->setTo(tmp); 73272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 73372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 734c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { 7355d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen ALOGV("entering parseChunk %lld/%d", *offset, depth); 73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t hdr[2]; 73734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt(*offset, hdr, 8) < 8) { 73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint64_t chunk_size = ntohl(hdr[0]); 74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t chunk_type = ntohl(hdr[1]); 742c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t data_offset = *offset + 8; 74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_size == 1) { 74534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { 74620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_size = ntoh64(chunk_size); 74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset += 8; 75071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber 75171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber if (chunk_size < 16) { 75271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber // The smallest valid chunk is 16 bytes long in this case. 75371b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber return ERROR_MALFORMED; 75471b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber } 75571b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber } else if (chunk_size < 8) { 75671b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber // The smallest valid chunk is 8 bytes long. 75771b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber return ERROR_MALFORMED; 75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber char chunk[5]; 76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MakeFourCCString(chunk_type, chunk); 76205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth); 76320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0 76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const char kWhitespace[] = " "; 76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth]; 76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size); 76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber char buffer[256]; 770ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber size_t n = chunk_size; 771ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber if (n > sizeof(buffer)) { 772ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber n = sizeof(buffer); 773ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber } 774ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber if (mDataSource->readAt(*offset, buffer, n) 775ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber < (ssize_t)n) { 776ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber return ERROR_IO; 77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 778ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber 779ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber hexdump(buffer, n); 78020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif 78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder autoAdder(&mPath, chunk_type); 78372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 784c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t chunk_data_size = *offset + chunk_size - data_offset; 78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (chunk_type != FOURCC('c', 'p', 'r', 't') 787515e855eae78aa495da58356486aaa666cb57fd1James Dong && chunk_type != FOURCC('c', 'o', 'v', 'r') 78872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && mPath.size() == 5 && underMetaDataPath(mPath)) { 789c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 79072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset = data_offset; 79172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber while (*offset < stop_offset) { 79272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseChunk(offset, depth + 1); 79372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 79472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 79572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 79672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 797bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 798bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 799bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 800bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 80172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 80272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return OK; 80372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 80472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber switch(chunk_type) { 80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'o', 'o', 'v'): 80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'r', 'a', 'k'): 80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'd', 'i', 'a'): 80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'i', 'n', 'f'): 81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('d', 'i', 'n', 'f'): 81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'b', 'l'): 81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'v', 'e', 'x'): 81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'o', 'o', 'f'): 81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'r', 'a', 'f'): 81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'f', 'r', 'a'): 81672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('u', 'd', 't', 'a'): 81772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('i', 'l', 's', 't'): 818ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'i', 'n', 'f'): 819ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'c', 'h', 'i'): 8200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen case FOURCC('e', 'd', 't', 's'): 82120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 82250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (chunk_type == FOURCC('s', 't', 'b', 'l')) { 8233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size); 82450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 825b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber if (mDataSource->flags() 826b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber & (DataSource::kWantsPrefetching 827b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber | DataSource::kIsCachingDataSource)) { 82850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber sp<MPEG4DataSource> cachedSource = 82950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber new MPEG4DataSource(mDataSource); 83050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 83150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (cachedSource->setCachedRange(*offset, chunk_size) == OK) { 83250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mDataSource = cachedSource; 83350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 83450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 8351edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber 8361edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber mLastTrack->sampleTable = new SampleTable(mDataSource); 83750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 83850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 8396f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber bool isTrack = false; 840bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (chunk_type == FOURCC('t', 'r', 'a', 'k')) { 8416f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber isTrack = true; 8426f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 843bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber Track *track = new Track; 844bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->next = NULL; 845bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (mLastTrack) { 846bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber mLastTrack->next = track; 847bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else { 848bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber mFirstTrack = track; 849bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 850bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber mLastTrack = track; 851bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 852bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->meta = new MetaData; 853bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->includes_expensive_metadata = false; 8546f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber track->skipTrack = false; 855bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->timescale = 0; 856bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->meta->setCString(kKeyMIMEType, "application/octet-stream"); 857bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 858bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 859c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset; 86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 86220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 86320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 86420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 86520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 86720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 868bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 869bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 870bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 871bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 8726f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber if (isTrack) { 8736f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber if (mLastTrack->skipTrack) { 8746f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber Track *cur = mFirstTrack; 8756f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 8766f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber if (cur == mLastTrack) { 8776f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber delete cur; 8786f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber mFirstTrack = mLastTrack = NULL; 8796f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } else { 8806f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber while (cur && cur->next != mLastTrack) { 8816f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber cur = cur->next; 8826f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } 8836f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber cur->next = NULL; 8846f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber delete mLastTrack; 8856f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber mLastTrack = cur; 8866f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } 8876f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 8886f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber return OK; 8896f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } 8906f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 891bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber status_t err = verifyTrack(mLastTrack); 892bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 893bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (err != OK) { 894bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return err; 895bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 896bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { 897bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber mInitCheck = OK; 89820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 899dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (!mIsDrm) { 900dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return UNKNOWN_ERROR; // Return a dummy error. 901dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else { 902dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return OK; 903dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9080a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen case FOURCC('e', 'l', 's', 't'): 9090a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen { 9100a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen // See 14496-12 8.6.6 9110a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint8_t version; 9120a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (mDataSource->readAt(data_offset, &version, 1) < 1) { 9130a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9140a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9150a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9160a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint32_t entry_count; 9170a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) { 9180a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9190a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (entry_count != 1) { 9220a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen // we only support a single entry at the moment, for gapless playback 9230a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen ALOGW("ignoring edit list with %d entries", entry_count); 9240a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } else { 9250a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen off64_t entriesoffset = data_offset + 8; 9260a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint64_t segment_duration; 9270a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t media_time; 9280a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9290a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (version == 1) { 9300a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (!mDataSource->getUInt64(entriesoffset, &segment_duration) || 9310a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) { 9320a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9330a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9340a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } else if (version == 0) { 9350a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint32_t sd; 9360a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int32_t mt; 9370a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (!mDataSource->getUInt32(entriesoffset, &sd) || 9380a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) { 9390a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9400a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9410a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen segment_duration = sd; 9420a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen media_time = mt; 9430a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } else { 9440a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9450a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9460a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9470a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint64_t halfscale = mLastTrack->timescale / 2; 9480a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen segment_duration = (segment_duration * 1000000 + halfscale)/ mLastTrack->timescale; 9490a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen media_time = (media_time * 1000000 + halfscale) / mLastTrack->timescale; 9500a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9510a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t duration; 9520a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int32_t samplerate; 9530a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (mLastTrack->meta->findInt64(kKeyDuration, &duration) && 9540a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) { 9550a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9560a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t delay = (media_time * samplerate + 500000) / 1000000; 9570a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen mLastTrack->meta->setInt32(kKeyEncoderDelay, delay); 9580a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9590a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t paddingus = duration - (segment_duration + media_time); 9600a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000; 9610a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples); 9620a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen *offset += chunk_size; 9650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen break; 9660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9670a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 968ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('f', 'r', 'm', 'a'): 969ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen { 97048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t original_fourcc; 971ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) { 972ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 973ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 974ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen original_fourcc = ntohl(original_fourcc); 975ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("read original format: %d", original_fourcc); 976ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc)); 97748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t num_channels = 0; 97848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t sample_rate = 0; 97948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) { 98048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 98148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 98248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 983ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 984ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 985ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 986ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 987ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('t', 'e', 'n', 'c'): 988ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen { 989ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (chunk_size < 32) { 990ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 991ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 992ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 993ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte 994ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // default IV size, 16 bytes default KeyID 995ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // (ISO 23001-7) 996ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen char buf[4]; 997ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(buf, 0, 4); 998ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) { 999ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1000ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1001ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf)); 1002ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (defaultAlgorithmId > 1) { 1003ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // only 0 (clear) and 1 (AES-128) are valid 1004ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1005ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1006ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1007ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(buf, 0, 4); 1008ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) { 1009ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1010ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1011ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t defaultIVSize = ntohl(*((int32_t*)buf)); 1012ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1013ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if ((defaultAlgorithmId == 0 && defaultIVSize != 0) || 1014ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen (defaultAlgorithmId != 0 && defaultIVSize == 0)) { 1015ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // only unencrypted data must have 0 IV size 1016ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1017ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } else if (defaultIVSize != 0 && 1018ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen defaultIVSize != 8 && 1019ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen defaultIVSize != 16) { 1020ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // only supported sizes are 0, 8 and 16 1021ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1022ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1024ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t defaultKeyId[16]; 1025ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1026ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) { 1027ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1028ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId); 1031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize); 1032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16); 1033ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 1034ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 1035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 103720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'k', 'h', 'd'): 103820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 1039ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber status_t err; 1040ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) { 1041ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return err; 104220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 104320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 104420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 104720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1048ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('p', 's', 's', 'h'): 1049ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen { 1050ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen PsshInfo pssh; 1051ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1052ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) { 1053ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1054ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1055ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t psshdatalen = 0; 1057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) { 1058ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1060ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen pssh.datalen = ntohl(psshdatalen); 1061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("pssh data size: %d", pssh.datalen); 1062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (pssh.datalen + 20 > chunk_size) { 1063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // pssh data length exceeds size of containing box 1064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen pssh.data = new uint8_t[pssh.datalen]; 1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("allocated pssh @ %p", pssh.data); 1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ssize_t requested = (ssize_t) pssh.datalen; 1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) { 1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mPssh.push_back(pssh); 1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 107920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'd', 'h', 'd'): 108020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 108120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 4) { 108220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 108320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 108420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 108520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t version; 108634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 108720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, &version, sizeof(version)) 108820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(version)) { 108920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 109020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 109120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1092c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t timescale_offset; 109320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 109420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (version == 1) { 109520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset = data_offset + 4 + 16; 109620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else if (version == 0) { 109720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset = data_offset + 4 + 8; 109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 110020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 110120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t timescale; 110334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset, ×cale, sizeof(timescale)) 110520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(timescale)) { 110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->timescale = ntohl(timescale); 111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 111105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t duration = 0; 111220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (version == 1) { 111334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 111420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset + 4, &duration, sizeof(duration)) 111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(duration)) { 111620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 111720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 111820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber duration = ntoh64(duration); 111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 112005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t duration32; 112134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 112220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset + 4, &duration32, sizeof(duration32)) 112320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(duration32)) { 112420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 112520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 112605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // ffmpeg sets duration to -1, which is incorrect. 112705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (duration32 != 0xffffffff) { 112805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen duration = ntohl(duration32); 112905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 113020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 113148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mLastTrack->meta->setInt64( 113248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber kKeyDuration, (duration * 1000000) / mLastTrack->timescale); 113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11347a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang uint8_t lang[2]; 11357a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang off64_t lang_offset; 11367a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang if (version == 1) { 11377a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_offset = timescale_offset + 4 + 8; 11387a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } else if (version == 0) { 11397a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_offset = timescale_offset + 4 + 4; 11407a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } else { 11417a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang return ERROR_IO; 11427a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 11437a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 11447a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang if (mDataSource->readAt(lang_offset, &lang, sizeof(lang)) 11457a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang < (ssize_t)sizeof(lang)) { 11467a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang return ERROR_IO; 11477a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 11487a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 11497a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // To get the ISO-639-2/T three character language code 11507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // 1 bit pad followed by 3 5-bits characters. Each character 11517a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // is packed as the difference between its ASCII value and 0x60. 11527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang char lang_code[4]; 11537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60; 11547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60; 11557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[2] = (lang[1] & 0x1f) + 0x60; 11567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[3] = '\0'; 11577a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 11587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang mLastTrack->meta->setCString( 11597a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang kKeyMediaLanguage, lang_code); 11607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 116220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 116320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'd'): 116620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 8) { 116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[8]; 1172c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (chunk_data_size < (off64_t)sizeof(buffer)) { 1173bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1174bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 1175bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 117634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, 8) < 8) { 117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (U32_AT(buffer) != 0) { 118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Should be version 0, flags 0. 118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t entry_count = U32_AT(&buffer[4]); 118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (entry_count > 1) { 11893b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // For 3GPP timed text, there could be multiple tx3g boxes contain 11903b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // multiple text display formats. These formats will be used to 11913b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // display the timed text. 1192ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // For encrypted files, there may also be more than one entry. 11933b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang const char *mime; 11943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 1195ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) && 1196ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen strcasecmp(mime, "application/octet-stream")) { 11973b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // For now we only support a single type of media per track. 11983b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang mLastTrack->skipTrack = true; 11993b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang *offset += chunk_size; 12003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang break; 12013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1203c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + 8; 120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (uint32_t i = 0; i < entry_count; ++i) { 120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 121020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1211bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1212bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1213bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1214bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'a'): 121948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen case FOURCC('e', 'n', 'c', 'a'): 122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 1221371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber case FOURCC('s', 'a', 'w', 'b'): 122220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 122320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[8 + 20]; 122420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Basic AudioSampleEntry size. 122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 122934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 123548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t num_channels = U16_AT(&buffer[16]); 123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint16_t sample_size = U16_AT(&buffer[18]); 123881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint32_t sample_rate = U32_AT(&buffer[24]) >> 16; 123981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 124048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (chunk_type != FOURCC('e', 'n', 'c', 'a')) { 124148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // if the chunk type is enca, we'll get the type from the sinf/frma box later 124248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 124348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate); 124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 124548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen ALOGV("*** coding='%s' %d channels, size %d, rate %d\n", 124681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber chunk, num_channels, sample_size, sample_rate); 124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 124920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1250c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + sizeof(buffer); 125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1258bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1259bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1260bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1261bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 126220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 126320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 126420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'v'): 1266ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('e', 'n', 'c', 'v'): 126720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', '2', '6', '3'): 1268e071b055cee301d71335519601474c62b10af411James Dong case FOURCC('H', '2', '6', '3'): 1269e071b055cee301d71335519601474c62b10af411James Dong case FOURCC('h', '2', '6', '3'): 127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', '1'): 127120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 12727be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber mHasVideo = true; 12737be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[78]; 127520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Basic VideoSampleEntry size. 127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 128034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 128120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 128320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t width = U16_AT(&buffer[6 + 18]); 128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t height = U16_AT(&buffer[6 + 20]); 128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1289ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // The video sample is not standard-compliant if it has invalid dimension. 1290a6256238d9015c42129fe43791968768fe501efaJames Dong // Use some default width and height value, and 1291a6256238d9015c42129fe43791968768fe501efaJames Dong // let the decoder figure out the actual width and height (and thus 1292a6256238d9015c42129fe43791968768fe501efaJames Dong // be prepared for INFO_FOMRAT_CHANGED event). 1293a6256238d9015c42129fe43791968768fe501efaJames Dong if (width == 0) width = 352; 1294a6256238d9015c42129fe43791968768fe501efaJames Dong if (height == 0) height = 288; 1295a6256238d9015c42129fe43791968768fe501efaJames Dong 1296134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber // printf("*** coding='%s' width=%d height=%d\n", 1297134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber // chunk, width, height); 129820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1299ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (chunk_type != FOURCC('e', 'n', 'c', 'v')) { 1300ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // if the chunk type is encv, we'll get the type from the sinf/frma box later 1301ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 1302ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyWidth, width); 130420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyHeight, height); 130520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1306c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + sizeof(buffer); 130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 130920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 131020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1314bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1315bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1316bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1317bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'c', 'o'): 132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('c', 'o', '6', '4'): 132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setChunkOffsetParams( 132620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_type, data_offset, chunk_data_size); 132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'c'): 133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSampleToChunkParams( 134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'z'): 135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'z', '2'): 135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSampleSizeParams( 135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_type, data_offset, chunk_data_size); 135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1361738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber size_t max_size; 136249110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber err = mLastTrack->sampleTable->getMaxSampleSize(&max_size); 136349110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber 136449110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber if (err != OK) { 136549110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber return err; 136649110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber } 1367738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber 136805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (max_size != 0) { 136905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // Assume that a given buffer only contains at most 10 chunks, 137005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // each chunk originally prefixed with a 2 byte length will 137105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion, 137205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // and thus will grow by 2 bytes per chunk. 137305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2); 137405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 137505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // No size was specified. Pick a conservatively large size. 137605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t width, height; 137705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mLastTrack->meta->findInt32(kKeyWidth, &width) && 137805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mLastTrack->meta->findInt32(kKeyHeight, &height)) { 137905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mLastTrack->meta->setInt32(kKeyMaxInputSize, width * height * 3 / 2); 138005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 138105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGE("No width or height, assuming worst case 1080p"); 138205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mLastTrack->meta->setInt32(kKeyMaxInputSize, 3110400); 138305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 138405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 1386113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong 1387113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong // Calculate average frame rate. 1388113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong const char *mime; 1389113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 1390113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong if (!strncasecmp("video/", mime, 6)) { 1391113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong size_t nSamples = mLastTrack->sampleTable->countSamples(); 1392113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong int64_t durationUs; 1393113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) { 1394113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong if (durationUs > 0) { 1395113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong int32_t frameRate = (nSamples * 1000000LL + 1396113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong (durationUs >> 1)) / durationUs; 1397113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong mLastTrack->meta->setInt32(kKeyFrameRate, frameRate); 1398113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong } 1399113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong } 1400113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong } 1401113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong 140220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 140320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 140420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 't', 's'): 140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setTimeToSampleParams( 140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 141020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 141220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 141420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14194931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber case FOURCC('c', 't', 't', 's'): 14204931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber { 14214931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber status_t err = 14224931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber mLastTrack->sampleTable->setCompositionTimeToSampleParams( 14234931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber data_offset, chunk_data_size); 14244931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 14254931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber if (err != OK) { 14264931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber return err; 14274931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 14284931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 14294931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber *offset += chunk_size; 14304931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber break; 14314931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 14324931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 's'): 143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 143520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 143620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSyncSampleParams( 143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 143820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 143920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 144420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 144620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14474948818cb91176df74c972ac27b2f392b5d148bcJames Dong // @xyz 14484948818cb91176df74c972ac27b2f392b5d148bcJames Dong case FOURCC('\xA9', 'x', 'y', 'z'): 14494948818cb91176df74c972ac27b2f392b5d148bcJames Dong { 14504948818cb91176df74c972ac27b2f392b5d148bcJames Dong // Best case the total data length inside "@xyz" box 14514948818cb91176df74c972ac27b2f392b5d148bcJames Dong // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/", 14524948818cb91176df74c972ac27b2f392b5d148bcJames Dong // where "\x00\x04" is the text string length with value = 4, 14534948818cb91176df74c972ac27b2f392b5d148bcJames Dong // "\0x15\xc7" is the language code = en, and "0+0" is a 14544948818cb91176df74c972ac27b2f392b5d148bcJames Dong // location (string) value with longitude = 0 and latitude = 0. 14554948818cb91176df74c972ac27b2f392b5d148bcJames Dong if (chunk_data_size < 8) { 14564948818cb91176df74c972ac27b2f392b5d148bcJames Dong return ERROR_MALFORMED; 14574948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 14584948818cb91176df74c972ac27b2f392b5d148bcJames Dong 14594948818cb91176df74c972ac27b2f392b5d148bcJames Dong // Worst case the location string length would be 18, 14604948818cb91176df74c972ac27b2f392b5d148bcJames Dong // for instance +90.0000-180.0000, without the trailing "/" and 14614948818cb91176df74c972ac27b2f392b5d148bcJames Dong // the string length + language code. 14624948818cb91176df74c972ac27b2f392b5d148bcJames Dong char buffer[18]; 14634948818cb91176df74c972ac27b2f392b5d148bcJames Dong 14644948818cb91176df74c972ac27b2f392b5d148bcJames Dong // Substracting 5 from the data size is because the text string length + 14654948818cb91176df74c972ac27b2f392b5d148bcJames Dong // language code takes 4 bytes, and the trailing slash "/" takes 1 byte. 14664948818cb91176df74c972ac27b2f392b5d148bcJames Dong off64_t location_length = chunk_data_size - 5; 14674948818cb91176df74c972ac27b2f392b5d148bcJames Dong if (location_length >= (off64_t) sizeof(buffer)) { 14684948818cb91176df74c972ac27b2f392b5d148bcJames Dong return ERROR_MALFORMED; 14694948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 14704948818cb91176df74c972ac27b2f392b5d148bcJames Dong 14714948818cb91176df74c972ac27b2f392b5d148bcJames Dong if (mDataSource->readAt( 14724948818cb91176df74c972ac27b2f392b5d148bcJames Dong data_offset + 4, buffer, location_length) < location_length) { 14734948818cb91176df74c972ac27b2f392b5d148bcJames Dong return ERROR_IO; 14744948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 14754948818cb91176df74c972ac27b2f392b5d148bcJames Dong 14764948818cb91176df74c972ac27b2f392b5d148bcJames Dong buffer[location_length] = '\0'; 14774948818cb91176df74c972ac27b2f392b5d148bcJames Dong mFileMetaData->setCString(kKeyLocation, buffer); 14784948818cb91176df74c972ac27b2f392b5d148bcJames Dong *offset += chunk_size; 14794948818cb91176df74c972ac27b2f392b5d148bcJames Dong break; 14804948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 14814948818cb91176df74c972ac27b2f392b5d148bcJames Dong 148220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('e', 's', 'd', 's'): 148320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 148420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 4) { 148520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 148620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 148720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 148820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[256]; 1489c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (chunk_data_size > (off64_t)sizeof(buffer)) { 149020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_BUFFER_TOO_SMALL; 149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 149334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 149420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 149520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 149620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 149720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 149820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (U32_AT(buffer) != 0) { 149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Should be version 0, flags 0. 150020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setData( 150420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); 150520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1506ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (mPath.size() >= 2 1507ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) { 1508ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // Information from the ESDS must be relied on for proper 1509ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // setup of sample rate and channel count for MPEG4 Audio. 1510ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // The generic header appears to only contain generic 1511ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // information... 1512ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1513ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio( 1514ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber &buffer[4], chunk_data_size - 4); 1515ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1516ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (err != OK) { 1517ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return err; 1518ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1519ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1520ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 152420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', 'C'): 152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 1527d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson sp<ABuffer> buffer = new ABuffer(chunk_data_size); 152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 152934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 1530d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson data_offset, buffer->data(), chunk_data_size) < chunk_data_size) { 153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setData( 1535d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size); 153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 154020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1541244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong case FOURCC('d', '2', '6', '3'): 1542244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong { 154317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong /* 154417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * d263 contains a fixed 7 bytes part: 154517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * vendor - 4 bytes 154617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * version - 1 byte 154717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * level - 1 byte 154817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * profile - 1 byte 154917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * optionally, "d263" box itself may contain a 16-byte 155017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * bit rate box (bitr) 155117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * average bit rate - 4 bytes 155217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * max bit rate - 4 bytes 155317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong */ 155417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong char buffer[23]; 155517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong if (chunk_data_size != 7 && 155617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong chunk_data_size != 23) { 155729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Incorrect D263 box size %lld", chunk_data_size); 1558244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong return ERROR_MALFORMED; 1559244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong } 1560244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 1561244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong if (mDataSource->readAt( 1562244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong data_offset, buffer, chunk_data_size) < chunk_data_size) { 1563244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong return ERROR_IO; 1564244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong } 1565244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 1566244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size); 1567244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 1568244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong *offset += chunk_size; 1569244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong break; 1570244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong } 1571244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 157272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('m', 'e', 't', 'a'): 157372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 157472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint8_t buffer[4]; 1575c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (chunk_data_size < (off64_t)sizeof(buffer)) { 1576bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1577bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 1578bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 157972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 158072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber data_offset, buffer, 4) < 4) { 158172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 158272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 158372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 158472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (U32_AT(buffer) != 0) { 158572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber // Should be version 0, flags 0. 1586ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber 1587ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // If it's not, let's assume this is one of those 1588ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // apparently malformed chunks that don't have flags 1589ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // and completely different semantics than what's 1590ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // in the MPEG4 specs and skip it. 1591ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber *offset += chunk_size; 1592ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber return OK; 159372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 159472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1595c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 159672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset = data_offset + sizeof(buffer); 159772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber while (*offset < stop_offset) { 159872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseChunk(offset, depth + 1); 159972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 160072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 160172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 160272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 1603bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1604bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1605bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1606bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 160772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 160872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 160972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 16105d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('m', 'e', 'a', 'n'): 16115d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('n', 'a', 'm', 'e'): 161272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('d', 'a', 't', 'a'): 161372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 161472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mPath.size() == 6 && underMetaDataPath(mPath)) { 161572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseMetaData(data_offset, chunk_data_size); 161672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 161772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 161872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 161972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 162072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 162172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 162272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset += chunk_size; 162372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 162472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 162572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 162672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('m', 'v', 'h', 'd'): 162772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 162872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (chunk_data_size < 12) { 162972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_MALFORMED; 163072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 163172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 163272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint8_t header[12]; 163372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 163472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber data_offset, header, sizeof(header)) 163572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber < (ssize_t)sizeof(header)) { 163672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 163772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 163872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 163972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber int64_t creationTime; 164072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (header[0] == 1) { 164172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber creationTime = U64_AT(&header[4]); 1642bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (header[0] != 0) { 1643bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 164472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 164572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber creationTime = U32_AT(&header[4]); 164672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 164772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 164872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber String8 s; 164972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber convertTimeToDate(creationTime, &s); 165072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 165172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyDate, s.string()); 165272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 165372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset += chunk_size; 165472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 165572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 165672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang case FOURCC('m', 'd', 'a', 't'): 1658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang { 1659ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("mdat chunk, drm: %d", mIsDrm); 1660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (!mIsDrm) { 1661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang *offset += chunk_size; 1662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang break; 1663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 1665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (chunk_size < 8) { 1666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 1667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 1669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return parseDrmSINF(offset, data_offset); 1670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 16723b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang case FOURCC('h', 'd', 'l', 'r'): 16733b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang { 16743b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint32_t buffer; 16753b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if (mDataSource->readAt( 16763b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang data_offset + 8, &buffer, 4) < 4) { 16773b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang return ERROR_IO; 16783b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 16793b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 16803b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint32_t type = ntohl(buffer); 16813b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // For the 3GPP file format, the handler-type within the 'hdlr' box 1682e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang // shall be 'text'. We also want to support 'sbtl' handler type 1683e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang // for a practical reason as various MPEG4 containers use it. 1684e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) { 16853b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP); 16863b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 16873b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 16883b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang *offset += chunk_size; 16893b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang break; 16903b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 16913b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 16927a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang case FOURCC('t', 'x', '3', 'g'): 16937a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang { 16943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint32_t type; 16953b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang const void *data; 16963b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang size_t size = 0; 16973b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if (!mLastTrack->meta->findData( 16983b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang kKeyTextFormatData, &type, &data, &size)) { 16993b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang size = 0; 17003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint8_t *buffer = new uint8_t[size + chunk_size]; 17033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if (size > 0) { 17053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang memcpy(buffer, data, size); 17063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size)) 17093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang < chunk_size) { 17103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang delete[] buffer; 17113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang buffer = NULL; 17123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang return ERROR_IO; 17143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang mLastTrack->meta->setData( 17173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang kKeyTextFormatData, 0, buffer, size + chunk_size); 17183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17193b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang delete[] buffer; 17207a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 17217a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang *offset += chunk_size; 17227a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang break; 17237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 17247a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 1725515e855eae78aa495da58356486aaa666cb57fd1James Dong case FOURCC('c', 'o', 'v', 'r'): 1726515e855eae78aa495da58356486aaa666cb57fd1James Dong { 1727515e855eae78aa495da58356486aaa666cb57fd1James Dong if (mFileMetaData != NULL) { 17283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("chunk_data_size = %lld and data_offset = %lld", 1729515e855eae78aa495da58356486aaa666cb57fd1James Dong chunk_data_size, data_offset); 17301552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1); 1731515e855eae78aa495da58356486aaa666cb57fd1James Dong if (mDataSource->readAt( 17321552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) { 1733515e855eae78aa495da58356486aaa666cb57fd1James Dong return ERROR_IO; 1734515e855eae78aa495da58356486aaa666cb57fd1James Dong } 1735515e855eae78aa495da58356486aaa666cb57fd1James Dong const int kSkipBytesOfDataBox = 16; 1736515e855eae78aa495da58356486aaa666cb57fd1James Dong mFileMetaData->setData( 1737515e855eae78aa495da58356486aaa666cb57fd1James Dong kKeyAlbumArt, MetaData::TYPE_NONE, 17381552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox); 1739515e855eae78aa495da58356486aaa666cb57fd1James Dong } 1740515e855eae78aa495da58356486aaa666cb57fd1James Dong 1741515e855eae78aa495da58356486aaa666cb57fd1James Dong *offset += chunk_size; 1742515e855eae78aa495da58356486aaa666cb57fd1James Dong break; 1743515e855eae78aa495da58356486aaa666cb57fd1James Dong } 1744515e855eae78aa495da58356486aaa666cb57fd1James Dong 17455d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('-', '-', '-', '-'): 17465d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen { 17475d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentMean.clear(); 17485d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentName.clear(); 17495d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentData.clear(); 17505d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen *offset += chunk_size; 17515d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 17525d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 17535d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen 175405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('s', 'i', 'd', 'x'): 175505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen { 175605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseSegmentIndex(data_offset, chunk_data_size); 175705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 175805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return UNKNOWN_ERROR; // stop parsing after sidx 175905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 176005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 176120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber default: 176220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 176320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 176420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 176520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 176620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 176720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 176820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 176920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 177020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 177105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) { 177205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Extractor::parseSegmentIndex"); 177305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 177405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 12) { 177505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 177605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 177705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 177805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t flags; 177905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &flags)) { 178005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 178105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 178205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 178305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t version = flags >> 24; 178405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen flags &= 0xffffff; 178505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 178605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("sidx version %d", version); 178705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 178805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t referenceId; 178905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, &referenceId)) { 179005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 179105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 179205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 179305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t timeScale; 179405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 8, &timeScale)) { 179505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 179605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 179705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale); 179805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 179905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t earliestPresentationTime; 180005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t firstOffset; 180105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 180205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 12; 180305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 12; 180405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 180505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (version == 0) { 180605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 180705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 180805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 180905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t tmp; 181005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 181105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 181205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 181305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen earliestPresentationTime = tmp; 181405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, &tmp)) { 181505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 181605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 181705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen firstOffset = tmp; 181805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 181905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 182005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 182105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 16) { 182205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 182305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 182405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) { 182505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 182605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 182705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt64(offset + 8, &firstOffset)) { 182805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 182905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 183005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 16; 183105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 16; 183205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 183305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset); 183405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 183505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 183605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 183705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 183805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 183905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint16_t referenceCount; 184005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt16(offset + 2, &referenceCount)) { 184105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 184205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 184305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 184405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 184505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("refcount: %d", referenceCount); 184605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 184705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < referenceCount * 12) { 184805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 184905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 185005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 185105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t total_duration = 0; 185205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen for (unsigned int i = 0; i < referenceCount; i++) { 185305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t d1, d2, d3; 185405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 185505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &d1) || // size 185605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen !mDataSource->getUInt32(offset + 4, &d2) || // duration 185705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen !mDataSource->getUInt32(offset + 8, &d3)) { // flags 185805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 185905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 186005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 186105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (d1 & 0x80000000) { 186205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGW("sub-sidx boxes not supported yet"); 186305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 186405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool sap = d3 & 0x80000000; 186505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool saptype = d3 >> 28; 186605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!sap || saptype > 2) { 186705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGW("not a stream access point, or unsupported type"); 186805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 186905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen total_duration += d2; 187005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 12; 187105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3); 187205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen SidxEntry se; 187305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen se.mSize = d1 & 0x7fffffff; 187405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen se.mDurationUs = 1000000LL * d2 / timeScale; 187505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSidxEntries.add(se); 187605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 187705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 187805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSidxDuration = total_duration * 1000000 / timeScale; 187905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("duration: %lld", mSidxDuration); 188005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 188105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t metaDuration; 188205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) { 188305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mLastTrack->meta->setInt64(kKeyDuration, mSidxDuration); 188405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 188505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 188605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 188705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 188805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 188905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 1890ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader( 1891c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t data_offset, off64_t data_size) { 1892ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (data_size < 4) { 1893ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_MALFORMED; 1894ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1895ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1896ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint8_t version; 1897ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (mDataSource->readAt(data_offset, &version, 1) < 1) { 1898ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_IO; 1899ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1900ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1901ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber size_t dynSize = (version == 1) ? 36 : 24; 1902ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1903ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint8_t buffer[36 + 60]; 1904ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1905c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (data_size != (off64_t)dynSize + 60) { 1906ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_MALFORMED; 1907ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1908ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1909ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (mDataSource->readAt( 1910ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber data_offset, buffer, data_size) < (ssize_t)data_size) { 1911ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_IO; 1912ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1913ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1914ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint64_t ctime, mtime, duration; 1915ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t id; 1916ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1917ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (version == 1) { 1918ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber ctime = U64_AT(&buffer[4]); 1919ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mtime = U64_AT(&buffer[12]); 1920ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber id = U32_AT(&buffer[20]); 1921ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber duration = U64_AT(&buffer[28]); 1922ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else { 1923ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber CHECK_EQ((unsigned)version, 0u); 1924ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1925ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber ctime = U32_AT(&buffer[4]); 1926ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mtime = U32_AT(&buffer[8]); 1927ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber id = U32_AT(&buffer[12]); 1928ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber duration = U32_AT(&buffer[20]); 1929ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1930ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1931ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mLastTrack->meta->setInt32(kKeyTrackID, id); 1932ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1933ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber size_t matrixOffset = dynSize + 16; 1934ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a00 = U32_AT(&buffer[matrixOffset]); 1935ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a01 = U32_AT(&buffer[matrixOffset + 4]); 1936ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t dx = U32_AT(&buffer[matrixOffset + 8]); 1937ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a10 = U32_AT(&buffer[matrixOffset + 12]); 1938ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a11 = U32_AT(&buffer[matrixOffset + 16]); 1939ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t dy = U32_AT(&buffer[matrixOffset + 20]); 1940ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1941ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0 1942df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("x' = %.2f * x + %.2f * y + %.2f", 1943ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f); 1944df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("y' = %.2f * x + %.2f * y + %.2f", 1945ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f); 1946ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif 1947ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1948ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint32_t rotationDegrees; 1949ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1950ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber static const int32_t kFixedOne = 0x10000; 1951ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) { 1952ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber // Identity, no rotation 1953ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 0; 1954ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) { 1955ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 90; 1956ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) { 1957ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 270; 1958ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) { 1959ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 180; 1960ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else { 19615ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("We only support 0,90,180,270 degree rotation matrices"); 1962ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 0; 1963ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1964ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1965ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (rotationDegrees != 0) { 1966ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees); 1967ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1968ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1969b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong // Handle presentation display size, which could be different 1970b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong // from the image size indicated by kKeyWidth and kKeyHeight. 1971ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint32_t width = U32_AT(&buffer[dynSize + 52]); 1972ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint32_t height = U32_AT(&buffer[dynSize + 56]); 1973b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16); 1974b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16); 1975ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1976ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return OK; 1977ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber} 1978ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1979c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) { 198072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (size < 4) { 198172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_MALFORMED; 198272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 198372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 198472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint8_t *buffer = new uint8_t[size + 1]; 198572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 198672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber offset, buffer, size) != (ssize_t)size) { 198772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber delete[] buffer; 198872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer = NULL; 198972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 199072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 199172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 199272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 199372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint32_t flags = U32_AT(buffer); 199472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 199572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint32_t metadataKey = 0; 19965d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen char chunk[5]; 19975d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen MakeFourCCString(mPath[4], chunk); 19985d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen ALOGV("meta: %s @ %lld", chunk, offset); 199972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber switch (mPath[4]) { 200072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'a', 'l', 'b'): 200172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 200272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyAlbum; 200372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 200472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 200572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'A', 'R', 'T'): 200672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 200772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyArtist; 200872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 200972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 201066ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen case FOURCC('a', 'A', 'R', 'T'): 201166ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen { 201266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen metadataKey = kKeyAlbumArtist; 201366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen break; 201466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen } 201572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'd', 'a', 'y'): 201672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 201772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyYear; 201872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 201972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 202072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'n', 'a', 'm'): 202172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 202272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyTitle; 202372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 202472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 202572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'w', 'r', 't'): 202672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 202772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyWriter; 202872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 202972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 203072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('c', 'o', 'v', 'r'): 203172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 203272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyAlbumArt; 203372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 203472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 203572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('g', 'n', 'r', 'e'): 203672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 203772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyGenre; 203872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 203972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 204026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen case FOURCC(0xa9, 'g', 'e', 'n'): 204126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen { 204226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen metadataKey = kKeyGenre; 204326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen break; 204426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 204511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen case FOURCC('c', 'p', 'i', 'l'): 204611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { 204711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen if (size == 9 && flags == 21) { 204811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen char tmp[16]; 204911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen sprintf(tmp, "%d", 205011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen (int)buffer[size - 1]); 205111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen 205211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen mFileMetaData->setCString(kKeyCompilation, tmp); 205311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen } 205411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen break; 205511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen } 205672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('t', 'r', 'k', 'n'): 205772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 205872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (size == 16 && flags == 0) { 205972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char tmp[16]; 2060afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pTrack = (uint16_t*)&buffer[10]; 2061afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pTotalTracks = (uint16_t*)&buffer[12]; 2062afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks)); 206372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 206472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyCDTrackNumber, tmp); 206572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 206672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 206772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 206826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen case FOURCC('d', 'i', 's', 'k'): 206926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen { 2070afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik if ((size == 14 || size == 16) && flags == 0) { 207126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen char tmp[16]; 2072afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pDisc = (uint16_t*)&buffer[10]; 2073afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pTotalDiscs = (uint16_t*)&buffer[12]; 2074afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs)); 207526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 207626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen mFileMetaData->setCString(kKeyDiscNumber, tmp); 207726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 207826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen break; 207926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 20805d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('-', '-', '-', '-'): 20815d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen { 20825d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen buffer[size] = '\0'; 20835d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen switch (mPath[5]) { 20845d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('m', 'e', 'a', 'n'): 20855d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentMean.setTo((const char *)buffer + 4); 20865d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 20875d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('n', 'a', 'm', 'e'): 20885d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentName.setTo((const char *)buffer + 4); 20895d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 20905d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('d', 'a', 't', 'a'): 20915d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentData.setTo((const char *)buffer + 8); 20925d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 20935d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 20948c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman 20958c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // Once we have a set of mean/name/data info, go ahead and process 20968c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // it to see if its something we are interested in. Whether or not 20978c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // were are interested in the specific tag, make sure to clear out 20988c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // the set so we can be ready to process another tuple should one 20998c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // show up later in the file. 21008c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman if ((mLastCommentMean.length() != 0) && 21018c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman (mLastCommentName.length() != 0) && 21028c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman (mLastCommentData.length() != 0)) { 21038c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman 21048c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman if (mLastCommentMean == "com.apple.iTunes" 21058c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman && mLastCommentName == "iTunSMPB") { 21068c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman int32_t delay, padding; 21078c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman if (sscanf(mLastCommentData, 21088c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman " %*x %x %x %*x", &delay, &padding) == 2) { 21098c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman mLastTrack->meta->setInt32(kKeyEncoderDelay, delay); 21108c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman mLastTrack->meta->setInt32(kKeyEncoderPadding, padding); 21118c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman } 21125d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 21138c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman 21145d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentMean.clear(); 21155d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentName.clear(); 21165d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentData.clear(); 21175d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 21185d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 21195d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 212026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 212172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber default: 212272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 212372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 212472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 212572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (size >= 8 && metadataKey) { 212672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (metadataKey == kKeyAlbumArt) { 212772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setData( 212872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber kKeyAlbumArt, MetaData::TYPE_NONE, 212972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer + 8, size - 8); 213072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else if (metadataKey == kKeyGenre) { 213172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (flags == 0) { 213226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // uint8_t genre code, iTunes genre codes are 213326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // the standard id3 codes, except they start 213426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // at 1 instead of 0 (e.g. Pop is 14, not 13) 213526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // We use standard id3 numbering, so subtract 1. 213626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen int genrecode = (int)buffer[size - 1]; 213726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen genrecode--; 213826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen if (genrecode < 0) { 213926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen genrecode = 255; // reserved for 'unknown genre' 214026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 214172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char genre[10]; 214226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen sprintf(genre, "%d", genrecode); 214372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 214472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(metadataKey, genre); 214526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } else if (flags == 1) { 214626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // custom genre string 214726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen buffer[size] = '\0'; 214826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 214926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen mFileMetaData->setCString( 215026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen metadataKey, (const char *)buffer + 8); 215172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 215272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 215372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer[size] = '\0'; 215472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 215572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString( 215672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey, (const char *)buffer + 8); 215772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 215872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 215972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 216072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber delete[] buffer; 216172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer = NULL; 216272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 216372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return OK; 216472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 216572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 2166693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) { 216720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 216820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 2169693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return NULL; 217020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 217120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 217220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 217320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (index > 0) { 217420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (track == NULL) { 2175693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return NULL; 217620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 217720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 217820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 217920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber --index; 218020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 218120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2182371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber if (track == NULL) { 2183371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber return NULL; 2184371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber } 2185371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber 2186ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("getTrack called, pssh: %d", mPssh.size()); 2187ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2188693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return new MPEG4Source( 218905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen track->meta, mDataSource, track->timescale, track->sampleTable, 219005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSidxEntries, mMoofOffset); 219120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 219220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2193bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static 2194bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) { 2195bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber const char *mime; 2196bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 2197bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 2198bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber uint32_t type; 2199bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber const void *data; 2200bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber size_t size; 2201bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 2202bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!track->meta->findData(kKeyAVCC, &type, &data, &size) 2203bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || type != kTypeAVCC) { 2204bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 2205bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 2206bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 2207bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 2208bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!track->meta->findData(kKeyESDS, &type, &data, &size) 2209bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || type != kTypeESDS) { 2210bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 2211bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 2212bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 2213bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 2214169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber if (!track->sampleTable->isValid()) { 2215169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber // Make sure we have all the metadata we need. 2216169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber return ERROR_MALFORMED; 2217169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber } 2218169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber 2219bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return OK; 2220bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber} 2221bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 2222ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( 2223ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber const void *esds_data, size_t esds_size) { 2224ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber ESDS esds(esds_data, esds_size); 222581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 222681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint8_t objectTypeIndication; 222781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) { 222881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber return ERROR_MALFORMED; 222981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber } 223081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 223181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber if (objectTypeIndication == 0xe1) { 223281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber // This isn't MPEG4 audio at all, it's QCELP 14k... 223381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP); 223481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber return OK; 223581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber } 223681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 2237633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong if (objectTypeIndication == 0x6b) { 2238633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong // The media subtype is MP3 audio 2239633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong // Our software MP3 audio decoder may not be able to handle 2240633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED 224129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("MP3 track in MP4/3GPP file is not supported"); 2242633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong return ERROR_UNSUPPORTED; 2243633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong } 2244633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong 2245ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber const uint8_t *csd; 2246ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber size_t csd_size; 2247ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (esds.getCodecSpecificInfo( 2248ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber (const void **)&csd, &csd_size) != OK) { 2249ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 2250ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2251ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2252ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0 2253ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber printf("ESD of size %d\n", csd_size); 2254ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber hexdump(csd, csd_size); 2255ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif 2256ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2257a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber if (csd_size == 0) { 2258a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber // There's no further information, i.e. no codec specific data 2259a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber // Let's assume that the information provided in the mpeg4 headers 2260a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber // is accurate and hope for the best. 2261a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber 2262a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber return OK; 2263a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber } 2264a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber 2265ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (csd_size < 2) { 2266ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 2267ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2268ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2269aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke ABitReader br(csd, csd_size); 2270aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke uint32_t objectType = br.getBits(5); 2271ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2272aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke if (objectType == 31) { // AAC-ELD => additional 6 bits 2273aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke objectType = 32 + br.getBits(6); 2274ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2275ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2276aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke uint32_t freqIndex = br.getBits(4); 2277aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke 2278ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t sampleRate = 0; 2279ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t numChannels = 0; 2280ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (freqIndex == 15) { 2281ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (csd_size < 5) { 2282ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 2283ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2284aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke sampleRate = br.getBits(24); 2285aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke numChannels = br.getBits(4); 2286ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } else { 2287595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen numChannels = br.getBits(4); 2288595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen if (objectType == 5) { 2289595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen // SBR specific config per 14496-3 table 1.13 2290595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen freqIndex = br.getBits(4); 2291595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen if (freqIndex == 15) { 2292595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen if (csd_size < 8) { 2293595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen return ERROR_MALFORMED; 2294595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen } 2295595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen sampleRate = br.getBits(24); 2296595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen } 2297ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2298ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2299595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen if (sampleRate == 0) { 2300595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen static uint32_t kSamplingRate[] = { 2301595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 2302595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen 16000, 12000, 11025, 8000, 7350 2303595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen }; 2304595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen 2305595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen if (freqIndex == 13 || freqIndex == 14) { 2306595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen return ERROR_MALFORMED; 2307595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen } 2308595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen 2309595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen sampleRate = kSamplingRate[freqIndex]; 2310595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen } 2311ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2312ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2313ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (numChannels == 0) { 2314ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_UNSUPPORTED; 2315ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2316ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2317ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t prevSampleRate; 2318ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate)); 2319ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2320ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (prevSampleRate != sampleRate) { 23213856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("mpeg4 audio sample rate different from previous setting. " 2322ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber "was: %d, now: %d", prevSampleRate, sampleRate); 2323ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2324ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2325ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sampleRate); 2326ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2327ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t prevChannelCount; 2328ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount)); 2329ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2330ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (prevChannelCount != numChannels) { 23313856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("mpeg4 audio channel count different from previous setting. " 2332ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber "was: %d, now: %d", prevChannelCount, numChannels); 2333ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2334ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2335ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, numChannels); 2336ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2337ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return OK; 2338ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber} 2339ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 234020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 234120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 234220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source( 234320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const sp<MetaData> &format, 2344693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &dataSource, 234548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int32_t timeScale, 234605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const sp<SampleTable> &sampleTable, 234705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<SidxEntry> &sidx, 234805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t firstMoofOffset) 234920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFormat(format), 235020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDataSource(dataSource), 235148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mTimescale(timeScale), 235220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSampleTable(sampleTable), 235320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCurrentSampleIndex(0), 235405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentFragmentIndex(0), 235505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSegments(sidx), 235605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mFirstMoofOffset(firstMoofOffset), 235705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentMoofOffset(firstMoofOffset), 235805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentTime(0), 2359ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoAllocSize(0), 2360ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoSizes(NULL), 2361ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsetsAllocSize(0), 2362ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets(NULL), 236320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mIsAVC(false), 23646064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mNALLengthSize(0), 236520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted(false), 236620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup(NULL), 236720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer(NULL), 2368dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments(false), 23690024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer(NULL) { 2370ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2371ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mFormat->findInt32(kKeyCryptoMode, &mCryptoMode); 237248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mDefaultIVSize = 0; 2373ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize); 2374ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t keytype; 2375ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen const void *key; 2376ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen size_t keysize; 2377ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) { 2378ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen CHECK(keysize <= 16); 2379ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(mCryptoKey, 0, 16); 2380ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memcpy(mCryptoKey, key, keysize); 2381ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2382ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 238320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 238420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mFormat->findCString(kKeyMIMEType, &mime); 2385dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(success); 238620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 238718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 23886064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 23896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber if (mIsAVC) { 23906064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber uint32_t type; 23916064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber const void *data; 23926064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t size; 23936064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(format->findData(kKeyAVCC, &type, &data, &size)); 23946064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 23956064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber const uint8_t *ptr = (const uint8_t *)data; 23966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 23976064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(size >= 7); 2398ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 23996064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 24006064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // The number of bytes used to encode the length of a NAL unit. 24016064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mNALLengthSize = 1 + (ptr[4] & 3); 24026064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber } 240305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 240405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(format->findInt32(kKeyTrackID, &mTrackId)); 240505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 240605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mFirstMoofOffset != 0) { 240705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t offset = mFirstMoofOffset; 240805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(&offset); 240905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 241020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 241120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 241220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() { 241320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mStarted) { 241420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 241520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 2416ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen free(mCurrentSampleInfoSizes); 2417ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen free(mCurrentSampleInfoOffsets); 241820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 241920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 242020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) { 24217b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 24227b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 2423dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(!mStarted); 242420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 242520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t val; 2426dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (params && params->findInt32(kKeyWantsNALFragments, &val) 242720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && val != 0) { 2428dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments = true; 242920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 2430dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments = false; 243120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 243220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 243320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup = new MediaBufferGroup; 243420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2435738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber int32_t max_size; 2436738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size)); 243720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2438738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber mGroup->add_buffer(new MediaBuffer(max_size)); 24390024245e134467d120b40099da16c467dc365e76Andreas Huber 24400024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer = new uint8_t[max_size]; 244120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 244220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = true; 244320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 244420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 244520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 244620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 244720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() { 24487b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 24497b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 2450dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(mStarted); 245120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 245220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mBuffer != NULL) { 245320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 245420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 245520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 245620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24570024245e134467d120b40099da16c467dc365e76Andreas Huber delete[] mSrcBuffer; 24580024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer = NULL; 24590024245e134467d120b40099da16c467dc365e76Andreas Huber 246020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete mGroup; 246120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup = NULL; 246220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 246320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = false; 246420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCurrentSampleIndex = 0; 246520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 246620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 246720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 246820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 246905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) { 247005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t hdr[2]; 247105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mDataSource->readAt(*offset, hdr, 8) < 8) { 247205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 247305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 247405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t chunk_size = ntohl(hdr[0]); 247505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t chunk_type = ntohl(hdr[1]); 247605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t data_offset = *offset + 8; 247705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 247805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_size == 1) { 247905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { 248005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 248105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 248205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen chunk_size = ntoh64(chunk_size); 248305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen data_offset += 8; 248405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 248505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_size < 16) { 248605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // The smallest valid chunk is 16 bytes long in this case. 248705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 248805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 248905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (chunk_size < 8) { 249005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // The smallest valid chunk is 8 bytes long. 249105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 249205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 249305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 249405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen char chunk[5]; 249505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MakeFourCCString(chunk_type, chunk); 249605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset); 249705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 249805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t chunk_data_size = *offset + chunk_size - data_offset; 249905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 250005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen switch(chunk_type) { 250105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 250205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('t', 'r', 'a', 'f'): 250305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('m', 'o', 'o', 'f'): { 250405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t stop_offset = *offset + chunk_size; 250505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset = data_offset; 250605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen while (*offset < stop_offset) { 250705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err = parseChunk(offset); 250805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (err != OK) { 250905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 251005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 251105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 251205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_type == FOURCC('m', 'o', 'o', 'f')) { 2513ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // *offset points to the mdat box following this moof 251405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(offset); // doesn't actually parse it, just updates offset 251505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mNextMoofOffset = *offset; 251605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 251705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 251805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 251905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 252005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('t', 'f', 'h', 'd'): { 252105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err; 252205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) { 252305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 252405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 252505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 252605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 252705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 252805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 252905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('t', 'r', 'u', 'n'): { 253005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err; 253105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mLastParsedTrackId == mTrackId) { 253205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) { 253305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 253405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 253505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 253605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 253705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 253805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 253905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 254005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 2541ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'a', 'i', 'z'): { 2542ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t err; 2543ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) { 2544ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return err; 2545ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2546ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 2547ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 2548ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2549ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'a', 'i', 'o'): { 2550ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t err; 2551ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) { 2552ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return err; 2553ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2554ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 2555ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 2556ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2557ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2558ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('m', 'd', 'a', 't'): { 2559ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // parse DRM info if present 2560ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("MPEG4Source::parseChunk mdat"); 2561ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // if saiz/saoi was previously observed, do something with the sampleinfos 2562ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 2563ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 2564ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2565ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 256605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen default: { 256705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 256805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 256905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 257005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 257105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 257205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 257305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 2574ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size) { 2575ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("parseSampleAuxiliaryInformationSizes"); 2576ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // 14496-12 8.7.12 2577ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t version; 2578ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt( 2579ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset, &version, sizeof(version)) 2580ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen < (ssize_t)sizeof(version)) { 2581ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2582ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2583ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2584ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (version != 0) { 2585ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_UNSUPPORTED; 2586ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2587ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset++; 2588ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2589ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t flags; 2590ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt24(offset, &flags)) { 2591ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2592ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2593ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 3; 2594ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2595ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (flags & 1) { 2596ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t tmp; 2597ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 2598ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 2599ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2600ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentAuxInfoType = tmp; 2601ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2602ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 2603ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 2604ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2605ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentAuxInfoTypeParameter = tmp; 2606ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2607ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2608ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2609ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t defsize; 2610ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(offset, &defsize, 1) != 1) { 2611ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 2612ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2613ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentDefaultSampleInfoSize = defsize; 2614ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset++; 2615ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2616ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t smplcnt; 2617ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &smplcnt)) { 2618ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 2619ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 262048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mCurrentSampleInfoCount = smplcnt; 2621ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2622ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 262348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (mCurrentDefaultSampleInfoSize != 0) { 262448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize); 262548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return OK; 262648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 2627ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (smplcnt > mCurrentSampleInfoAllocSize) { 2628ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt); 2629ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoAllocSize = smplcnt; 2630ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2631ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2632ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt); 2633ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return OK; 2634ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen} 2635ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2636ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size) { 2637ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("parseSampleAuxiliaryInformationOffsets"); 2638ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // 14496-12 8.7.13 2639ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t version; 2640ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) { 2641ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2642ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2643ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset++; 2644ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2645ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t flags; 2646ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt24(offset, &flags)) { 2647ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2648ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2649ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 3; 2650ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2651ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t entrycount; 2652ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &entrycount)) { 2653ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2654ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2655ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2656ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2657ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (entrycount > mCurrentSampleInfoOffsetsAllocSize) { 2658ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8); 2659ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsetsAllocSize = entrycount; 2660ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2661ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsetCount = entrycount; 2662ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2663ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < entrycount; i++) { 2664ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (version == 0) { 2665ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t tmp; 2666ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 2667ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2668ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2669ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets[i] = tmp; 2670ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2671ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } else { 2672ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint64_t tmp; 2673ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt64(offset, &tmp)) { 2674ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2675ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2676ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets[i] = tmp; 2677ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 8; 2678ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2679ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2680ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2681ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // parse clear/encrypted data 2682ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2683ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof 2684ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2685ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen drmoffset += mCurrentMoofOffset; 2686ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int ivlength; 2687ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength)); 268848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 268948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // read CencSampleAuxiliaryDataFormats 2690ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mCurrentSampleInfoCount; i++) { 2691ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen Sample *smpl = &mCurrentSamples.editItemAt(i); 2692ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2693ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(smpl->iv, 0, 16); 2694ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) { 2695ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2696ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2697ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2698ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen drmoffset += ivlength; 2699ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 270048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen int32_t smplinfosize = mCurrentDefaultSampleInfoSize; 270148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (smplinfosize == 0) { 270248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smplinfosize = mCurrentSampleInfoSizes[i]; 2703ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 270448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (smplinfosize > ivlength) { 270548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint16_t numsubsamples; 270648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) { 2707ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2708ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2709ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen drmoffset += 2; 271048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen for (size_t j = 0; j < numsubsamples; j++) { 271148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint16_t numclear; 271248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t numencrypted; 271348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!mDataSource->getUInt16(drmoffset, &numclear)) { 271448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return ERROR_IO; 271548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 271648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen drmoffset += 2; 271748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!mDataSource->getUInt32(drmoffset, &numencrypted)) { 271848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return ERROR_IO; 271948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 272048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen drmoffset += 4; 272148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->clearsizes.add(numclear); 272248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->encryptedsizes.add(numencrypted); 2723ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 272448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } else { 272548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->clearsizes.add(0); 272648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->encryptedsizes.add(smpl->size); 2727ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2728ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2729ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2730ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2731ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return OK; 2732ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen} 2733ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 273405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) { 273505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 273605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 273705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 273805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 273905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 274005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t flags; 2741ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags 274205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 274305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 274405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 274505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & 0xff000000) { 274605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 274705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 274805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 274905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) { 275005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 275105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 275205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 275305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mLastParsedTrackId != mTrackId) { 275405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // this is not the right track, skip it 275505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 275605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 275705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 275805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mFlags = flags; 275905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId; 276005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 276105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 276205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 276305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID); 276405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 276505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) { 276605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 276705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 276805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 276905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 277005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) { 277105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 277205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 277305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 277405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 277505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 277605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 277705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) { 277805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 277905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 278005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 278105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 278205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) { 278305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 278405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 278505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 278605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 278705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 278805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 278905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) { 279005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 279105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 279205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 279305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 279405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) { 279505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 279605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 279705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 279805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 279905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 280005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 280105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) { 280205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 280305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 280405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 280505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 280605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) { 280705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 280805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 280905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 281005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 281105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 281205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 281305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) { 281405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 281505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 281605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 281705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 281805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) { 281905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 282005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 282105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 282205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 282305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 282405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 282505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) { 282605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset; 282705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 282805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 282905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mDataOffset = 0; 283005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 283105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 283205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 283305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) { 283405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 283505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Extractor::parseTrackFragmentRun"); 283605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 283705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 283805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 283905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 284005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen enum { 284105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDataOffsetPresent = 0x01, 284205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kFirstSampleFlagsPresent = 0x04, 284305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleDurationPresent = 0x100, 284405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleSizePresent = 0x200, 284505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleFlagsPresent = 0x400, 284605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleCompositionTimeOffsetPresent = 0x800, 284705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 284805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 284905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t flags; 285005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &flags)) { 285105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 285205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 285305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("fragment run flags: %08x", flags); 285405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 285505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & 0xff000000) { 285605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 285705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 285805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 285905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) { 286005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // These two shall not be used together. 286105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 286205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 286305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 286405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleCount; 286505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, &sampleCount)) { 286605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 286705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 286805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 286905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 287005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 287105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset; 287205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 287305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t firstSampleFlags = 0; 287405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 287505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kDataOffsetPresent) { 287605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 287705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 287805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 287905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 288005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t dataOffsetDelta; 288105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) { 288205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 288305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 288405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 288505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta; 288605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 288705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 288805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 288905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 289005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 289105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kFirstSampleFlagsPresent) { 289205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 289305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 289405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 289505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 289605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &firstSampleFlags)) { 289705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 289805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 289905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 290005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 290105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 290205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 290305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0, 290405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleCtsOffset = 0; 290505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 290605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t bytesPerSample = 0; 290705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleDurationPresent) { 290805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 290905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (mTrackFragmentHeaderInfo.mFlags 291005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) { 291105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration; 291205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 291305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration; 291405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 291505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 291605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleSizePresent) { 291705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 291805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (mTrackFragmentHeaderInfo.mFlags 291905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) { 292005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize; 292105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 292205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize; 292305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 292405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 292505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleFlagsPresent) { 292605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 292705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (mTrackFragmentHeaderInfo.mFlags 292805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) { 292905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags; 293005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 293105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags; 293205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 293305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 293405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleCompositionTimeOffsetPresent) { 293505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 293605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 293705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleCtsOffset = 0; 293805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 293905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 294005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < sampleCount * bytesPerSample) { 294105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 294205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 294305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 294405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Sample tmp; 294505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen for (uint32_t i = 0; i < sampleCount; ++i) { 294605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleDurationPresent) { 294705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleDuration)) { 294805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 294905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 295005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 295105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 295205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 295305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleSizePresent) { 295405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleSize)) { 295505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 295605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 295705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 295805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 295905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 296005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleFlagsPresent) { 296105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleFlags)) { 296205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 296305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 296405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 296505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 296605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 296705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleCompositionTimeOffsetPresent) { 296805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) { 296905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 297005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 297105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 297205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 297305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 2974ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("adding sample %d at offset 0x%08llx, size %u, duration %u, " 2975ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen " flags 0x%08x", i + 1, 297605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dataOffset, sampleSize, sampleDuration, 297705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (flags & kFirstSampleFlagsPresent) && i == 0 297805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ? firstSampleFlags : sampleFlags); 297905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen tmp.offset = dataOffset; 298005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen tmp.size = sampleSize; 298105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen tmp.duration = sampleDuration; 298205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSamples.add(tmp); 298305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 298405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dataOffset += sampleSize; 298505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 298605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 298705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mDataOffset = dataOffset; 298805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 298905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 299005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 299105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 299220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() { 29937b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 29947b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 299520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return mFormat; 299620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 299720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29986064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const { 29996064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber switch (mNALLengthSize) { 30006064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 1: 30016064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return *data; 30026064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 2: 30036064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return U16_AT(data); 30046064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 3: 30056064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return ((size_t)data[0] << 16) | U16_AT(&data[1]); 30066064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 4: 30076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return U32_AT(data); 30086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber } 30096064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 30106064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // This cannot happen, mNALLengthSize springs to life by adding 1 to 30116064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // a 2-bit integer. 30126064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(!"Should not be here."); 30136064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 30146064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return 0; 30156064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber} 30166064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 301720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read( 301820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer **out, const ReadOptions *options) { 30197b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 30207b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 3021dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(mStarted); 302220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 302305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mFirstMoofOffset > 0) { 302405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return fragmentedRead(out, options); 302505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 302605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 302720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *out = NULL; 302820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3029abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber int64_t targetSampleTimeUs = -1; 3030abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 303120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t seekTimeUs; 3032abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 3033abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 3034abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t findFlags = 0; 3035abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber switch (mode) { 3036abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_PREVIOUS_SYNC: 3037abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagBefore; 3038abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3039abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_NEXT_SYNC: 3040abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagAfter; 3041abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3042abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_CLOSEST_SYNC: 3043abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_CLOSEST: 3044abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagClosest; 3045abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3046abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber default: 3047abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber CHECK(!"Should not be here."); 3048abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3049abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3050abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 305120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t sampleIndex; 3052abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber status_t err = mSampleTable->findSampleAtTime( 305320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber seekTimeUs * mTimescale / 1000000, 3054abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber &sampleIndex, findFlags); 3055abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3056abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 3057abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber // We found the closest sample already, now we want the sync 3058abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber // sample preceding it (or the sample itself of course), even 3059abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber // if the subsequent sync sample is closer. 3060abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagBefore; 3061abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3062abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3063abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t syncSampleIndex; 3064abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (err == OK) { 3065abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber err = mSampleTable->findSyncSampleNear( 3066abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber sampleIndex, &syncSampleIndex, findFlags); 3067abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 306820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3069788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber uint32_t sampleTime; 3070788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber if (err == OK) { 3071788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber err = mSampleTable->getMetaDataForSample( 3072788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber sampleIndex, NULL, NULL, &sampleTime); 3073788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber } 3074788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber 307520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 30765295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber if (err == ERROR_OUT_OF_RANGE) { 30775295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // An attempt to seek past the end of the stream would 30785295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // normally cause this ERROR_OUT_OF_RANGE error. Propagating 30795295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // this all the way to the MediaPlayer would cause abnormal 30805295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // termination. Legacy behaviour appears to be to behave as if 30815295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // we had seeked to the end of stream, ending normally. 30825295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber err = ERROR_END_OF_STREAM; 30835295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber } 308405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("end of stream"); 308520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 308620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 308720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3088abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 3089abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale; 3090abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3091abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3092abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0 3093abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t syncSampleTime; 3094abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber CHECK_EQ(OK, mSampleTable->getMetaDataForSample( 3095abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber syncSampleIndex, NULL, NULL, &syncSampleTime)); 3096abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3097df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("seek to time %lld us => sample at time %lld us, " 3098abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber "sync sample at time %lld us", 3099abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber seekTimeUs, 3100abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber sampleTime * 1000000ll / mTimescale, 3101abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber syncSampleTime * 1000000ll / mTimescale); 3102abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif 3103abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3104abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mCurrentSampleIndex = syncSampleIndex; 310520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mBuffer != NULL) { 310620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 310720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 310820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 310920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 311020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // fall through 311120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 311220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3113c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset; 31140024245e134467d120b40099da16c467dc365e76Andreas Huber size_t size; 31154678a6dc5f09008481524949a9667af5a6190374Andreas Huber uint32_t cts; 31168bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber bool isSyncSample; 3117dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber bool newBuffer = false; 3118dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (mBuffer == NULL) { 3119dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber newBuffer = true; 312020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3121c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber status_t err = 3122c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber mSampleTable->getMetaDataForSample( 31234678a6dc5f09008481524949a9667af5a6190374Andreas Huber mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample); 312420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3125dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (err != OK) { 3126dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return err; 3127dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3128dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3129dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber err = mGroup->acquire_buffer(&mBuffer); 3130c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 3131dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (err != OK) { 3132ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber CHECK(mBuffer == NULL); 3133dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return err; 3134dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 31350024245e134467d120b40099da16c467dc365e76Andreas Huber } 313620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3137dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (!mIsAVC || mWantsNALFragments) { 3138dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (newBuffer) { 3139dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber ssize_t num_bytes_read = 314034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 3141dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3142dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (num_bytes_read < (ssize_t)size) { 3143dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->release(); 3144dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 3145dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3146dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return ERROR_IO; 3147dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3148dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 31497b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(mBuffer != NULL); 3150dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->set_range(0, size); 3151dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->meta_data()->clear(); 315248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mBuffer->meta_data()->setInt64( 31534678a6dc5f09008481524949a9667af5a6190374Andreas Huber kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 3154abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3155abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (targetSampleTimeUs >= 0) { 3156abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mBuffer->meta_data()->setInt64( 3157abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber kKeyTargetTime, targetSampleTimeUs); 3158abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3159abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 31608bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber if (isSyncSample) { 31618bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 31628bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 31638bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 3164dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber ++mCurrentSampleIndex; 3165dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3166dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3167dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (!mIsAVC) { 3168dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber *out = mBuffer; 3169dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 3170dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3171dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return OK; 3172dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3173dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3174dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // Each NAL unit is split up into its constituent fragments and 3175dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // each one of them returned in its own buffer. 3176dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 31776064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(mBuffer->range_length() >= mNALLengthSize); 3178dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3179dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber const uint8_t *src = 3180dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 3181dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 31826064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t nal_size = parseNALSize(src); 3183e8a084958c27327b0aca749f69095605d2a21309Andreas Huber if (mBuffer->range_length() < mNALLengthSize + nal_size) { 318429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("incomplete NAL unit."); 3185e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 3186e8a084958c27327b0aca749f69095605d2a21309Andreas Huber mBuffer->release(); 3187e8a084958c27327b0aca749f69095605d2a21309Andreas Huber mBuffer = NULL; 3188e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 3189e8a084958c27327b0aca749f69095605d2a21309Andreas Huber return ERROR_MALFORMED; 3190e8a084958c27327b0aca749f69095605d2a21309Andreas Huber } 3191dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3192dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber MediaBuffer *clone = mBuffer->clone(); 31937b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(clone != NULL); 31946064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 3195dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 31967b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(mBuffer != NULL); 3197dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->set_range( 31986064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mBuffer->range_offset() + mNALLengthSize + nal_size, 31996064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mBuffer->range_length() - mNALLengthSize - nal_size); 3200dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3201dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (mBuffer->range_length() == 0) { 3202dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->release(); 3203dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 3204dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3205dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3206dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber *out = clone; 3207dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3208dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return OK; 3209dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } else { 3210dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // Whole NAL units are returned but each fragment is prefixed by 3211dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // the start code (0x00 00 00 01). 3212dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang ssize_t num_bytes_read = 0; 3213dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t drm = 0; 3214dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0); 3215dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (usesDRM) { 3216dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang num_bytes_read = 3217dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size); 3218dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else { 3219dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size); 3220dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 322120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 322220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (num_bytes_read < (ssize_t)size) { 322320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 322420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 322520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3226dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return ERROR_IO; 322720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 322820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3229dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (usesDRM) { 3230dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK(mBuffer != NULL); 3231dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer->set_range(0, size); 32326064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 3233dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else { 3234dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t *dstData = (uint8_t *)mBuffer->data(); 3235dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size_t srcOffset = 0; 3236dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size_t dstOffset = 0; 3237e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 3238dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (srcOffset < size) { 323934fe252c89e33572d01fea981b58d7b115e76164James Dong bool isMalFormed = (srcOffset + mNALLengthSize > size); 324034fe252c89e33572d01fea981b58d7b115e76164James Dong size_t nalLength = 0; 324134fe252c89e33572d01fea981b58d7b115e76164James Dong if (!isMalFormed) { 324234fe252c89e33572d01fea981b58d7b115e76164James Dong nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 324334fe252c89e33572d01fea981b58d7b115e76164James Dong srcOffset += mNALLengthSize; 324434fe252c89e33572d01fea981b58d7b115e76164James Dong isMalFormed = srcOffset + nalLength > size; 324534fe252c89e33572d01fea981b58d7b115e76164James Dong } 3246e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 324734fe252c89e33572d01fea981b58d7b115e76164James Dong if (isMalFormed) { 324829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Video is malformed"); 3249dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer->release(); 3250dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer = NULL; 3251dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 3252dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 3253dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 3254dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (nalLength == 0) { 3255dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang continue; 3256dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 3257dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3258dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK(dstOffset + 4 <= mBuffer->size()); 3259dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3260dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 0; 3261dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 0; 3262dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 0; 3263dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 1; 3264dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 3265dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang srcOffset += nalLength; 3266dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstOffset += nalLength; 3267dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 3268dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK_EQ(srcOffset, size); 3269dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK(mBuffer != NULL); 3270dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer->set_range(0, dstOffset); 3271dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3272dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 327320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->meta_data()->clear(); 327448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mBuffer->meta_data()->setInt64( 32754678a6dc5f09008481524949a9667af5a6190374Andreas Huber kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 3276abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3277abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (targetSampleTimeUs >= 0) { 3278abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mBuffer->meta_data()->setInt64( 3279abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber kKeyTargetTime, targetSampleTimeUs); 3280abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3281abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 32828bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber if (isSyncSample) { 32838bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 32848bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 32858bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 328620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++mCurrentSampleIndex; 328720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 328820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *out = mBuffer; 328920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 329020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 329120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 329220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 329320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 329420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 329505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead( 329605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MediaBuffer **out, const ReadOptions *options) { 329705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 329805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Source::fragmentedRead"); 329905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 330005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mStarted); 330105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 330205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = NULL; 330305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 330405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t targetSampleTimeUs = -1; 330505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 330605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t seekTimeUs; 330705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ReadOptions::SeekMode mode; 330805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (options && options->getSeekTo(&seekTimeUs, &mode)) { 330905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 331005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int numSidxEntries = mSegments.size(); 331105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (numSidxEntries != 0) { 331205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t totalTime = 0; 331305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t totalOffset = mFirstMoofOffset; 331405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen for (int i = 0; i < numSidxEntries; i++) { 331505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const SidxEntry *se = &mSegments[i]; 331605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (totalTime + se->mDurationUs > seekTimeUs) { 331705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // The requested time is somewhere in this segment 331805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((mode == ReadOptions::SEEK_NEXT_SYNC) || 331905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (mode == ReadOptions::SEEK_CLOSEST_SYNC && 332005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) { 332105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // requested next sync, or closest sync and it was closer to the end of 332205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // this segment 332305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalTime += se->mDurationUs; 332405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalOffset += se->mSize; 332505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 332605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 332705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 332805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalTime += se->mDurationUs; 332905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalOffset += se->mSize; 333005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 333105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentMoofOffset = totalOffset; 333205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSamples.clear(); 333305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSampleIndex = 0; 333405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(&totalOffset); 333505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentTime = totalTime * mTimescale / 1000000ll; 333605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 333705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 333805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer != NULL) { 333905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 334005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 334105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 334205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 334305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // fall through 334405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 334505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 334605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t offset = 0; 334705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t size; 334805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t cts = 0; 334905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool isSyncSample = false; 335005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool newBuffer = false; 335105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer == NULL) { 335205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen newBuffer = true; 335305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 335405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mCurrentSampleIndex >= mCurrentSamples.size()) { 335505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // move to next fragment 335605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Sample lastSample = mCurrentSamples[mCurrentSamples.size() - 1]; 335705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size; 335805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentMoofOffset = nextMoof; 335905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSamples.clear(); 336005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSampleIndex = 0; 336105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(&nextMoof); 336205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mCurrentSampleIndex >= mCurrentSamples.size()) { 336305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_END_OF_STREAM; 336405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 336505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 336605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 336705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex]; 336805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset = smpl->offset; 336905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size = smpl->size; 337005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen cts = mCurrentTime; 337105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentTime += smpl->duration; 337205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen isSyncSample = (mCurrentSampleIndex == 0); // XXX 337305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 337405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err = mGroup->acquire_buffer(&mBuffer); 337505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 337605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (err != OK) { 337705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer == NULL); 337805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("acquire_buffer returned %d", err); 337905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 338005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 338105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 338205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 338348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex]; 338448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen const sp<MetaData> bufmeta = mBuffer->meta_data(); 338548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->clear(); 338648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (smpl->encryptedsizes.size()) { 338748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // store clear/encrypted lengths in metadata 338848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyPlainSizes, 0, 338948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->clearsizes.array(), smpl->clearsizes.size() * 4); 339048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyEncryptedSizes, 0, 339148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4); 339248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size? 339348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize); 339448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setInt32(kKeyCryptoMode, mCryptoMode); 339548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16); 339648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 339748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 339805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mIsAVC || mWantsNALFragments) { 339905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (newBuffer) { 340005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ssize_t num_bytes_read = 340105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 340205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 340305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (num_bytes_read < (ssize_t)size) { 340405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 340505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 340605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 340705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("i/o error"); 340805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 340905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 341005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 341105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 341205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range(0, size); 341305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 341405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 341505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 341605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (targetSampleTimeUs >= 0) { 341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 341805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTargetTime, targetSampleTimeUs); 341905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 342005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 342105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (isSyncSample) { 342205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 342305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 342405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 342505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ++mCurrentSampleIndex; 342605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 342705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 342805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mIsAVC) { 342905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = mBuffer; 343005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 343105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 343205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 343305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 343405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 343505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // Each NAL unit is split up into its constituent fragments and 343605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // each one of them returned in its own buffer. 343705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 343805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer->range_length() >= mNALLengthSize); 343905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 344005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const uint8_t *src = 344105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 344205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 344305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t nal_size = parseNALSize(src); 344405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer->range_length() < mNALLengthSize + nal_size) { 344505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGE("incomplete NAL unit."); 344605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 344705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 344805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 344905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 345005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 345105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 345205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 345305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MediaBuffer *clone = mBuffer->clone(); 345405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(clone != NULL); 345505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 345605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 345705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 345805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range( 345905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->range_offset() + mNALLengthSize + nal_size, 346005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->range_length() - mNALLengthSize - nal_size); 346105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 346205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer->range_length() == 0) { 346305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 346405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 346705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = clone; 346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 347105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("whole NAL"); 347205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // Whole NAL units are returned but each fragment is prefixed by 347305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // the start code (0x00 00 00 01). 347405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ssize_t num_bytes_read = 0; 347505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t drm = 0; 347605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0); 347705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (usesDRM) { 347805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen num_bytes_read = 347905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size); 348005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 348105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size); 348205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 348305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 348405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (num_bytes_read < (ssize_t)size) { 348505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 348605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 348705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 348805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("i/o error"); 348905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 349005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 349105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 349205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (usesDRM) { 349305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 349405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range(0, size); 349505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 349605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 349705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint8_t *dstData = (uint8_t *)mBuffer->data(); 349805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t srcOffset = 0; 349905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t dstOffset = 0; 350005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 350105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen while (srcOffset < size) { 350205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool isMalFormed = (srcOffset + mNALLengthSize > size); 350305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t nalLength = 0; 350405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!isMalFormed) { 350505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 350605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen srcOffset += mNALLengthSize; 350705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen isMalFormed = srcOffset + nalLength > size; 350805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 350905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 351005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (isMalFormed) { 351105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGE("Video is malformed"); 351205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 351305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 351405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 351505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 351605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 351705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (nalLength == 0) { 351805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen continue; 351905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 352005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 352105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(dstOffset + 4 <= mBuffer->size()); 352205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 352305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 0; 352405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 0; 352505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 0; 352605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 1; 352705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 352805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen srcOffset += nalLength; 352905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstOffset += nalLength; 353005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 353105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK_EQ(srcOffset, size); 353205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 353305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range(0, dstOffset); 353405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 353505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 353605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 353705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 353805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 353905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (targetSampleTimeUs >= 0) { 354005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 354105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTargetTime, targetSampleTimeUs); 354205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 354305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 354405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (isSyncSample) { 354505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 354605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 354705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 354805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ++mCurrentSampleIndex; 354905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 355005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = mBuffer; 355105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 355205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 355305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 355405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 355505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 355605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 3557bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix( 3558bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber const char *mimePrefix) { 3559bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber for (Track *track = mFirstTrack; track != NULL; track = track->next) { 3560bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber const char *mime; 3561bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber if (track->meta != NULL 3562bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber && track->meta->findCString(kKeyMIMEType, &mime) 3563bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) { 3564bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return track; 3565bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber } 3566bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber } 3567bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber 3568bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return NULL; 3569bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber} 3570bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber 35711b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4( 3572693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 357320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t header[8]; 357420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 357534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber ssize_t n = source->readAt(4, header, sizeof(header)); 357620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (n < (ssize_t)sizeof(header)) { 357720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return false; 357820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 357920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 358020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8) 3581b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8) 3582b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8) 35830dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8) 3584ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8) 3585983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) { 358618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 35875a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber *confidence = 0.4; 358820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 358920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return true; 359020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 359120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 359220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return false; 359320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 359420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35951b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) { 35961b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber static const uint32_t kCompatibleBrands[] = { 35971b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('i', 's', 'o', 'm'), 35981b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('i', 's', 'o', '2'), 35991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('a', 'v', 'c', '1'), 36001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('3', 'g', 'p', '4'), 36011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('m', 'p', '4', '1'), 36021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('m', 'p', '4', '2'), 36034cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong 36044cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong // Won't promise that the following file types can be played. 36054cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong // Just give these file types a chance. 36064cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong FOURCC('q', 't', ' ', ' '), // Apple's QuickTime 36074cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong FOURCC('M', 'S', 'N', 'V'), // Sony's PSP 360858fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber 360958fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber FOURCC('3', 'g', '2', 'a'), // 3GPP2 361058fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber FOURCC('3', 'g', '2', 'b'), 36111b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber }; 36121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 36131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber for (size_t i = 0; 36141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]); 36151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber ++i) { 36161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (kCompatibleBrands[i] == fourcc) { 36171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 36181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 36191b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 36201b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 36211b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 36221b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 36231b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 36241b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable 36251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present. 3626a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends 3627a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of 3628a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata. 36291b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4( 3630a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 3631a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber sp<AMessage> *meta) { 3632a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // We scan up to 128 bytes to identify this file as an MP4. 3633a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber static const off64_t kMaxScanOffset = 128ll; 36341b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3635a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t offset = 0ll; 3636a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber bool foundGoodFileType = false; 3637a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t moovAtomEndOffset = -1ll; 3638a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber bool done = false; 36391b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3640a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber while (!done && offset < kMaxScanOffset) { 3641a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t hdr[2]; 3642a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (source->readAt(offset, hdr, 8) < 8) { 3643a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3644a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3645a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3646a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint64_t chunkSize = ntohl(hdr[0]); 3647a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t chunkType = ntohl(hdr[1]); 3648a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t chunkDataOffset = offset + 8; 3649a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3650a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (chunkSize == 1) { 3651a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (source->readAt(offset + 8, &chunkSize, 8) < 8) { 36521b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 36531b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 36541b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3655a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber chunkSize = ntoh64(chunkSize); 3656a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber chunkDataOffset += 8; 3657a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3658a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (chunkSize < 16) { 3659a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // The smallest valid chunk is 16 bytes long in this case. 3660a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3661a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3662a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } else if (chunkSize < 8) { 3663a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // The smallest valid chunk is 8 bytes long. 3664a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3665a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3666a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3667a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t chunkDataSize = offset + chunkSize - chunkDataOffset; 3668a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 366905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen char chunkstring[5]; 367005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MakeFourCCString(chunkType, chunkstring); 367105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("saw chunk type %s, size %lld @ %lld", chunkstring, chunkSize, offset); 3672a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber switch (chunkType) { 3673a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber case FOURCC('f', 't', 'y', 'p'): 3674a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber { 3675a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (chunkDataSize < 8) { 3676a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3677a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3678a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3679a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4; 3680a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber for (size_t i = 0; i < numCompatibleBrands + 2; ++i) { 3681a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (i == 1) { 3682a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // Skip this index, it refers to the minorVersion, 3683a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // not a brand. 3684a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber continue; 3685a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3686a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3687a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t brand; 3688a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (source->readAt( 3689a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber chunkDataOffset + 4 * i, &brand, 4) < 4) { 3690a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3691a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3692a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3693a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber brand = ntohl(brand); 3694a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3695a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (isCompatibleBrand(brand)) { 3696a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber foundGoodFileType = true; 3697a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber break; 3698a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3699a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3700a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3701a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (!foundGoodFileType) { 3702a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3703a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3704a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 37051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber break; 37061b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 3707a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3708a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber case FOURCC('m', 'o', 'o', 'v'): 3709a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber { 3710a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber moovAtomEndOffset = offset + chunkSize; 3711a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3712a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber done = true; 3713a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber break; 3714a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3715a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3716a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber default: 3717a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber break; 37181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 3719a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3720a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber offset += chunkSize; 37211b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 37221b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3723a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (!foundGoodFileType) { 37241b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 37251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 37261b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 37271b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 37285a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber *confidence = 0.4f; 37291b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3730a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (moovAtomEndOffset >= 0) { 3731a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber *meta = new AMessage; 3732a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber (*meta)->setInt64("meta-data-size", moovAtomEndOffset); 3733a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3734456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber ALOGV("found metadata size: %lld", moovAtomEndOffset); 3735a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3736a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 37371b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 37381b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 37391b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 37401b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4( 37415a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 3742a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber sp<AMessage> *meta) { 3743a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (BetterSniffMPEG4(source, mimeType, confidence, meta)) { 37441b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 37451b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 37461b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 37471b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (LegacySniffMPEG4(source, mimeType, confidence)) { 37485ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Identified supported mpeg4 through LegacySniffMPEG4."); 37491b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 37501b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 37511b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 37521b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 37531b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 37541b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 375520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3756