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), 344fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen mHeaderTimescale(0), 34520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFirstTrack(NULL), 34672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mLastTrack(NULL), 347dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mFileMetaData(new MetaData), 348dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mFirstSINF(NULL), 349dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mIsDrm(false) { 35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() { 35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (track) { 35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *next = track->next; 35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete track; 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = next; 35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFirstTrack = mLastTrack = NULL; 361dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 362dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *sinf = mFirstSINF; 363dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (sinf) { 364dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *next = sinf->next; 365dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang delete sinf->IPMPData; 366dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang delete sinf; 367dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf = next; 368dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 369dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mFirstSINF = NULL; 370ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 371ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mPssh.size(); i++) { 372ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen delete [] mPssh[i].data; 373ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenuint32_t MPEG4Extractor::flags() const { 37705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return CAN_PAUSE | 37805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ((mMoofOffset == 0 || mSidxEntries.size() != 0) ? 37905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0); 38005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 38105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 3827be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() { 3837be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber status_t err; 3847be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber if ((err = readMetaData()) != OK) { 38572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return new MetaData; 3867be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber } 3877be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 38872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return mFileMetaData; 3897be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber} 3907be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 391693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() { 39220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 39320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 394ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("MPEG4Extractor::countTracks: no tracks"); 395693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return 0; 39620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 39720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 398693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber size_t n = 0; 39920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 40020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (track) { 401693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber ++n; 40220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 40320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 40420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 405ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("MPEG4Extractor::countTracks: %d tracks", n); 406693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return n; 40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 40820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4097e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData( 4107e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber size_t index, uint32_t flags) { 41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 41220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 41520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (index > 0) { 41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (track == NULL) { 41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber --index; 42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 426371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber if (track == NULL) { 427371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber return NULL; 428371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber } 429371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber 4307e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber if ((flags & kIncludeExtensiveMetaData) 4317e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber && !track->includes_expensive_metadata) { 4327e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber track->includes_expensive_metadata = true; 4337e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 4347e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber const char *mime; 4357e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 4367e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber if (!strncasecmp("video/", mime, 6)) { 43705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mMoofOffset > 0) { 43805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t duration; 43905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (track->meta->findInt64(kKeyDuration, &duration)) { 44005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // nothing fancy, just pick a frame near 1/4th of the duration 44105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen track->meta->setInt64( 44205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyThumbnailTime, duration / 4); 44305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 44405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 44505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleIndex; 44605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleTime; 44705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK 44805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen && track->sampleTable->getMetaDataForSample( 44905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleIndex, NULL /* offset */, NULL /* size */, 45005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen &sampleTime) == OK) { 45105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen track->meta->setInt64( 45205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyThumbnailTime, 45305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ((int64_t)sampleTime * 1000000) / track->timescale); 45405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 4557e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 4567e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 4577e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 4587e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 45920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return track->meta; 46020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 46120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 46248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) { 46348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[0] = x >> 24; 46448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[1] = (x >> 16) & 0xff; 46548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[2] = (x >> 8) & 0xff; 46648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[3] = x & 0xff; 46748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[4] = '\0'; 46848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen} 46948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 47020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() { 471bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber if (mInitCheck != NO_INIT) { 472bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return mInitCheck; 47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 475c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = 0; 47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 47705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen while (true) { 47805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen err = parseChunk(&offset, 0); 47905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (err == OK) { 48005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen continue; 48105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 48205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 48305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t hdr[2]; 48405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mDataSource->readAt(offset, hdr, 8) < 8) { 48505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 48605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 48705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t chunk_type = ntohl(hdr[1]); 48805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_type == FOURCC('s', 'i', 'd', 'x')) { 48905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // parse the sidx box too 49005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen continue; 49105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (chunk_type == FOURCC('m', 'o', 'o', 'f')) { 49205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // store the offset of the first segment 49305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mMoofOffset = offset; 49405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 49505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 49620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 4977be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 498bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber if (mInitCheck == OK) { 49972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mHasVideo) { 500bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber mFileMetaData->setCString( 501bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4); 50272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 50372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyMIMEType, "audio/mp4"); 50472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 50572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 5064678a6dc5f09008481524949a9667af5a6190374Andreas Huber mInitCheck = OK; 507bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber } else { 508bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber mInitCheck = err; 50920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 51020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 511bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber CHECK_NE(err, (status_t)NO_INIT); 512ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 513ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // copy pssh data into file metadata 514ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int psshsize = 0; 515ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mPssh.size(); i++) { 516ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen psshsize += 20 + mPssh[i].datalen; 517ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 518ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (psshsize) { 519ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen char *buf = (char*)malloc(psshsize); 520ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen char *ptr = buf; 521ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mPssh.size(); i++) { 522ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memcpy(ptr, mPssh[i].uuid, 20); // uuid + length 523ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen); 524ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ptr += (20 + mPssh[i].datalen); 525ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 526ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize); 527ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen free(buf); 528ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 529bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return mInitCheck; 53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 532dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) { 533dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mFirstSINF == NULL) { 534dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return NULL; 535dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 536dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 537dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *sinf = mFirstSINF; 538dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (sinf && (trackID != sinf->trackID)) { 539dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf = sinf->next; 540dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 541dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 542dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (sinf == NULL) { 543dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return NULL; 544dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 545dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 546dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang *len = sinf->len; 547dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return sinf->IPMPData; 548dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang} 549dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 550dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear. 55156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic int32_t readSize(off64_t offset, 552dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang const sp<DataSource> DataSource, uint8_t *numOfBytes) { 553dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint32_t size = 0; 554dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t data; 555dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang bool moreData = true; 556dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang *numOfBytes = 0; 557dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 558dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (moreData) { 559dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (DataSource->readAt(offset, &data, 1) < 1) { 560dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return -1; 561dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 562dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang offset ++; 563dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang moreData = (data >= 128) ? true : false; 564dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size = (size << 7) | (data & 0x7f); // Take last 7 bits 565dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang (*numOfBytes) ++; 566dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 567dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 568dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return size; 569dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang} 570dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 571c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) { 572dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t updateIdTag; 573dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) { 574dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 575dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 576dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 577dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 578dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) { 579dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 580dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 581dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 582dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t numOfBytes; 583dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t size = readSize(data_offset, mDataSource, &numOfBytes); 584dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (size < 0) { 585dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 586dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 587dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t classSize = size; 588dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += numOfBytes; 589dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 590dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while(size >= 11 ) { 591dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t descriptorTag; 592dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) { 593dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 594dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 595dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 596dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 597dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) { 598dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 599dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 600dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 601dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t buffer[8]; 602dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang //ObjectDescriptorID and ObjectDescriptor url flag 603dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, buffer, 2) < 2) { 604dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 605dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 606dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += 2; 607dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 608dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if ((buffer[1] >> 5) & 0x0001) { //url flag is set 609dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 610dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 611dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 612dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, buffer, 8) < 8) { 613dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 614dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 615dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += 8; 616dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 617dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1]) 618dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) { 619dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 620dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 621dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 622dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *sinf = new SINF; 623dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->trackID = U16_AT(&buffer[3]); 624dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->IPMPDescriptorID = buffer[7]; 625dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->next = mFirstSINF; 626dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mFirstSINF = sinf; 627dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 628dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size -= (8 + 2 + 1); 629dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 630dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 631dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (size != 0) { 632dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 633dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 634dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 635dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) { 636dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 637dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 638dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 639dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) { 641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size = readSize(data_offset, mDataSource, &numOfBytes); 645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (size < 0) { 646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 648dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang classSize = size; 649dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += numOfBytes; 650dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 651dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (size > 0) { 652dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t tag; 653dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t dataLen; 654dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &tag, 1) < 1) { 655dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 656dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) { 660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t id; 661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dataLen = readSize(data_offset, mDataSource, &numOfBytes); 662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (dataLen < 0) { 663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else if (dataLen < 4) { 665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += numOfBytes; 668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &id, 1) < 1) { 670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 672dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 673dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 674dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *sinf = mFirstSINF; 675dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (sinf && (sinf->IPMPDescriptorID != id)) { 676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf = sinf->next; 677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 678dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (sinf == NULL) { 679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->len = dataLen - 3; 682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->IPMPData = new char[sinf->len]; 683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) { 685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += sinf->len; 688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size -= (dataLen + numOfBytes + 1); 690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (size != 0) { 694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return UNKNOWN_ERROR; // Return a dummy error. 698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang} 699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 70072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder { 70172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder(Vector<uint32_t> *path, uint32_t chunkType) 70272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber : mPath(path) { 70372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mPath->push(chunkType); 70472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 70572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 70672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber ~PathAdder() { 70772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mPath->pop(); 70872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 70972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 71072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate: 71172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber Vector<uint32_t> *mPath; 71272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 71372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder(const PathAdder &); 71472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder &operator=(const PathAdder &); 71572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}; 71672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 71772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) { 71872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return path.size() >= 5 71972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[0] == FOURCC('m', 'o', 'o', 'v') 72072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[1] == FOURCC('u', 'd', 't', 'a') 72172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[2] == FOURCC('m', 'e', 't', 'a') 72272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[3] == FOURCC('i', 'l', 's', 't'); 72372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 72472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 72572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string. 72672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) { 72772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600); 72872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 72972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char tmp[32]; 73072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970)); 73172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 73272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber s->setTo(tmp); 73372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 73472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 735c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { 7365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen ALOGV("entering parseChunk %lld/%d", *offset, depth); 73720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t hdr[2]; 73834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt(*offset, hdr, 8) < 8) { 73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint64_t chunk_size = ntohl(hdr[0]); 74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t chunk_type = ntohl(hdr[1]); 743c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t data_offset = *offset + 8; 74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_size == 1) { 74634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { 74720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 74820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 74920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_size = ntoh64(chunk_size); 75020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset += 8; 75171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber 75271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber if (chunk_size < 16) { 75371b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber // The smallest valid chunk is 16 bytes long in this case. 75471b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber return ERROR_MALFORMED; 75571b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber } 75671b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber } else if (chunk_size < 8) { 75771b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber // The smallest valid chunk is 8 bytes long. 75871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber return ERROR_MALFORMED; 75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 76020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber char chunk[5]; 76220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MakeFourCCString(chunk_type, chunk); 76305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth); 76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0 76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const char kWhitespace[] = " "; 76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth]; 76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size); 76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber char buffer[256]; 771ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber size_t n = chunk_size; 772ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber if (n > sizeof(buffer)) { 773ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber n = sizeof(buffer); 774ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber } 775ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber if (mDataSource->readAt(*offset, buffer, n) 776ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber < (ssize_t)n) { 777ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber return ERROR_IO; 77820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 779ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber 780ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber hexdump(buffer, n); 78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif 78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder autoAdder(&mPath, chunk_type); 78472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 785c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t chunk_data_size = *offset + chunk_size - data_offset; 78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (chunk_type != FOURCC('c', 'p', 'r', 't') 788515e855eae78aa495da58356486aaa666cb57fd1James Dong && chunk_type != FOURCC('c', 'o', 'v', 'r') 78972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && mPath.size() == 5 && underMetaDataPath(mPath)) { 790c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 79172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset = data_offset; 79272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber while (*offset < stop_offset) { 79372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseChunk(offset, depth + 1); 79472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 79572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 79672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 79772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 798bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 799bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 800bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 801bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 80272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 80372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return OK; 80472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 80572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber switch(chunk_type) { 80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'o', 'o', 'v'): 80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'r', 'a', 'k'): 80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'd', 'i', 'a'): 81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'i', 'n', 'f'): 81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('d', 'i', 'n', 'f'): 81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'b', 'l'): 81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'v', 'e', 'x'): 81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'o', 'o', 'f'): 81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'r', 'a', 'f'): 81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'f', 'r', 'a'): 81772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('u', 'd', 't', 'a'): 81872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('i', 'l', 's', 't'): 819ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'i', 'n', 'f'): 820ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'c', 'h', 'i'): 8210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen case FOURCC('e', 'd', 't', 's'): 82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 82350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (chunk_type == FOURCC('s', 't', 'b', 'l')) { 8243856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size); 82550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 826b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber if (mDataSource->flags() 827b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber & (DataSource::kWantsPrefetching 828b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber | DataSource::kIsCachingDataSource)) { 82950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber sp<MPEG4DataSource> cachedSource = 83050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber new MPEG4DataSource(mDataSource); 83150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 83250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (cachedSource->setCachedRange(*offset, chunk_size) == OK) { 83350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mDataSource = cachedSource; 83450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 83550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 8361edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber 8371edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber mLastTrack->sampleTable = new SampleTable(mDataSource); 83850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 83950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 8406f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber bool isTrack = false; 841bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (chunk_type == FOURCC('t', 'r', 'a', 'k')) { 8426f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber isTrack = true; 8436f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 844bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber Track *track = new Track; 845bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->next = NULL; 846bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (mLastTrack) { 847bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber mLastTrack->next = track; 848bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else { 849bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber mFirstTrack = track; 850bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 851bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber mLastTrack = track; 852bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 853bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->meta = new MetaData; 854bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->includes_expensive_metadata = false; 8556f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber track->skipTrack = false; 856bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->timescale = 0; 857bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->meta->setCString(kKeyMIMEType, "application/octet-stream"); 858bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 859bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 860c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset; 86220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 86320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 86420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 86520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 86720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 86820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 869bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 870bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 871bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 872bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 8736f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber if (isTrack) { 8746f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber if (mLastTrack->skipTrack) { 8756f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber Track *cur = mFirstTrack; 8766f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 8776f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber if (cur == mLastTrack) { 8786f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber delete cur; 8796f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber mFirstTrack = mLastTrack = NULL; 8806f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } else { 8816f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber while (cur && cur->next != mLastTrack) { 8826f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber cur = cur->next; 8836f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } 8846f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber cur->next = NULL; 8856f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber delete mLastTrack; 8866f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber mLastTrack = cur; 8876f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } 8886f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 8896f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber return OK; 8906f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } 8916f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 892bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber status_t err = verifyTrack(mLastTrack); 893bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 894bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (err != OK) { 895bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return err; 896bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 897bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { 898bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber mInitCheck = OK; 89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 900dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (!mIsDrm) { 901dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return UNKNOWN_ERROR; // Return a dummy error. 902dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else { 903dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return OK; 904dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9090a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen case FOURCC('e', 'l', 's', 't'): 9100a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen { 9110a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen // See 14496-12 8.6.6 9120a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint8_t version; 9130a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (mDataSource->readAt(data_offset, &version, 1) < 1) { 9140a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9150a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9160a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9170a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint32_t entry_count; 9180a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) { 9190a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9220a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (entry_count != 1) { 9230a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen // we only support a single entry at the moment, for gapless playback 9240a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen ALOGW("ignoring edit list with %d entries", entry_count); 925fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen } else if (mHeaderTimescale == 0) { 926210efd48ed21ca0084d9440f9a1db7d9878f8094Marco Nelissen ALOGW("ignoring edit list because timescale is 0"); 9270a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } else { 9280a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen off64_t entriesoffset = data_offset + 8; 9290a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint64_t segment_duration; 9300a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t media_time; 9310a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9320a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (version == 1) { 9330a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (!mDataSource->getUInt64(entriesoffset, &segment_duration) || 9340a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) { 9350a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9360a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9370a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } else if (version == 0) { 9380a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint32_t sd; 9390a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int32_t mt; 9400a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (!mDataSource->getUInt32(entriesoffset, &sd) || 9410a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) { 9420a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9430a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9440a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen segment_duration = sd; 9450a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen media_time = mt; 9460a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } else { 9470a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9480a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9490a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 950fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen uint64_t halfscale = mHeaderTimescale / 2; 951fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale; 952fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale; 9530a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9540a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t duration; 9550a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int32_t samplerate; 9560a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (mLastTrack->meta->findInt64(kKeyDuration, &duration) && 9570a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) { 9580a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9590a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t delay = (media_time * samplerate + 500000) / 1000000; 9600a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen mLastTrack->meta->setInt32(kKeyEncoderDelay, delay); 9610a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9620a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t paddingus = duration - (segment_duration + media_time); 9630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000; 9640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples); 9650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9670a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen *offset += chunk_size; 9680a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen break; 9690a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9700a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 971ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('f', 'r', 'm', 'a'): 972ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen { 97348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t original_fourcc; 974ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) { 975ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 976ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 977ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen original_fourcc = ntohl(original_fourcc); 978ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("read original format: %d", original_fourcc); 979ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc)); 98048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t num_channels = 0; 98148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t sample_rate = 0; 98248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) { 98348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 98448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 98548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 986ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 987ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 988ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 989ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 990ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('t', 'e', 'n', 'c'): 991ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen { 992ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (chunk_size < 32) { 993ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 994ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 995ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 996ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte 997ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // default IV size, 16 bytes default KeyID 998ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // (ISO 23001-7) 999ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen char buf[4]; 1000ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(buf, 0, 4); 1001ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) { 1002ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1003ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1004ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf)); 1005ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (defaultAlgorithmId > 1) { 1006ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // only 0 (clear) and 1 (AES-128) are valid 1007ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1008ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1009ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1010ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(buf, 0, 4); 1011ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) { 1012ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1013ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1014ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t defaultIVSize = ntohl(*((int32_t*)buf)); 1015ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1016ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if ((defaultAlgorithmId == 0 && defaultIVSize != 0) || 1017ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen (defaultAlgorithmId != 0 && defaultIVSize == 0)) { 1018ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // only unencrypted data must have 0 IV size 1019ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1020ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } else if (defaultIVSize != 0 && 1021ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen defaultIVSize != 8 && 1022ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen defaultIVSize != 16) { 1023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // only supported sizes are 0, 8 and 16 1024ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1025ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1026ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1027ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t defaultKeyId[16]; 1028ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) { 1030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1033ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId); 1034ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize); 1035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16); 1036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 1037ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 1038ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1039ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 104020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'k', 'h', 'd'): 104120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 1042ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber status_t err; 1043ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) { 1044ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return err; 104520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 104720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 104820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 104920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 105020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1051ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('p', 's', 's', 'h'): 1052ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen { 1053ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen PsshInfo pssh; 1054ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1055ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) { 1056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1058ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t psshdatalen = 0; 1060ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) { 1061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen pssh.datalen = ntohl(psshdatalen); 1064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("pssh data size: %d", pssh.datalen); 1065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (pssh.datalen + 20 > chunk_size) { 1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // pssh data length exceeds size of containing box 1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen pssh.data = new uint8_t[pssh.datalen]; 1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("allocated pssh @ %p", pssh.data); 1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ssize_t requested = (ssize_t) pssh.datalen; 1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) { 1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mPssh.push_back(pssh); 1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 1079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 1080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 108220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'd', 'h', 'd'): 108320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 108420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 4) { 108520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 108620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 108720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 108820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t version; 108934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 109020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, &version, sizeof(version)) 109120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(version)) { 109220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 109320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 109420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1095c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t timescale_offset; 109620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 109720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (version == 1) { 109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset = data_offset + 4 + 16; 109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else if (version == 0) { 110020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset = data_offset + 4 + 8; 110120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 110320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 110520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t timescale; 110634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset, ×cale, sizeof(timescale)) 110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(timescale)) { 110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 111220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->timescale = ntohl(timescale); 111320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 111405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t duration = 0; 111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (version == 1) { 111634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 111720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset + 4, &duration, sizeof(duration)) 111820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(duration)) { 111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 112020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber duration = ntoh64(duration); 112220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 112305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t duration32; 112434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 112520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset + 4, &duration32, sizeof(duration32)) 112620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(duration32)) { 112720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 112905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // ffmpeg sets duration to -1, which is incorrect. 113005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (duration32 != 0xffffffff) { 113105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen duration = ntohl(duration32); 113205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 113448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mLastTrack->meta->setInt64( 113548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber kKeyDuration, (duration * 1000000) / mLastTrack->timescale); 113620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11377a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang uint8_t lang[2]; 11387a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang off64_t lang_offset; 11397a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang if (version == 1) { 11407a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_offset = timescale_offset + 4 + 8; 11417a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } else if (version == 0) { 11427a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_offset = timescale_offset + 4 + 4; 11437a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } else { 11447a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang return ERROR_IO; 11457a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 11467a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 11477a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang if (mDataSource->readAt(lang_offset, &lang, sizeof(lang)) 11487a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang < (ssize_t)sizeof(lang)) { 11497a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang return ERROR_IO; 11507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 11517a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 11527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // To get the ISO-639-2/T three character language code 11537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // 1 bit pad followed by 3 5-bits characters. Each character 11547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // is packed as the difference between its ASCII value and 0x60. 11557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang char lang_code[4]; 11567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60; 11577a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60; 11587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[2] = (lang[1] & 0x1f) + 0x60; 11597a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[3] = '\0'; 11607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 11617a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang mLastTrack->meta->setCString( 11627a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang kKeyMediaLanguage, lang_code); 11637a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 116620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'd'): 116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 8) { 117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[8]; 1175c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (chunk_data_size < (off64_t)sizeof(buffer)) { 1176bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1177bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 1178bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 117934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, 8) < 8) { 118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 118320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (U32_AT(buffer) != 0) { 118520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Should be version 0, flags 0. 118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t entry_count = U32_AT(&buffer[4]); 119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (entry_count > 1) { 11923b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // For 3GPP timed text, there could be multiple tx3g boxes contain 11933b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // multiple text display formats. These formats will be used to 11943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // display the timed text. 1195ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // For encrypted files, there may also be more than one entry. 11963b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang const char *mime; 11973b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 1198ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) && 1199ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen strcasecmp(mime, "application/octet-stream")) { 12003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // For now we only support a single type of media per track. 12013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang mLastTrack->skipTrack = true; 12023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang *offset += chunk_size; 12033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang break; 12043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1206c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + 8; 120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (uint32_t i = 0; i < entry_count; ++i) { 120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 121020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 121220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1214bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1215bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1216bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1217bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 122020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 122120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'a'): 122248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen case FOURCC('e', 'n', 'c', 'a'): 122320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 1224371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber case FOURCC('s', 'a', 'w', 'b'): 122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[8 + 20]; 122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 122820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Basic AudioSampleEntry size. 122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 123848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t num_channels = U16_AT(&buffer[16]); 123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 124081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint16_t sample_size = U16_AT(&buffer[18]); 124181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint32_t sample_rate = U32_AT(&buffer[24]) >> 16; 124281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 124348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (chunk_type != FOURCC('e', 'n', 'c', 'a')) { 124448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // if the chunk type is enca, we'll get the type from the sinf/frma box later 124548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 124648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate); 124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 124848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen ALOGV("*** coding='%s' %d channels, size %d, rate %d\n", 124981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber chunk, num_channels, sample_size, sample_rate); 125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1253c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + sizeof(buffer); 125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 125920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1261bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1262bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1263bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1264bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 126720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 126820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'v'): 1269ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('e', 'n', 'c', 'v'): 127020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', '2', '6', '3'): 1271e071b055cee301d71335519601474c62b10af411James Dong case FOURCC('H', '2', '6', '3'): 1272e071b055cee301d71335519601474c62b10af411James Dong case FOURCC('h', '2', '6', '3'): 127320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', '1'): 127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 12757be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber mHasVideo = true; 12767be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[78]; 127820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Basic VideoSampleEntry size. 128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 128120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 128334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t width = U16_AT(&buffer[6 + 18]); 129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t height = U16_AT(&buffer[6 + 20]); 129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1292ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // The video sample is not standard-compliant if it has invalid dimension. 1293a6256238d9015c42129fe43791968768fe501efaJames Dong // Use some default width and height value, and 1294a6256238d9015c42129fe43791968768fe501efaJames Dong // let the decoder figure out the actual width and height (and thus 1295a6256238d9015c42129fe43791968768fe501efaJames Dong // be prepared for INFO_FOMRAT_CHANGED event). 1296a6256238d9015c42129fe43791968768fe501efaJames Dong if (width == 0) width = 352; 1297a6256238d9015c42129fe43791968768fe501efaJames Dong if (height == 0) height = 288; 1298a6256238d9015c42129fe43791968768fe501efaJames Dong 1299134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber // printf("*** coding='%s' width=%d height=%d\n", 1300134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber // chunk, width, height); 130120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1302ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (chunk_type != FOURCC('e', 'n', 'c', 'v')) { 1303ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // if the chunk type is encv, we'll get the type from the sinf/frma box later 1304ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 1305ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 130620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyWidth, width); 130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyHeight, height); 130820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1309c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 131020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + sizeof(buffer); 131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 131520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1317bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1318bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1319bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1320bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'c', 'o'): 132520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('c', 'o', '6', '4'): 132620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setChunkOffsetParams( 132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_type, data_offset, chunk_data_size); 133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'c'): 134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSampleToChunkParams( 134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'z'): 135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'z', '2'): 135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSampleSizeParams( 135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_type, data_offset, chunk_data_size); 135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1364738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber size_t max_size; 136549110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber err = mLastTrack->sampleTable->getMaxSampleSize(&max_size); 136649110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber 136749110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber if (err != OK) { 136849110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber return err; 136949110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber } 1370738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber 137105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (max_size != 0) { 137205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // Assume that a given buffer only contains at most 10 chunks, 137305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // each chunk originally prefixed with a 2 byte length will 137405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion, 137505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // and thus will grow by 2 bytes per chunk. 137605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2); 137705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 137805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // No size was specified. Pick a conservatively large size. 137905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t width, height; 1380f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar if (!mLastTrack->meta->findInt32(kKeyWidth, &width) || 1381f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar !mLastTrack->meta->findInt32(kKeyHeight, &height)) { 138205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGE("No width or height, assuming worst case 1080p"); 1383f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar width = 1920; 1384f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar height = 1080; 138505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 1386f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar 13874256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen const char *mime; 13884256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 1389f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 1390f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar // AVC requires compression ratio of at least 2, and uses 1391f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar // macroblocks 1392f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192; 1393f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar } else { 1394f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar // For all other formats there is no minimum compression 1395f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar // ratio. Use compression ratio of 1. 1396f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar max_size = width * height * 3 / 2; 1397f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar } 1398f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size); 139905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 140020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 1401113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong 14024256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen // NOTE: setting another piece of metadata invalidates any pointers (such as the 14034256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen // mimetype) previously obtained, so don't cache them. 14044256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen const char *mime; 14054256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 1406113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong // Calculate average frame rate. 1407113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong if (!strncasecmp("video/", mime, 6)) { 1408113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong size_t nSamples = mLastTrack->sampleTable->countSamples(); 1409113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong int64_t durationUs; 1410113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) { 1411113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong if (durationUs > 0) { 1412113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong int32_t frameRate = (nSamples * 1000000LL + 1413113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong (durationUs >> 1)) / durationUs; 1414113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong mLastTrack->meta->setInt32(kKeyFrameRate, frameRate); 1415113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong } 1416113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong } 1417113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong } 1418113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong 141920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 142020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 142120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 't', 's'): 142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 142420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 142520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setTimeToSampleParams( 142620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 142820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 143120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 143220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 143520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14364931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber case FOURCC('c', 't', 't', 's'): 14374931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber { 14384931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber status_t err = 14394931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber mLastTrack->sampleTable->setCompositionTimeToSampleParams( 14404931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber data_offset, chunk_data_size); 14414931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 14424931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber if (err != OK) { 14434931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber return err; 14444931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 14454931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 14464931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber *offset += chunk_size; 14474931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber break; 14484931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 14494931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 145020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 's'): 145120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 145220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 145320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSyncSampleParams( 145420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 145520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 145720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 145820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 145920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 146020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 146320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14644948818cb91176df74c972ac27b2f392b5d148bcJames Dong // @xyz 14654948818cb91176df74c972ac27b2f392b5d148bcJames Dong case FOURCC('\xA9', 'x', 'y', 'z'): 14664948818cb91176df74c972ac27b2f392b5d148bcJames Dong { 14674948818cb91176df74c972ac27b2f392b5d148bcJames Dong // Best case the total data length inside "@xyz" box 14684948818cb91176df74c972ac27b2f392b5d148bcJames Dong // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/", 14694948818cb91176df74c972ac27b2f392b5d148bcJames Dong // where "\x00\x04" is the text string length with value = 4, 14704948818cb91176df74c972ac27b2f392b5d148bcJames Dong // "\0x15\xc7" is the language code = en, and "0+0" is a 14714948818cb91176df74c972ac27b2f392b5d148bcJames Dong // location (string) value with longitude = 0 and latitude = 0. 14724948818cb91176df74c972ac27b2f392b5d148bcJames Dong if (chunk_data_size < 8) { 14734948818cb91176df74c972ac27b2f392b5d148bcJames Dong return ERROR_MALFORMED; 14744948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 14754948818cb91176df74c972ac27b2f392b5d148bcJames Dong 14764948818cb91176df74c972ac27b2f392b5d148bcJames Dong // Worst case the location string length would be 18, 14774948818cb91176df74c972ac27b2f392b5d148bcJames Dong // for instance +90.0000-180.0000, without the trailing "/" and 14784948818cb91176df74c972ac27b2f392b5d148bcJames Dong // the string length + language code. 14794948818cb91176df74c972ac27b2f392b5d148bcJames Dong char buffer[18]; 14804948818cb91176df74c972ac27b2f392b5d148bcJames Dong 14814948818cb91176df74c972ac27b2f392b5d148bcJames Dong // Substracting 5 from the data size is because the text string length + 14824948818cb91176df74c972ac27b2f392b5d148bcJames Dong // language code takes 4 bytes, and the trailing slash "/" takes 1 byte. 14834948818cb91176df74c972ac27b2f392b5d148bcJames Dong off64_t location_length = chunk_data_size - 5; 14844948818cb91176df74c972ac27b2f392b5d148bcJames Dong if (location_length >= (off64_t) sizeof(buffer)) { 14854948818cb91176df74c972ac27b2f392b5d148bcJames Dong return ERROR_MALFORMED; 14864948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 14874948818cb91176df74c972ac27b2f392b5d148bcJames Dong 14884948818cb91176df74c972ac27b2f392b5d148bcJames Dong if (mDataSource->readAt( 14894948818cb91176df74c972ac27b2f392b5d148bcJames Dong data_offset + 4, buffer, location_length) < location_length) { 14904948818cb91176df74c972ac27b2f392b5d148bcJames Dong return ERROR_IO; 14914948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 14924948818cb91176df74c972ac27b2f392b5d148bcJames Dong 14934948818cb91176df74c972ac27b2f392b5d148bcJames Dong buffer[location_length] = '\0'; 14944948818cb91176df74c972ac27b2f392b5d148bcJames Dong mFileMetaData->setCString(kKeyLocation, buffer); 14954948818cb91176df74c972ac27b2f392b5d148bcJames Dong *offset += chunk_size; 14964948818cb91176df74c972ac27b2f392b5d148bcJames Dong break; 14974948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 14984948818cb91176df74c972ac27b2f392b5d148bcJames Dong 149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('e', 's', 'd', 's'): 150020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 4) { 150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 150420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 150520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[256]; 1506c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (chunk_data_size > (off64_t)sizeof(buffer)) { 150720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_BUFFER_TOO_SMALL; 150820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 150920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 151034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 151120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 151220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 151320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 151420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 151520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (U32_AT(buffer) != 0) { 151620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Should be version 0, flags 0. 151720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 152020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setData( 152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); 152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1523ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (mPath.size() >= 2 1524ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) { 1525ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // Information from the ESDS must be relied on for proper 1526ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // setup of sample rate and channel count for MPEG4 Audio. 1527ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // The generic header appears to only contain generic 1528ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // information... 1529ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1530ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio( 1531ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber &buffer[4], chunk_data_size - 4); 1532ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1533ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (err != OK) { 1534ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return err; 1535ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1536ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1537ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 154020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 154120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 154220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', 'C'): 154320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 1544d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson sp<ABuffer> buffer = new ABuffer(chunk_data_size); 154520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 154634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 1547d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson data_offset, buffer->data(), chunk_data_size) < chunk_data_size) { 154820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 154920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 155020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 155120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setData( 1552d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size); 155320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 155420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 155520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 155620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 155720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1558244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong case FOURCC('d', '2', '6', '3'): 1559244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong { 156017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong /* 156117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * d263 contains a fixed 7 bytes part: 156217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * vendor - 4 bytes 156317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * version - 1 byte 156417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * level - 1 byte 156517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * profile - 1 byte 156617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * optionally, "d263" box itself may contain a 16-byte 156717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * bit rate box (bitr) 156817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * average bit rate - 4 bytes 156917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * max bit rate - 4 bytes 157017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong */ 157117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong char buffer[23]; 157217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong if (chunk_data_size != 7 && 157317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong chunk_data_size != 23) { 157429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Incorrect D263 box size %lld", chunk_data_size); 1575244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong return ERROR_MALFORMED; 1576244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong } 1577244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 1578244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong if (mDataSource->readAt( 1579244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong data_offset, buffer, chunk_data_size) < chunk_data_size) { 1580244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong return ERROR_IO; 1581244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong } 1582244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 1583244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size); 1584244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 1585244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong *offset += chunk_size; 1586244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong break; 1587244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong } 1588244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 158972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('m', 'e', 't', 'a'): 159072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 159172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint8_t buffer[4]; 1592c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (chunk_data_size < (off64_t)sizeof(buffer)) { 1593bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1594bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 1595bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 159672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 159772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber data_offset, buffer, 4) < 4) { 159872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 159972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 160072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 160172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (U32_AT(buffer) != 0) { 160272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber // Should be version 0, flags 0. 1603ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber 1604ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // If it's not, let's assume this is one of those 1605ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // apparently malformed chunks that don't have flags 1606ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // and completely different semantics than what's 1607ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // in the MPEG4 specs and skip it. 1608ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber *offset += chunk_size; 1609ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber return OK; 161072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 161172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1612c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 161372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset = data_offset + sizeof(buffer); 161472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber while (*offset < stop_offset) { 161572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseChunk(offset, depth + 1); 161672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 161772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 161872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 161972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 1620bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1621bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1622bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1623bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 162472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 162572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 162672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 16275d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('m', 'e', 'a', 'n'): 16285d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('n', 'a', 'm', 'e'): 162972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('d', 'a', 't', 'a'): 163072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 163172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mPath.size() == 6 && underMetaDataPath(mPath)) { 163272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseMetaData(data_offset, chunk_data_size); 163372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 163472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 163572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 163672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 163772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 163872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 163972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset += chunk_size; 164072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 164172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 164272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 164372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('m', 'v', 'h', 'd'): 164472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 1645fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen if (chunk_data_size < 24) { 164672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_MALFORMED; 164772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 164872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1649fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen uint8_t header[24]; 165072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 165172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber data_offset, header, sizeof(header)) 165272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber < (ssize_t)sizeof(header)) { 165372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 165472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 165572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1656fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen uint64_t creationTime; 165772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (header[0] == 1) { 165872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber creationTime = U64_AT(&header[4]); 1659fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen mHeaderTimescale = U32_AT(&header[20]); 1660bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (header[0] != 0) { 1661bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 166272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 166372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber creationTime = U32_AT(&header[4]); 1664fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen mHeaderTimescale = U32_AT(&header[12]); 166572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 166672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 166772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber String8 s; 166872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber convertTimeToDate(creationTime, &s); 166972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 167072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyDate, s.string()); 167172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 167272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset += chunk_size; 167372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 167472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 167572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang case FOURCC('m', 'd', 'a', 't'): 1677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang { 1678ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("mdat chunk, drm: %d", mIsDrm); 1679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (!mIsDrm) { 1680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang *offset += chunk_size; 1681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang break; 1682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 1684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (chunk_size < 8) { 1685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 1686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 1688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return parseDrmSINF(offset, data_offset); 1689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 16913b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang case FOURCC('h', 'd', 'l', 'r'): 16923b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang { 16933b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint32_t buffer; 16943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if (mDataSource->readAt( 16953b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang data_offset + 8, &buffer, 4) < 4) { 16963b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang return ERROR_IO; 16973b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 16983b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 16993b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint32_t type = ntohl(buffer); 17003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // For the 3GPP file format, the handler-type within the 'hdlr' box 1701e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang // shall be 'text'. We also want to support 'sbtl' handler type 1702e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang // for a practical reason as various MPEG4 containers use it. 1703e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) { 17043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP); 17053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang *offset += chunk_size; 17083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang break; 17093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17117a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang case FOURCC('t', 'x', '3', 'g'): 17127a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang { 17133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint32_t type; 17143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang const void *data; 17153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang size_t size = 0; 17163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if (!mLastTrack->meta->findData( 17173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang kKeyTextFormatData, &type, &data, &size)) { 17183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang size = 0; 17193b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17203b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17213b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint8_t *buffer = new uint8_t[size + chunk_size]; 17223b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17233b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if (size > 0) { 17243b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang memcpy(buffer, data, size); 17253b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17273b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size)) 17283b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang < chunk_size) { 17293b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang delete[] buffer; 17303b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang buffer = NULL; 17313b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17323b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang return ERROR_IO; 17333b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17343b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17353b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang mLastTrack->meta->setData( 17363b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang kKeyTextFormatData, 0, buffer, size + chunk_size); 17373b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17383b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang delete[] buffer; 17397a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 17407a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang *offset += chunk_size; 17417a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang break; 17427a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 17437a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 1744515e855eae78aa495da58356486aaa666cb57fd1James Dong case FOURCC('c', 'o', 'v', 'r'): 1745515e855eae78aa495da58356486aaa666cb57fd1James Dong { 1746515e855eae78aa495da58356486aaa666cb57fd1James Dong if (mFileMetaData != NULL) { 17473856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("chunk_data_size = %lld and data_offset = %lld", 1748515e855eae78aa495da58356486aaa666cb57fd1James Dong chunk_data_size, data_offset); 17491552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1); 1750515e855eae78aa495da58356486aaa666cb57fd1James Dong if (mDataSource->readAt( 17511552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) { 1752515e855eae78aa495da58356486aaa666cb57fd1James Dong return ERROR_IO; 1753515e855eae78aa495da58356486aaa666cb57fd1James Dong } 1754515e855eae78aa495da58356486aaa666cb57fd1James Dong const int kSkipBytesOfDataBox = 16; 1755515e855eae78aa495da58356486aaa666cb57fd1James Dong mFileMetaData->setData( 1756515e855eae78aa495da58356486aaa666cb57fd1James Dong kKeyAlbumArt, MetaData::TYPE_NONE, 17571552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox); 1758515e855eae78aa495da58356486aaa666cb57fd1James Dong } 1759515e855eae78aa495da58356486aaa666cb57fd1James Dong 1760515e855eae78aa495da58356486aaa666cb57fd1James Dong *offset += chunk_size; 1761515e855eae78aa495da58356486aaa666cb57fd1James Dong break; 1762515e855eae78aa495da58356486aaa666cb57fd1James Dong } 1763515e855eae78aa495da58356486aaa666cb57fd1James Dong 17645d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('-', '-', '-', '-'): 17655d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen { 17665d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentMean.clear(); 17675d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentName.clear(); 17685d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentData.clear(); 17695d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen *offset += chunk_size; 17705d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 17715d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 17725d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen 177305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('s', 'i', 'd', 'x'): 177405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen { 177505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseSegmentIndex(data_offset, chunk_data_size); 177605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 177705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return UNKNOWN_ERROR; // stop parsing after sidx 177805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 177905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 178020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber default: 178120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 178220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 178320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 178420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 178520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 178620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 178720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 178820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 178920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 179005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) { 179105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Extractor::parseSegmentIndex"); 179205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 179305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 12) { 179405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 179505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 179605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 179705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t flags; 179805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &flags)) { 179905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 180005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 180105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 180205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t version = flags >> 24; 180305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen flags &= 0xffffff; 180405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 180505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("sidx version %d", version); 180605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 180705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t referenceId; 180805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, &referenceId)) { 180905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 181005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 181105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 181205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t timeScale; 181305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 8, &timeScale)) { 181405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 181505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 181605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale); 181705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 181805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t earliestPresentationTime; 181905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t firstOffset; 182005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 182105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 12; 182205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 12; 182305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 182405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (version == 0) { 182505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 182605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 182705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 182805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t tmp; 182905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 183005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 183105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 183205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen earliestPresentationTime = tmp; 183305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, &tmp)) { 183405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 183505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 183605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen firstOffset = tmp; 183705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 183805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 183905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 184005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 16) { 184105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 184205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 184305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) { 184405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 184505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 184605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt64(offset + 8, &firstOffset)) { 184705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 184805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 184905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 16; 185005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 16; 185105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 185205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset); 185305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 185405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 185505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 185605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 185705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 185805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint16_t referenceCount; 185905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt16(offset + 2, &referenceCount)) { 186005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 186105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 186205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 186305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 186405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("refcount: %d", referenceCount); 186505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 186605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < referenceCount * 12) { 186705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 186805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 186905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 187005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t total_duration = 0; 187105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen for (unsigned int i = 0; i < referenceCount; i++) { 187205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t d1, d2, d3; 187305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 187405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &d1) || // size 187505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen !mDataSource->getUInt32(offset + 4, &d2) || // duration 187605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen !mDataSource->getUInt32(offset + 8, &d3)) { // flags 187705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 187805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 187905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 188005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (d1 & 0x80000000) { 188105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGW("sub-sidx boxes not supported yet"); 188205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 188305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool sap = d3 & 0x80000000; 188405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool saptype = d3 >> 28; 188505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!sap || saptype > 2) { 188605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGW("not a stream access point, or unsupported type"); 188705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 188805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen total_duration += d2; 188905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 12; 189005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3); 189105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen SidxEntry se; 189205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen se.mSize = d1 & 0x7fffffff; 189305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen se.mDurationUs = 1000000LL * d2 / timeScale; 189405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSidxEntries.add(se); 189505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 189605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 189705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSidxDuration = total_duration * 1000000 / timeScale; 189805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("duration: %lld", mSidxDuration); 189905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 190005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t metaDuration; 190105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) { 190205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mLastTrack->meta->setInt64(kKeyDuration, mSidxDuration); 190305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 190405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 190505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 190605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 190705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 190805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 1909ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader( 1910c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t data_offset, off64_t data_size) { 1911ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (data_size < 4) { 1912ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_MALFORMED; 1913ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1914ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1915ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint8_t version; 1916ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (mDataSource->readAt(data_offset, &version, 1) < 1) { 1917ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_IO; 1918ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1919ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1920ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber size_t dynSize = (version == 1) ? 36 : 24; 1921ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1922ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint8_t buffer[36 + 60]; 1923ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1924c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (data_size != (off64_t)dynSize + 60) { 1925ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_MALFORMED; 1926ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1927ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1928ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (mDataSource->readAt( 1929ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber data_offset, buffer, data_size) < (ssize_t)data_size) { 1930ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_IO; 1931ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1932ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1933ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint64_t ctime, mtime, duration; 1934ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t id; 1935ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1936ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (version == 1) { 1937ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber ctime = U64_AT(&buffer[4]); 1938ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mtime = U64_AT(&buffer[12]); 1939ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber id = U32_AT(&buffer[20]); 1940ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber duration = U64_AT(&buffer[28]); 194104022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen } else if (version == 0) { 1942ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber ctime = U32_AT(&buffer[4]); 1943ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mtime = U32_AT(&buffer[8]); 1944ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber id = U32_AT(&buffer[12]); 1945ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber duration = U32_AT(&buffer[20]); 194604022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen } else { 194704022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen return ERROR_UNSUPPORTED; 1948ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1949ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1950ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mLastTrack->meta->setInt32(kKeyTrackID, id); 1951ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1952ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber size_t matrixOffset = dynSize + 16; 1953ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a00 = U32_AT(&buffer[matrixOffset]); 1954ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a01 = U32_AT(&buffer[matrixOffset + 4]); 1955ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t dx = U32_AT(&buffer[matrixOffset + 8]); 1956ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a10 = U32_AT(&buffer[matrixOffset + 12]); 1957ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a11 = U32_AT(&buffer[matrixOffset + 16]); 1958ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t dy = U32_AT(&buffer[matrixOffset + 20]); 1959ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1960ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0 1961df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("x' = %.2f * x + %.2f * y + %.2f", 1962ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f); 1963df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("y' = %.2f * x + %.2f * y + %.2f", 1964ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f); 1965ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif 1966ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1967ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint32_t rotationDegrees; 1968ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1969ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber static const int32_t kFixedOne = 0x10000; 1970ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) { 1971ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber // Identity, no rotation 1972ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 0; 1973ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) { 1974ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 90; 1975ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) { 1976ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 270; 1977ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) { 1978ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 180; 1979ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else { 19805ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("We only support 0,90,180,270 degree rotation matrices"); 1981ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 0; 1982ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1983ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1984ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (rotationDegrees != 0) { 1985ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees); 1986ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1987ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1988b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong // Handle presentation display size, which could be different 1989b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong // from the image size indicated by kKeyWidth and kKeyHeight. 1990ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint32_t width = U32_AT(&buffer[dynSize + 52]); 1991ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint32_t height = U32_AT(&buffer[dynSize + 56]); 1992b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16); 1993b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16); 1994ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1995ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return OK; 1996ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber} 1997ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1998c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) { 199972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (size < 4) { 200072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_MALFORMED; 200172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 200272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 200372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint8_t *buffer = new uint8_t[size + 1]; 200472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 200572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber offset, buffer, size) != (ssize_t)size) { 200672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber delete[] buffer; 200772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer = NULL; 200872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 200972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 201072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 201172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 201272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint32_t flags = U32_AT(buffer); 201372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 201472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint32_t metadataKey = 0; 20155d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen char chunk[5]; 20165d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen MakeFourCCString(mPath[4], chunk); 20175d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen ALOGV("meta: %s @ %lld", chunk, offset); 201872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber switch (mPath[4]) { 201972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'a', 'l', 'b'): 202072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 202172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyAlbum; 202272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 202372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 202472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'A', 'R', 'T'): 202572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 202672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyArtist; 202772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 202872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 202966ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen case FOURCC('a', 'A', 'R', 'T'): 203066ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen { 203166ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen metadataKey = kKeyAlbumArtist; 203266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen break; 203366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen } 203472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'd', 'a', 'y'): 203572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 203672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyYear; 203772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 203872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 203972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'n', 'a', 'm'): 204072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 204172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyTitle; 204272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 204372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 204472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'w', 'r', 't'): 204572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 204672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyWriter; 204772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 204872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 204972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('c', 'o', 'v', 'r'): 205072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 205172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyAlbumArt; 205272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 205372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 205472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('g', 'n', 'r', 'e'): 205572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 205672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyGenre; 205772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 205872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 205926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen case FOURCC(0xa9, 'g', 'e', 'n'): 206026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen { 206126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen metadataKey = kKeyGenre; 206226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen break; 206326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 206411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen case FOURCC('c', 'p', 'i', 'l'): 206511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { 206611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen if (size == 9 && flags == 21) { 206711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen char tmp[16]; 206811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen sprintf(tmp, "%d", 206911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen (int)buffer[size - 1]); 207011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen 207111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen mFileMetaData->setCString(kKeyCompilation, tmp); 207211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen } 207311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen break; 207411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen } 207572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('t', 'r', 'k', 'n'): 207672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 207772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (size == 16 && flags == 0) { 207872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char tmp[16]; 2079afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pTrack = (uint16_t*)&buffer[10]; 2080afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pTotalTracks = (uint16_t*)&buffer[12]; 2081afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks)); 208272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 208372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyCDTrackNumber, tmp); 208472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 208572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 208672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 208726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen case FOURCC('d', 'i', 's', 'k'): 208826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen { 2089afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik if ((size == 14 || size == 16) && flags == 0) { 209026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen char tmp[16]; 2091afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pDisc = (uint16_t*)&buffer[10]; 2092afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pTotalDiscs = (uint16_t*)&buffer[12]; 2093afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs)); 209426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 209526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen mFileMetaData->setCString(kKeyDiscNumber, tmp); 209626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 209726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen break; 209826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 20995d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('-', '-', '-', '-'): 21005d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen { 21015d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen buffer[size] = '\0'; 21025d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen switch (mPath[5]) { 21035d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('m', 'e', 'a', 'n'): 21045d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentMean.setTo((const char *)buffer + 4); 21055d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 21065d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('n', 'a', 'm', 'e'): 21075d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentName.setTo((const char *)buffer + 4); 21085d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 21095d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('d', 'a', 't', 'a'): 21105d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentData.setTo((const char *)buffer + 8); 21115d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 21125d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 21138c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman 21148c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // Once we have a set of mean/name/data info, go ahead and process 21158c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // it to see if its something we are interested in. Whether or not 21168c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // were are interested in the specific tag, make sure to clear out 21178c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // the set so we can be ready to process another tuple should one 21188c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // show up later in the file. 21198c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman if ((mLastCommentMean.length() != 0) && 21208c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman (mLastCommentName.length() != 0) && 21218c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman (mLastCommentData.length() != 0)) { 21228c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman 21238c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman if (mLastCommentMean == "com.apple.iTunes" 21248c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman && mLastCommentName == "iTunSMPB") { 21258c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman int32_t delay, padding; 21268c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman if (sscanf(mLastCommentData, 21278c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman " %*x %x %x %*x", &delay, &padding) == 2) { 21288c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman mLastTrack->meta->setInt32(kKeyEncoderDelay, delay); 21298c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman mLastTrack->meta->setInt32(kKeyEncoderPadding, padding); 21308c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman } 21315d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 21328c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman 21335d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentMean.clear(); 21345d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentName.clear(); 21355d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentData.clear(); 21365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 21375d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 21385d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 213926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 214072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber default: 214172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 214272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 214372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 214472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (size >= 8 && metadataKey) { 214572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (metadataKey == kKeyAlbumArt) { 214672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setData( 214772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber kKeyAlbumArt, MetaData::TYPE_NONE, 214872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer + 8, size - 8); 214972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else if (metadataKey == kKeyGenre) { 215072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (flags == 0) { 215126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // uint8_t genre code, iTunes genre codes are 215226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // the standard id3 codes, except they start 215326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // at 1 instead of 0 (e.g. Pop is 14, not 13) 215426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // We use standard id3 numbering, so subtract 1. 215526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen int genrecode = (int)buffer[size - 1]; 215626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen genrecode--; 215726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen if (genrecode < 0) { 215826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen genrecode = 255; // reserved for 'unknown genre' 215926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 216072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char genre[10]; 216126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen sprintf(genre, "%d", genrecode); 216272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 216372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(metadataKey, genre); 216426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } else if (flags == 1) { 216526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // custom genre string 216626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen buffer[size] = '\0'; 216726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 216826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen mFileMetaData->setCString( 216926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen metadataKey, (const char *)buffer + 8); 217072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 217172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 217272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer[size] = '\0'; 217372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 217472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString( 217572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey, (const char *)buffer + 8); 217672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 217772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 217872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 217972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber delete[] buffer; 218072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer = NULL; 218172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 218272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return OK; 218372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 218472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 2185693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) { 218620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 218720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 2188693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return NULL; 218920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 219020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 219120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 219220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (index > 0) { 219320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (track == NULL) { 2194693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return NULL; 219520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 219620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 219720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 219820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber --index; 219920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 220020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2201371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber if (track == NULL) { 2202371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber return NULL; 2203371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber } 2204371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber 2205ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("getTrack called, pssh: %d", mPssh.size()); 2206ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2207693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return new MPEG4Source( 220805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen track->meta, mDataSource, track->timescale, track->sampleTable, 220905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSidxEntries, mMoofOffset); 221020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 221120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2212bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static 2213bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) { 2214bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber const char *mime; 2215bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 2216bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 2217bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber uint32_t type; 2218bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber const void *data; 2219bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber size_t size; 2220bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 2221bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!track->meta->findData(kKeyAVCC, &type, &data, &size) 2222bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || type != kTypeAVCC) { 2223bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 2224bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 2225bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 2226bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 2227bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!track->meta->findData(kKeyESDS, &type, &data, &size) 2228bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || type != kTypeESDS) { 2229bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 2230bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 2231bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 2232bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 2233169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber if (!track->sampleTable->isValid()) { 2234169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber // Make sure we have all the metadata we need. 2235169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber return ERROR_MALFORMED; 2236169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber } 2237169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber 2238bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return OK; 2239bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber} 2240bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 2241ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( 2242ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber const void *esds_data, size_t esds_size) { 2243ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber ESDS esds(esds_data, esds_size); 224481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 224581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint8_t objectTypeIndication; 224681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) { 224781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber return ERROR_MALFORMED; 224881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber } 224981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 225081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber if (objectTypeIndication == 0xe1) { 225181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber // This isn't MPEG4 audio at all, it's QCELP 14k... 225281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP); 225381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber return OK; 225481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber } 225581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 2256633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong if (objectTypeIndication == 0x6b) { 2257633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong // The media subtype is MP3 audio 2258633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong // Our software MP3 audio decoder may not be able to handle 2259633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED 226029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("MP3 track in MP4/3GPP file is not supported"); 2261633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong return ERROR_UNSUPPORTED; 2262633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong } 2263633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong 2264ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber const uint8_t *csd; 2265ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber size_t csd_size; 2266ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (esds.getCodecSpecificInfo( 2267ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber (const void **)&csd, &csd_size) != OK) { 2268ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 2269ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2270ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2271ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0 2272ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber printf("ESD of size %d\n", csd_size); 2273ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber hexdump(csd, csd_size); 2274ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif 2275ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2276a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber if (csd_size == 0) { 2277a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber // There's no further information, i.e. no codec specific data 2278a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber // Let's assume that the information provided in the mpeg4 headers 2279a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber // is accurate and hope for the best. 2280a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber 2281a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber return OK; 2282a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber } 2283a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber 2284ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (csd_size < 2) { 2285ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 2286ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2287ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2288aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke ABitReader br(csd, csd_size); 2289aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke uint32_t objectType = br.getBits(5); 2290ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2291aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke if (objectType == 31) { // AAC-ELD => additional 6 bits 2292aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke objectType = 32 + br.getBits(6); 2293ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2294ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2295aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke uint32_t freqIndex = br.getBits(4); 2296aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke 2297ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t sampleRate = 0; 2298ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t numChannels = 0; 2299ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (freqIndex == 15) { 2300ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (csd_size < 5) { 2301ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 2302ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2303aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke sampleRate = br.getBits(24); 2304aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke numChannels = br.getBits(4); 2305ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } else { 2306595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen numChannels = br.getBits(4); 2307595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen if (objectType == 5) { 2308595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen // SBR specific config per 14496-3 table 1.13 2309595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen freqIndex = br.getBits(4); 2310595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen if (freqIndex == 15) { 2311595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen if (csd_size < 8) { 2312595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen return ERROR_MALFORMED; 2313595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen } 2314595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen sampleRate = br.getBits(24); 2315595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen } 2316ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2317ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2318595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen if (sampleRate == 0) { 2319595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen static uint32_t kSamplingRate[] = { 2320595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 2321595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen 16000, 12000, 11025, 8000, 7350 2322595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen }; 2323595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen 2324595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen if (freqIndex == 13 || freqIndex == 14) { 2325595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen return ERROR_MALFORMED; 2326595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen } 2327595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen 2328595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen sampleRate = kSamplingRate[freqIndex]; 2329595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen } 2330ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2331ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2332ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (numChannels == 0) { 2333ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_UNSUPPORTED; 2334ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2335ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2336ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t prevSampleRate; 2337ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate)); 2338ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2339ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (prevSampleRate != sampleRate) { 23403856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("mpeg4 audio sample rate different from previous setting. " 2341ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber "was: %d, now: %d", prevSampleRate, sampleRate); 2342ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2343ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2344ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sampleRate); 2345ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2346ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t prevChannelCount; 2347ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount)); 2348ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2349ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (prevChannelCount != numChannels) { 23503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("mpeg4 audio channel count different from previous setting. " 2351ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber "was: %d, now: %d", prevChannelCount, numChannels); 2352ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2353ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2354ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, numChannels); 2355ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2356ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return OK; 2357ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber} 2358ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 235920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 236020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 236120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source( 236220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const sp<MetaData> &format, 2363693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &dataSource, 236448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int32_t timeScale, 236505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const sp<SampleTable> &sampleTable, 236605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<SidxEntry> &sidx, 236705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t firstMoofOffset) 236820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFormat(format), 236920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDataSource(dataSource), 237048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mTimescale(timeScale), 237120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSampleTable(sampleTable), 237220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCurrentSampleIndex(0), 237305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentFragmentIndex(0), 237405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSegments(sidx), 237505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mFirstMoofOffset(firstMoofOffset), 237605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentMoofOffset(firstMoofOffset), 237705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentTime(0), 2378ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoAllocSize(0), 2379ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoSizes(NULL), 2380ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsetsAllocSize(0), 2381ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets(NULL), 238220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mIsAVC(false), 23836064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mNALLengthSize(0), 238420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted(false), 238520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup(NULL), 238620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer(NULL), 2387dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments(false), 23880024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer(NULL) { 2389ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2390ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mFormat->findInt32(kKeyCryptoMode, &mCryptoMode); 239148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mDefaultIVSize = 0; 2392ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize); 2393ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t keytype; 2394ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen const void *key; 2395ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen size_t keysize; 2396ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) { 2397ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen CHECK(keysize <= 16); 2398ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(mCryptoKey, 0, 16); 2399ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memcpy(mCryptoKey, key, keysize); 2400ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2401ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 240220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 240320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mFormat->findCString(kKeyMIMEType, &mime); 2404dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(success); 240520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 240618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 24076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 24086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber if (mIsAVC) { 24096064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber uint32_t type; 24106064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber const void *data; 24116064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t size; 24126064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(format->findData(kKeyAVCC, &type, &data, &size)); 24136064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 24146064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber const uint8_t *ptr = (const uint8_t *)data; 24156064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 24166064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(size >= 7); 2417ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 24186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 24196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // The number of bytes used to encode the length of a NAL unit. 24206064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mNALLengthSize = 1 + (ptr[4] & 3); 24216064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber } 242205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 242305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(format->findInt32(kKeyTrackID, &mTrackId)); 242405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 242505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mFirstMoofOffset != 0) { 242605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t offset = mFirstMoofOffset; 242705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(&offset); 242805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 242920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 243020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 243120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() { 243220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mStarted) { 243320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 243420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 2435ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen free(mCurrentSampleInfoSizes); 2436ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen free(mCurrentSampleInfoOffsets); 243720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 243820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 243920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) { 24407b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 24417b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 2442dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(!mStarted); 244320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 244420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t val; 2445dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (params && params->findInt32(kKeyWantsNALFragments, &val) 244620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && val != 0) { 2447dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments = true; 244820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 2449dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments = false; 245020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 245120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 245220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup = new MediaBufferGroup; 245320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2454738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber int32_t max_size; 2455738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size)); 245620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2457738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber mGroup->add_buffer(new MediaBuffer(max_size)); 24580024245e134467d120b40099da16c467dc365e76Andreas Huber 24590024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer = new uint8_t[max_size]; 246020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 246120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = true; 246220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 246320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 246420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 246520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 246620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() { 24677b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 24687b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 2469dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(mStarted); 247020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 247120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mBuffer != NULL) { 247220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 247320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 247420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 247520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24760024245e134467d120b40099da16c467dc365e76Andreas Huber delete[] mSrcBuffer; 24770024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer = NULL; 24780024245e134467d120b40099da16c467dc365e76Andreas Huber 247920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete mGroup; 248020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup = NULL; 248120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 248220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = false; 248320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCurrentSampleIndex = 0; 248420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 248520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 248620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 248720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 248805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) { 248905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t hdr[2]; 249005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mDataSource->readAt(*offset, hdr, 8) < 8) { 249105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 249205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 249305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t chunk_size = ntohl(hdr[0]); 249405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t chunk_type = ntohl(hdr[1]); 249505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t data_offset = *offset + 8; 249605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 249705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_size == 1) { 249805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { 249905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 250005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 250105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen chunk_size = ntoh64(chunk_size); 250205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen data_offset += 8; 250305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 250405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_size < 16) { 250505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // The smallest valid chunk is 16 bytes long in this case. 250605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 250705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 250805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (chunk_size < 8) { 250905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // The smallest valid chunk is 8 bytes long. 251005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 251105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 251205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 251305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen char chunk[5]; 251405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MakeFourCCString(chunk_type, chunk); 251505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset); 251605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 251705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t chunk_data_size = *offset + chunk_size - data_offset; 251805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 251905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen switch(chunk_type) { 252005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 252105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('t', 'r', 'a', 'f'): 252205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('m', 'o', 'o', 'f'): { 252305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t stop_offset = *offset + chunk_size; 252405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset = data_offset; 252505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen while (*offset < stop_offset) { 252605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err = parseChunk(offset); 252705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (err != OK) { 252805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 252905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 253005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 253105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_type == FOURCC('m', 'o', 'o', 'f')) { 2532ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // *offset points to the mdat box following this moof 253305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(offset); // doesn't actually parse it, just updates offset 253405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mNextMoofOffset = *offset; 253505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 253605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 253705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 253805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 253905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('t', 'f', 'h', 'd'): { 254005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err; 254105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) { 254205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 254305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 254405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 254505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 254605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 254705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 254805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('t', 'r', 'u', 'n'): { 254905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err; 255005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mLastParsedTrackId == mTrackId) { 255105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) { 255205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 255305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 255405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 255505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 255605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 255705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 255805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 255905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 2560ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'a', 'i', 'z'): { 2561ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t err; 2562ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) { 2563ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return err; 2564ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2565ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 2566ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 2567ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2568ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'a', 'i', 'o'): { 2569ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t err; 2570ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) { 2571ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return err; 2572ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2573ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 2574ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 2575ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2576ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2577ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('m', 'd', 'a', 't'): { 2578ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // parse DRM info if present 2579ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("MPEG4Source::parseChunk mdat"); 2580ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // if saiz/saoi was previously observed, do something with the sampleinfos 2581ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 2582ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 2583ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2584ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 258505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen default: { 258605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 258705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 258805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 258905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 259005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 259105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 259205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 2593ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size) { 2594ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("parseSampleAuxiliaryInformationSizes"); 2595ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // 14496-12 8.7.12 2596ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t version; 2597ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt( 2598ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset, &version, sizeof(version)) 2599ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen < (ssize_t)sizeof(version)) { 2600ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2601ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2602ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2603ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (version != 0) { 2604ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_UNSUPPORTED; 2605ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2606ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset++; 2607ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2608ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t flags; 2609ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt24(offset, &flags)) { 2610ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2611ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2612ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 3; 2613ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2614ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (flags & 1) { 2615ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t tmp; 2616ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 2617ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 2618ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2619ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentAuxInfoType = tmp; 2620ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2621ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 2622ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 2623ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2624ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentAuxInfoTypeParameter = tmp; 2625ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2626ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2627ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2628ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t defsize; 2629ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(offset, &defsize, 1) != 1) { 2630ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 2631ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2632ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentDefaultSampleInfoSize = defsize; 2633ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset++; 2634ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2635ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t smplcnt; 2636ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &smplcnt)) { 2637ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 2638ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 263948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mCurrentSampleInfoCount = smplcnt; 2640ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2641ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 264248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (mCurrentDefaultSampleInfoSize != 0) { 264348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize); 264448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return OK; 264548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 2646ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (smplcnt > mCurrentSampleInfoAllocSize) { 2647ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt); 2648ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoAllocSize = smplcnt; 2649ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2650ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2651ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt); 2652ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return OK; 2653ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen} 2654ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2655ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size) { 2656ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("parseSampleAuxiliaryInformationOffsets"); 2657ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // 14496-12 8.7.13 2658ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t version; 2659ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) { 2660ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2661ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2662ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset++; 2663ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2664ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t flags; 2665ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt24(offset, &flags)) { 2666ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2667ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2668ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 3; 2669ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2670ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t entrycount; 2671ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &entrycount)) { 2672ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2673ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2674ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2675ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2676ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (entrycount > mCurrentSampleInfoOffsetsAllocSize) { 2677ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8); 2678ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsetsAllocSize = entrycount; 2679ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2680ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsetCount = entrycount; 2681ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2682ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < entrycount; i++) { 2683ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (version == 0) { 2684ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t tmp; 2685ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 2686ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2687ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2688ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets[i] = tmp; 2689ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2690ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } else { 2691ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint64_t tmp; 2692ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt64(offset, &tmp)) { 2693ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2694ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2695ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets[i] = tmp; 2696ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 8; 2697ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2698ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2699ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2700ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // parse clear/encrypted data 2701ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2702ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof 2703ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2704ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen drmoffset += mCurrentMoofOffset; 2705ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int ivlength; 2706ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength)); 270748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 270848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // read CencSampleAuxiliaryDataFormats 2709ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mCurrentSampleInfoCount; i++) { 2710ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen Sample *smpl = &mCurrentSamples.editItemAt(i); 2711ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2712ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(smpl->iv, 0, 16); 2713ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) { 2714ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2715ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2716ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2717ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen drmoffset += ivlength; 2718ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 271948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen int32_t smplinfosize = mCurrentDefaultSampleInfoSize; 272048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (smplinfosize == 0) { 272148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smplinfosize = mCurrentSampleInfoSizes[i]; 2722ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 272348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (smplinfosize > ivlength) { 272448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint16_t numsubsamples; 272548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) { 2726ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2727ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2728ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen drmoffset += 2; 272948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen for (size_t j = 0; j < numsubsamples; j++) { 273048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint16_t numclear; 273148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t numencrypted; 273248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!mDataSource->getUInt16(drmoffset, &numclear)) { 273348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return ERROR_IO; 273448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 273548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen drmoffset += 2; 273648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!mDataSource->getUInt32(drmoffset, &numencrypted)) { 273748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return ERROR_IO; 273848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 273948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen drmoffset += 4; 274048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->clearsizes.add(numclear); 274148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->encryptedsizes.add(numencrypted); 2742ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 274348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } else { 274448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->clearsizes.add(0); 274548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->encryptedsizes.add(smpl->size); 2746ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2747ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2748ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2749ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2750ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return OK; 2751ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen} 2752ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 275305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) { 275405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 275505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 275605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 275705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 275805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 275905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t flags; 2760ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags 276105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 276205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 276305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 276405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & 0xff000000) { 276505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 276605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 276705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 276805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) { 276905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 277005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 277105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 277205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mLastParsedTrackId != mTrackId) { 277305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // this is not the right track, skip it 277405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 277505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 277605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 277705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mFlags = flags; 277805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId; 277905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 278005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 278105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 278205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID); 278305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 278405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) { 278505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 278605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 278705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 278805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 278905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) { 279005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 279105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 279205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 279305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 279405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 279505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 279605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) { 279705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 279805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 279905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 280005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 280105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) { 280205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 280305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 280405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 280505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 280605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 280705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 280805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) { 280905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 281005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 281105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 281205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 281305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) { 281405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 281505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 281605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 281705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 281805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 281905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 282005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) { 282105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 282205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 282305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 282405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 282505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) { 282605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 282705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 282805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 282905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 283005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 283105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 283205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) { 283305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 283405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 283505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 283605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 283705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) { 283805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 283905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 284005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 284105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 284205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 284305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 284405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) { 284505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset; 284605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 284705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 284805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mDataOffset = 0; 284905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 285005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 285105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 285205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) { 285305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 285405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Extractor::parseTrackFragmentRun"); 285505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 285605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 285705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 285805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 285905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen enum { 286005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDataOffsetPresent = 0x01, 286105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kFirstSampleFlagsPresent = 0x04, 286205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleDurationPresent = 0x100, 286305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleSizePresent = 0x200, 286405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleFlagsPresent = 0x400, 286505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleCompositionTimeOffsetPresent = 0x800, 286605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 286705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 286805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t flags; 286905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &flags)) { 287005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 287105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 287205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("fragment run flags: %08x", flags); 287305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 287405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & 0xff000000) { 287505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 287605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 287705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 287805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) { 287905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // These two shall not be used together. 288005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 288105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 288205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 288305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleCount; 288405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, &sampleCount)) { 288505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 288605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 288705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 288805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 288905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 289005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset; 289105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 289205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t firstSampleFlags = 0; 289305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 289405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kDataOffsetPresent) { 289505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 289605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 289705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 289805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 289905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t dataOffsetDelta; 290005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) { 290105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 290205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 290305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 290405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta; 290505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 290605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 290705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 290805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 290905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 291005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kFirstSampleFlagsPresent) { 291105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 291205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 291305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 291405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 291505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &firstSampleFlags)) { 291605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 291705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 291805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 291905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 292005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 292105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 292205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0, 292305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleCtsOffset = 0; 292405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 292505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t bytesPerSample = 0; 292605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleDurationPresent) { 292705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 292805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (mTrackFragmentHeaderInfo.mFlags 292905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) { 293005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration; 293105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 293205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration; 293305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 293405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 293505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleSizePresent) { 293605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 293705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (mTrackFragmentHeaderInfo.mFlags 293805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) { 293905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize; 294005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 294105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize; 294205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 294305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 294405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleFlagsPresent) { 294505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 294605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (mTrackFragmentHeaderInfo.mFlags 294705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) { 294805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags; 294905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 295005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags; 295105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 295205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 295305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleCompositionTimeOffsetPresent) { 295405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 295505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 295605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleCtsOffset = 0; 295705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 295805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 295905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < sampleCount * bytesPerSample) { 296005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 296105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 296205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 296305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Sample tmp; 296405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen for (uint32_t i = 0; i < sampleCount; ++i) { 296505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleDurationPresent) { 296605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleDuration)) { 296705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 296805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 296905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 297005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 297105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 297205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleSizePresent) { 297305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleSize)) { 297405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 297505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 297605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 297705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 297805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 297905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleFlagsPresent) { 298005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleFlags)) { 298105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 298205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 298305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 298405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 298505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 298605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleCompositionTimeOffsetPresent) { 298705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) { 298805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 298905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 299005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 299105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 299205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 2993ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("adding sample %d at offset 0x%08llx, size %u, duration %u, " 2994ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen " flags 0x%08x", i + 1, 299505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dataOffset, sampleSize, sampleDuration, 299605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (flags & kFirstSampleFlagsPresent) && i == 0 299705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ? firstSampleFlags : sampleFlags); 299805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen tmp.offset = dataOffset; 299905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen tmp.size = sampleSize; 300005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen tmp.duration = sampleDuration; 300105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSamples.add(tmp); 300205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 300305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dataOffset += sampleSize; 300405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 300505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 300605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mDataOffset = dataOffset; 300705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 300805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 300905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 301005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 301120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() { 30127b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 30137b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 301420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return mFormat; 301520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 301620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30176064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const { 30186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber switch (mNALLengthSize) { 30196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 1: 30206064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return *data; 30216064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 2: 30226064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return U16_AT(data); 30236064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 3: 30246064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return ((size_t)data[0] << 16) | U16_AT(&data[1]); 30256064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 4: 30266064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return U32_AT(data); 30276064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber } 30286064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 30296064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // This cannot happen, mNALLengthSize springs to life by adding 1 to 30306064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // a 2-bit integer. 30316064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(!"Should not be here."); 30326064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 30336064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return 0; 30346064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber} 30356064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 303620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read( 303720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer **out, const ReadOptions *options) { 30387b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 30397b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 3040dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(mStarted); 304120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 304205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mFirstMoofOffset > 0) { 304305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return fragmentedRead(out, options); 304405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 304505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 304620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *out = NULL; 304720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3048abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber int64_t targetSampleTimeUs = -1; 3049abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 305020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t seekTimeUs; 3051abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 3052abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 3053abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t findFlags = 0; 3054abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber switch (mode) { 3055abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_PREVIOUS_SYNC: 3056abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagBefore; 3057abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3058abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_NEXT_SYNC: 3059abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagAfter; 3060abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3061abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_CLOSEST_SYNC: 3062abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_CLOSEST: 3063abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagClosest; 3064abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3065abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber default: 3066abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber CHECK(!"Should not be here."); 3067abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3068abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3069abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 307020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t sampleIndex; 3071abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber status_t err = mSampleTable->findSampleAtTime( 307220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber seekTimeUs * mTimescale / 1000000, 3073abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber &sampleIndex, findFlags); 3074abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3075abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 3076abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber // We found the closest sample already, now we want the sync 3077abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber // sample preceding it (or the sample itself of course), even 3078abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber // if the subsequent sync sample is closer. 3079abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagBefore; 3080abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3081abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3082abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t syncSampleIndex; 3083abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (err == OK) { 3084abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber err = mSampleTable->findSyncSampleNear( 3085abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber sampleIndex, &syncSampleIndex, findFlags); 3086abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 308720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3088788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber uint32_t sampleTime; 3089788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber if (err == OK) { 3090788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber err = mSampleTable->getMetaDataForSample( 3091788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber sampleIndex, NULL, NULL, &sampleTime); 3092788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber } 3093788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber 309420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 30955295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber if (err == ERROR_OUT_OF_RANGE) { 30965295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // An attempt to seek past the end of the stream would 30975295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // normally cause this ERROR_OUT_OF_RANGE error. Propagating 30985295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // this all the way to the MediaPlayer would cause abnormal 30995295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // termination. Legacy behaviour appears to be to behave as if 31005295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // we had seeked to the end of stream, ending normally. 31015295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber err = ERROR_END_OF_STREAM; 31025295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber } 310305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("end of stream"); 310420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 310520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 310620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3107abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 3108abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale; 3109abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3110abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3111abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0 3112abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t syncSampleTime; 3113abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber CHECK_EQ(OK, mSampleTable->getMetaDataForSample( 3114abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber syncSampleIndex, NULL, NULL, &syncSampleTime)); 3115abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3116df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("seek to time %lld us => sample at time %lld us, " 3117abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber "sync sample at time %lld us", 3118abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber seekTimeUs, 3119abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber sampleTime * 1000000ll / mTimescale, 3120abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber syncSampleTime * 1000000ll / mTimescale); 3121abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif 3122abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3123abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mCurrentSampleIndex = syncSampleIndex; 312420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mBuffer != NULL) { 312520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 312620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 312720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 312820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 312920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // fall through 313020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 313120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3132c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset; 31330024245e134467d120b40099da16c467dc365e76Andreas Huber size_t size; 31344678a6dc5f09008481524949a9667af5a6190374Andreas Huber uint32_t cts; 31358bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber bool isSyncSample; 3136dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber bool newBuffer = false; 3137dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (mBuffer == NULL) { 3138dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber newBuffer = true; 313920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3140c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber status_t err = 3141c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber mSampleTable->getMetaDataForSample( 31424678a6dc5f09008481524949a9667af5a6190374Andreas Huber mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample); 314320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3144dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (err != OK) { 3145dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return err; 3146dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3147dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3148dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber err = mGroup->acquire_buffer(&mBuffer); 3149c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 3150dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (err != OK) { 3151ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber CHECK(mBuffer == NULL); 3152dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return err; 3153dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 31540024245e134467d120b40099da16c467dc365e76Andreas Huber } 315520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3156dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (!mIsAVC || mWantsNALFragments) { 3157dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (newBuffer) { 3158dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber ssize_t num_bytes_read = 315934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 3160dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3161dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (num_bytes_read < (ssize_t)size) { 3162dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->release(); 3163dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 3164dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3165dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return ERROR_IO; 3166dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3167dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 31687b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(mBuffer != NULL); 3169dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->set_range(0, size); 3170dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->meta_data()->clear(); 317148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mBuffer->meta_data()->setInt64( 31724678a6dc5f09008481524949a9667af5a6190374Andreas Huber kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 3173abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3174abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (targetSampleTimeUs >= 0) { 3175abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mBuffer->meta_data()->setInt64( 3176abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber kKeyTargetTime, targetSampleTimeUs); 3177abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3178abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 31798bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber if (isSyncSample) { 31808bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 31818bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 31828bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 3183dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber ++mCurrentSampleIndex; 3184dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3185dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3186dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (!mIsAVC) { 3187dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber *out = mBuffer; 3188dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 3189dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3190dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return OK; 3191dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3192dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3193dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // Each NAL unit is split up into its constituent fragments and 3194dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // each one of them returned in its own buffer. 3195dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 31966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(mBuffer->range_length() >= mNALLengthSize); 3197dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3198dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber const uint8_t *src = 3199dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 3200dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 32016064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t nal_size = parseNALSize(src); 3202e8a084958c27327b0aca749f69095605d2a21309Andreas Huber if (mBuffer->range_length() < mNALLengthSize + nal_size) { 320329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("incomplete NAL unit."); 3204e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 3205e8a084958c27327b0aca749f69095605d2a21309Andreas Huber mBuffer->release(); 3206e8a084958c27327b0aca749f69095605d2a21309Andreas Huber mBuffer = NULL; 3207e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 3208e8a084958c27327b0aca749f69095605d2a21309Andreas Huber return ERROR_MALFORMED; 3209e8a084958c27327b0aca749f69095605d2a21309Andreas Huber } 3210dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3211dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber MediaBuffer *clone = mBuffer->clone(); 32127b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(clone != NULL); 32136064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 3214dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 32157b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(mBuffer != NULL); 3216dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->set_range( 32176064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mBuffer->range_offset() + mNALLengthSize + nal_size, 32186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mBuffer->range_length() - mNALLengthSize - nal_size); 3219dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3220dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (mBuffer->range_length() == 0) { 3221dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->release(); 3222dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 3223dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3224dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3225dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber *out = clone; 3226dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3227dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return OK; 3228dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } else { 3229dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // Whole NAL units are returned but each fragment is prefixed by 3230dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // the start code (0x00 00 00 01). 3231dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang ssize_t num_bytes_read = 0; 3232dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t drm = 0; 3233dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0); 3234dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (usesDRM) { 3235dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang num_bytes_read = 3236dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size); 3237dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else { 3238dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size); 3239dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 324020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 324120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (num_bytes_read < (ssize_t)size) { 324220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 324320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 324420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3245dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return ERROR_IO; 324620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 324720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3248dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (usesDRM) { 3249dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK(mBuffer != NULL); 3250dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer->set_range(0, size); 32516064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 3252dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else { 3253dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t *dstData = (uint8_t *)mBuffer->data(); 3254dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size_t srcOffset = 0; 3255dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size_t dstOffset = 0; 3256e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 3257dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (srcOffset < size) { 325834fe252c89e33572d01fea981b58d7b115e76164James Dong bool isMalFormed = (srcOffset + mNALLengthSize > size); 325934fe252c89e33572d01fea981b58d7b115e76164James Dong size_t nalLength = 0; 326034fe252c89e33572d01fea981b58d7b115e76164James Dong if (!isMalFormed) { 326134fe252c89e33572d01fea981b58d7b115e76164James Dong nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 326234fe252c89e33572d01fea981b58d7b115e76164James Dong srcOffset += mNALLengthSize; 326334fe252c89e33572d01fea981b58d7b115e76164James Dong isMalFormed = srcOffset + nalLength > size; 326434fe252c89e33572d01fea981b58d7b115e76164James Dong } 3265e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 326634fe252c89e33572d01fea981b58d7b115e76164James Dong if (isMalFormed) { 326729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Video is malformed"); 3268dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer->release(); 3269dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer = NULL; 3270dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 3271dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 3272dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 3273dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (nalLength == 0) { 3274dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang continue; 3275dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 3276dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3277dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK(dstOffset + 4 <= mBuffer->size()); 3278dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3279dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 0; 3280dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 0; 3281dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 0; 3282dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 1; 3283dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 3284dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang srcOffset += nalLength; 3285dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstOffset += nalLength; 3286dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 3287dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK_EQ(srcOffset, size); 3288dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK(mBuffer != NULL); 3289dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer->set_range(0, dstOffset); 3290dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3291dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 329220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->meta_data()->clear(); 329348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mBuffer->meta_data()->setInt64( 32944678a6dc5f09008481524949a9667af5a6190374Andreas Huber kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 3295abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3296abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (targetSampleTimeUs >= 0) { 3297abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mBuffer->meta_data()->setInt64( 3298abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber kKeyTargetTime, targetSampleTimeUs); 3299abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3300abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 33018bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber if (isSyncSample) { 33028bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 33038bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 33048bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 330520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++mCurrentSampleIndex; 330620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 330720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *out = mBuffer; 330820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 330920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 331020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 331120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 331220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 331320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 331405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead( 331505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MediaBuffer **out, const ReadOptions *options) { 331605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 331705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Source::fragmentedRead"); 331805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 331905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mStarted); 332005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 332105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = NULL; 332205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 332305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t targetSampleTimeUs = -1; 332405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 332505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t seekTimeUs; 332605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ReadOptions::SeekMode mode; 332705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (options && options->getSeekTo(&seekTimeUs, &mode)) { 332805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 332905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int numSidxEntries = mSegments.size(); 333005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (numSidxEntries != 0) { 333105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t totalTime = 0; 333205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t totalOffset = mFirstMoofOffset; 333305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen for (int i = 0; i < numSidxEntries; i++) { 333405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const SidxEntry *se = &mSegments[i]; 333505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (totalTime + se->mDurationUs > seekTimeUs) { 333605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // The requested time is somewhere in this segment 333705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((mode == ReadOptions::SEEK_NEXT_SYNC) || 333805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (mode == ReadOptions::SEEK_CLOSEST_SYNC && 333905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) { 334005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // requested next sync, or closest sync and it was closer to the end of 334105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // this segment 334205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalTime += se->mDurationUs; 334305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalOffset += se->mSize; 334405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 334505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 334605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 334705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalTime += se->mDurationUs; 334805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalOffset += se->mSize; 334905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 335005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentMoofOffset = totalOffset; 335105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSamples.clear(); 335205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSampleIndex = 0; 335305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(&totalOffset); 335405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentTime = totalTime * mTimescale / 1000000ll; 335505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 335605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 335705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer != NULL) { 335805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 335905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 336005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 336105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 336205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // fall through 336305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 336405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 336505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t offset = 0; 336605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t size; 336705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t cts = 0; 336805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool isSyncSample = false; 336905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool newBuffer = false; 337005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer == NULL) { 337105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen newBuffer = true; 337205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 337305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mCurrentSampleIndex >= mCurrentSamples.size()) { 337405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // move to next fragment 337505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Sample lastSample = mCurrentSamples[mCurrentSamples.size() - 1]; 337605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size; 337705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentMoofOffset = nextMoof; 337805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSamples.clear(); 337905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSampleIndex = 0; 338005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(&nextMoof); 338105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mCurrentSampleIndex >= mCurrentSamples.size()) { 338205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_END_OF_STREAM; 338305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 338405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 338505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 338605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex]; 338705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset = smpl->offset; 338805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size = smpl->size; 338905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen cts = mCurrentTime; 339005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentTime += smpl->duration; 339105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen isSyncSample = (mCurrentSampleIndex == 0); // XXX 339205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 339305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err = mGroup->acquire_buffer(&mBuffer); 339405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 339505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (err != OK) { 339605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer == NULL); 339705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("acquire_buffer returned %d", err); 339805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 339905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 340005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 340105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 340248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex]; 340348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen const sp<MetaData> bufmeta = mBuffer->meta_data(); 340448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->clear(); 340548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (smpl->encryptedsizes.size()) { 340648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // store clear/encrypted lengths in metadata 340748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyPlainSizes, 0, 340848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->clearsizes.array(), smpl->clearsizes.size() * 4); 340948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyEncryptedSizes, 0, 341048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4); 341148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size? 341248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize); 341348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setInt32(kKeyCryptoMode, mCryptoMode); 341448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16); 341548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 341648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mIsAVC || mWantsNALFragments) { 341805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (newBuffer) { 341905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ssize_t num_bytes_read = 342005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 342105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 342205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (num_bytes_read < (ssize_t)size) { 342305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 342405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 342505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 342605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("i/o error"); 342705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 342805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 342905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 343005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 343105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range(0, size); 343205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 343305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 343405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 343505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (targetSampleTimeUs >= 0) { 343605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 343705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTargetTime, targetSampleTimeUs); 343805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 343905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 344005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (isSyncSample) { 344105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 344205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 344305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 344405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ++mCurrentSampleIndex; 344505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 344605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 344705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mIsAVC) { 344805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = mBuffer; 344905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 345005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 345105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 345205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 345305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 345405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // Each NAL unit is split up into its constituent fragments and 345505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // each one of them returned in its own buffer. 345605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 345705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer->range_length() >= mNALLengthSize); 345805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 345905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const uint8_t *src = 346005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 346105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 346205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t nal_size = parseNALSize(src); 346305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer->range_length() < mNALLengthSize + nal_size) { 346405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGE("incomplete NAL unit."); 346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 346705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 347105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 347205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MediaBuffer *clone = mBuffer->clone(); 347305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(clone != NULL); 347405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 347505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 347605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 347705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range( 347805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->range_offset() + mNALLengthSize + nal_size, 347905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->range_length() - mNALLengthSize - nal_size); 348005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 348105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer->range_length() == 0) { 348205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 348305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 348405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 348505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 348605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = clone; 348705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 348805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 348905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 349005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("whole NAL"); 349105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // Whole NAL units are returned but each fragment is prefixed by 349205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // the start code (0x00 00 00 01). 349305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ssize_t num_bytes_read = 0; 349405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t drm = 0; 349505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0); 349605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (usesDRM) { 349705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen num_bytes_read = 349805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size); 349905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 350005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size); 350105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 350205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 350305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (num_bytes_read < (ssize_t)size) { 350405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 350505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 350605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 350705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("i/o error"); 350805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 350905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 351005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 351105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (usesDRM) { 351205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 351305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range(0, size); 351405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 351505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 351605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint8_t *dstData = (uint8_t *)mBuffer->data(); 351705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t srcOffset = 0; 351805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t dstOffset = 0; 351905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 352005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen while (srcOffset < size) { 352105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool isMalFormed = (srcOffset + mNALLengthSize > size); 352205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t nalLength = 0; 352305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!isMalFormed) { 352405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 352505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen srcOffset += mNALLengthSize; 352605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen isMalFormed = srcOffset + nalLength > size; 352705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 352805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 352905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (isMalFormed) { 353005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGE("Video is malformed"); 353105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 353205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 353305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 353405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 353505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 353605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (nalLength == 0) { 353705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen continue; 353805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 353905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 354005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(dstOffset + 4 <= mBuffer->size()); 354105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 354205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 0; 354305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 0; 354405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 0; 354505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 1; 354605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 354705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen srcOffset += nalLength; 354805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstOffset += nalLength; 354905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 355005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK_EQ(srcOffset, size); 355105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 355205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range(0, dstOffset); 355305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 355405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 355505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 355605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 355705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 355805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (targetSampleTimeUs >= 0) { 355905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 356005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTargetTime, targetSampleTimeUs); 356105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 356205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 356305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (isSyncSample) { 356405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 356505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 356605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 356705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ++mCurrentSampleIndex; 356805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 356905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = mBuffer; 357005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 357105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 357205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 357305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 357405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 357505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 3576bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix( 3577bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber const char *mimePrefix) { 3578bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber for (Track *track = mFirstTrack; track != NULL; track = track->next) { 3579bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber const char *mime; 3580bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber if (track->meta != NULL 3581bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber && track->meta->findCString(kKeyMIMEType, &mime) 3582bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) { 3583bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return track; 3584bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber } 3585bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber } 3586bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber 3587bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return NULL; 3588bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber} 3589bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber 35901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4( 3591693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 359220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t header[8]; 359320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 359434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber ssize_t n = source->readAt(4, header, sizeof(header)); 359520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (n < (ssize_t)sizeof(header)) { 359620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return false; 359720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 359820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 359920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8) 3600b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8) 3601b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8) 36020dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8) 3603ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8) 3604983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) { 360518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 36065a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber *confidence = 0.4; 360720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 360820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return true; 360920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 361020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 361120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return false; 361220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 361320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) { 36151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber static const uint32_t kCompatibleBrands[] = { 36161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('i', 's', 'o', 'm'), 36171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('i', 's', 'o', '2'), 36181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('a', 'v', 'c', '1'), 36191b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('3', 'g', 'p', '4'), 36201b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('m', 'p', '4', '1'), 36211b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('m', 'p', '4', '2'), 36224cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong 36234cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong // Won't promise that the following file types can be played. 36244cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong // Just give these file types a chance. 36254cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong FOURCC('q', 't', ' ', ' '), // Apple's QuickTime 36264cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong FOURCC('M', 'S', 'N', 'V'), // Sony's PSP 362758fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber 362858fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber FOURCC('3', 'g', '2', 'a'), // 3GPP2 362958fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber FOURCC('3', 'g', '2', 'b'), 36301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber }; 36311b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 36321b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber for (size_t i = 0; 36331b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]); 36341b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber ++i) { 36351b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (kCompatibleBrands[i] == fourcc) { 36361b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 36371b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 36381b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 36391b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 36401b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 36411b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 36421b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 36431b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable 36441b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present. 3645a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends 3646a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of 3647a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata. 36481b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4( 3649a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 3650a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber sp<AMessage> *meta) { 3651a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // We scan up to 128 bytes to identify this file as an MP4. 3652a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber static const off64_t kMaxScanOffset = 128ll; 36531b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3654a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t offset = 0ll; 3655a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber bool foundGoodFileType = false; 3656a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t moovAtomEndOffset = -1ll; 3657a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber bool done = false; 36581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3659a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber while (!done && offset < kMaxScanOffset) { 3660a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t hdr[2]; 3661a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (source->readAt(offset, hdr, 8) < 8) { 3662a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3663a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3664a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3665a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint64_t chunkSize = ntohl(hdr[0]); 3666a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t chunkType = ntohl(hdr[1]); 3667a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t chunkDataOffset = offset + 8; 3668a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3669a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (chunkSize == 1) { 3670a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (source->readAt(offset + 8, &chunkSize, 8) < 8) { 36711b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 36721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 36731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3674a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber chunkSize = ntoh64(chunkSize); 3675a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber chunkDataOffset += 8; 3676a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3677a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (chunkSize < 16) { 3678a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // The smallest valid chunk is 16 bytes long in this case. 3679a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3680a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3681a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } else if (chunkSize < 8) { 3682a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // The smallest valid chunk is 8 bytes long. 3683a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3684a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3685a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3686a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t chunkDataSize = offset + chunkSize - chunkDataOffset; 3687a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 368805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen char chunkstring[5]; 368905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MakeFourCCString(chunkType, chunkstring); 369005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("saw chunk type %s, size %lld @ %lld", chunkstring, chunkSize, offset); 3691a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber switch (chunkType) { 3692a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber case FOURCC('f', 't', 'y', 'p'): 3693a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber { 3694a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (chunkDataSize < 8) { 3695a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3696a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3697a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3698a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4; 3699a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber for (size_t i = 0; i < numCompatibleBrands + 2; ++i) { 3700a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (i == 1) { 3701a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // Skip this index, it refers to the minorVersion, 3702a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // not a brand. 3703a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber continue; 3704a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3705a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3706a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t brand; 3707a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (source->readAt( 3708a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber chunkDataOffset + 4 * i, &brand, 4) < 4) { 3709a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3710a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3711a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3712a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber brand = ntohl(brand); 3713a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3714a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (isCompatibleBrand(brand)) { 3715a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber foundGoodFileType = true; 3716a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber break; 3717a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3718a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3719a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3720a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (!foundGoodFileType) { 3721a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3722a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3723a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 37241b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber break; 37251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 3726a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3727a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber case FOURCC('m', 'o', 'o', 'v'): 3728a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber { 3729a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber moovAtomEndOffset = offset + chunkSize; 3730a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3731a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber done = true; 3732a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber break; 3733a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3734a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3735a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber default: 3736a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber break; 37371b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 3738a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3739a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber offset += chunkSize; 37401b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 37411b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3742a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (!foundGoodFileType) { 37431b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 37441b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 37451b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 37461b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 37475a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber *confidence = 0.4f; 37481b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3749a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (moovAtomEndOffset >= 0) { 3750a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber *meta = new AMessage; 3751a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber (*meta)->setInt64("meta-data-size", moovAtomEndOffset); 3752a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3753456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber ALOGV("found metadata size: %lld", moovAtomEndOffset); 3754a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3755a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 37561b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 37571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 37581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 37591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4( 37605a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 3761a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber sp<AMessage> *meta) { 3762a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (BetterSniffMPEG4(source, mimeType, confidence, meta)) { 37631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 37641b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 37651b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 37661b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (LegacySniffMPEG4(source, mimeType, confidence)) { 37675ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Identified supported mpeg4 through LegacySniffMPEG4."); 37681b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 37691b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 37701b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 37711b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 37721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 37731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 377420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3775