MPEG4Extractor.cpp revision 7e9ac3509d72e8dc6f1316b5ce0a0066638b9737
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> 3467a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar#include <media/stagefright/foundation/AUtils.h> 3520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h> 3718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h> 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource { 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 4620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Caller retains ownership of both "dataSource" and "sampleTable". 47693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber MPEG4Source(const sp<MetaData> &format, 48693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &dataSource, 4948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int32_t timeScale, 5005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const sp<SampleTable> &sampleTable, 5105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<SidxEntry> &sidx, 5205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t firstMoofOffset); 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual status_t start(MetaData *params = NULL); 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual status_t stop(); 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual sp<MetaData> getFormat(); 5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL); 6005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL); 6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected: 63693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber virtual ~MPEG4Source(); 64693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 667b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex mLock; 677b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mFormat; 69693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<DataSource> mDataSource; 7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t mTimescale; 71693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<SampleTable> mSampleTable; 7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t mCurrentSampleIndex; 7305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mCurrentFragmentIndex; 7405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<SidxEntry> &mSegments; 7505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t mFirstMoofOffset; 7605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t mCurrentMoofOffset; 7705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t mNextMoofOffset; 7805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mCurrentTime; 7905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t mLastParsedTrackId; 8005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t mTrackId; 8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 82ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int32_t mCryptoMode; // passed in from extractor 83ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int32_t mDefaultIVSize; // passed in from extractor 84ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t mCryptoKey[16]; // passed in from extractor 85ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentAuxInfoType; 86ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentAuxInfoTypeParameter; 8748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen int32_t mCurrentDefaultSampleInfoSize; 88ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentSampleInfoCount; 89ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentSampleInfoAllocSize; 90ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t* mCurrentSampleInfoSizes; 91ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentSampleInfoOffsetCount; 92ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentSampleInfoOffsetsAllocSize; 93ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint64_t* mCurrentSampleInfoOffsets; 94ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 9520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool mIsAVC; 966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t mNALLengthSize; 976064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 9820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool mStarted; 9920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBufferGroup *mGroup; 10120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 10220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *mBuffer; 10320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 104dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber bool mWantsNALFragments; 10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1060024245e134467d120b40099da16c467dc365e76Andreas Huber uint8_t *mSrcBuffer; 1070024245e134467d120b40099da16c467dc365e76Andreas Huber 1086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t parseNALSize(const uint8_t *data) const; 10905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t parseChunk(off64_t *offset); 11005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t parseTrackFragmentHeader(off64_t offset, off64_t size); 11105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t parseTrackFragmentRun(off64_t offset, off64_t size); 112ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size); 113ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size); 11405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 11505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen struct TrackFragmentHeaderInfo { 11605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen enum Flags { 11705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kBaseDataOffsetPresent = 0x01, 11805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleDescriptionIndexPresent = 0x02, 11905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDefaultSampleDurationPresent = 0x08, 12005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDefaultSampleSizePresent = 0x10, 12105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDefaultSampleFlagsPresent = 0x20, 12205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDurationIsEmpty = 0x10000, 12305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 12405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 12505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mTrackID; 12605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mFlags; 12705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t mBaseDataOffset; 12805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mSampleDescriptionIndex; 12905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mDefaultSampleDuration; 13005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mDefaultSampleSize; 13105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mDefaultSampleFlags; 13205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 13305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t mDataOffset; 13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen TrackFragmentHeaderInfo mTrackFragmentHeaderInfo; 13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 13705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen struct Sample { 13805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t offset; 13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t size; 14005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t duration; 141ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t iv[16]; 142ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen Vector<size_t> clearsizes; 143ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen Vector<size_t> encryptedsizes; 14405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 14505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<Sample> mCurrentSamples; 1466064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 14720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Source(const MPEG4Source &); 14820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Source &operator=(const MPEG4Source &); 14920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 15020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests 15250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding 15350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource. 15450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track, 15550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e. 15650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track. 15750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 15850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource { 15950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber MPEG4DataSource(const sp<DataSource> &source); 16050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 16150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual status_t initCheck() const; 162c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong virtual ssize_t readAt(off64_t offset, void *data, size_t size); 163c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong virtual status_t getSize(off64_t *size); 16450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual uint32_t flags(); 16550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 166c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong status_t setCachedRange(off64_t offset, size_t size); 16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected: 16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual ~MPEG4DataSource(); 17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate: 17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber Mutex mLock; 17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 17450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber sp<DataSource> mSource; 175c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t mCachedOffset; 17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber size_t mCachedSize; 17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber uint8_t *mCache; 17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber void clearCache(); 18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber MPEG4DataSource(const MPEG4DataSource &); 18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber MPEG4DataSource &operator=(const MPEG4DataSource &); 18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}; 18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source) 18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber : mSource(source), 18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedOffset(0), 18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedSize(0), 18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCache(NULL) { 19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() { 19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber clearCache(); 19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() { 19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (mCache) { 19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber free(mCache); 19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCache = NULL; 20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 20150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedOffset = 0; 20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedSize = 0; 20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const { 20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->initCheck(); 20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 20950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 210c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) { 21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber Mutex::Autolock autoLock(mLock); 21250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 21367a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar if (isInRange(mCachedOffset, mCachedSize, offset, size)) { 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); 963be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen if (paddingus < 0) { 964be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen // track duration from media header (which is what kKeyDuration is) might 965be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen // be slightly shorter than the segment duration, which would make the 966be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen // padding negative. Clamp to zero. 967be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen paddingus = 0; 968be1195a6d5e6dd4299da344cf9905dd6a12dc4efMarco Nelissen } 9690a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000; 9700a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples); 9710a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9720a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9730a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen *offset += chunk_size; 9740a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen break; 9750a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9760a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 977ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('f', 'r', 'm', 'a'): 978ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen { 97948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t original_fourcc; 980ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) { 981ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 982ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 983ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen original_fourcc = ntohl(original_fourcc); 984ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("read original format: %d", original_fourcc); 985ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc)); 98648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t num_channels = 0; 98748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t sample_rate = 0; 98848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) { 98948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 99048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 99148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 992ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 993ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 994ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 995ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 996ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('t', 'e', 'n', 'c'): 997ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen { 998ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (chunk_size < 32) { 999ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1000ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1001ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1002ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte 1003ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // default IV size, 16 bytes default KeyID 1004ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // (ISO 23001-7) 1005ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen char buf[4]; 1006ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(buf, 0, 4); 1007ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) { 1008ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1009ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1010ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf)); 1011ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (defaultAlgorithmId > 1) { 1012ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // only 0 (clear) and 1 (AES-128) are valid 1013ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1014ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1015ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1016ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(buf, 0, 4); 1017ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) { 1018ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1019ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1020ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t defaultIVSize = ntohl(*((int32_t*)buf)); 1021ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1022ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if ((defaultAlgorithmId == 0 && defaultIVSize != 0) || 1023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen (defaultAlgorithmId != 0 && defaultIVSize == 0)) { 1024ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // only unencrypted data must have 0 IV size 1025ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1026ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } else if (defaultIVSize != 0 && 1027ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen defaultIVSize != 8 && 1028ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen defaultIVSize != 16) { 1029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // only supported sizes are 0, 8 and 16 1030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1033ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t defaultKeyId[16]; 1034ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) { 1036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1037ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1038ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1039ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId); 1040ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize); 1041ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16); 1042ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 1043ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 1044ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1045ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 104620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'k', 'h', 'd'): 104720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 1048ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber status_t err; 1049ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) { 1050ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return err; 105120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 105220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 105320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 105420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('p', 's', 's', 'h'): 1058ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen { 1059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen PsshInfo pssh; 1060ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) { 1062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t psshdatalen = 0; 1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) { 1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen pssh.datalen = ntohl(psshdatalen); 1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("pssh data size: %d", pssh.datalen); 1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (pssh.datalen + 20 > chunk_size) { 1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // pssh data length exceeds size of containing box 1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen pssh.data = new uint8_t[pssh.datalen]; 1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("allocated pssh @ %p", pssh.data); 1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ssize_t requested = (ssize_t) pssh.datalen; 1079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) { 1080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mPssh.push_back(pssh); 1083ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1084ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 1085ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 1086ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1087ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 108820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'd', 'h', 'd'): 108920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 109020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 4) { 109120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 109220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 109320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 109420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t version; 109534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 109620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, &version, sizeof(version)) 109720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(version)) { 109820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 109920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 110020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1101c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t timescale_offset; 110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 110320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (version == 1) { 110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset = data_offset + 4 + 16; 110520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else if (version == 0) { 110620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset = data_offset + 4 + 8; 110720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 110820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 110920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 111020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 111120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t timescale; 111234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 111320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset, ×cale, sizeof(timescale)) 111420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(timescale)) { 111520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 111620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 111720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 111820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->timescale = ntohl(timescale); 111920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 112005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t duration = 0; 112120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (version == 1) { 112234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 112320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset + 4, &duration, sizeof(duration)) 112420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(duration)) { 112520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 112620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 112720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber duration = ntoh64(duration); 112820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 112905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t duration32; 113034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 113120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset + 4, &duration32, sizeof(duration32)) 113220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(duration32)) { 113320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 113420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 113505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // ffmpeg sets duration to -1, which is incorrect. 113605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (duration32 != 0xffffffff) { 113705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen duration = ntohl(duration32); 113805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 113920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 114048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mLastTrack->meta->setInt64( 114148c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber kKeyDuration, (duration * 1000000) / mLastTrack->timescale); 114220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11437a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang uint8_t lang[2]; 11447a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang off64_t lang_offset; 11457a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang if (version == 1) { 11467a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_offset = timescale_offset + 4 + 8; 11477a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } else if (version == 0) { 11487a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_offset = timescale_offset + 4 + 4; 11497a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } else { 11507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang return ERROR_IO; 11517a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 11527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 11537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang if (mDataSource->readAt(lang_offset, &lang, sizeof(lang)) 11547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang < (ssize_t)sizeof(lang)) { 11557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang return ERROR_IO; 11567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 11577a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 11587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // To get the ISO-639-2/T three character language code 11597a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // 1 bit pad followed by 3 5-bits characters. Each character 11607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // is packed as the difference between its ASCII value and 0x60. 11617a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang char lang_code[4]; 11627a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60; 11637a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60; 11647a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[2] = (lang[1] & 0x1f) + 0x60; 11657a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[3] = '\0'; 11667a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 11677a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang mLastTrack->meta->setCString( 11687a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang kKeyMediaLanguage, lang_code); 11697a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'd'): 117520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 117620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 8) { 117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 117820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[8]; 1181c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (chunk_data_size < (off64_t)sizeof(buffer)) { 1182bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1183bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 1184bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 118534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, 8) < 8) { 118720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 118820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (U32_AT(buffer) != 0) { 119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Should be version 0, flags 0. 119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 119320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 119420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t entry_count = U32_AT(&buffer[4]); 119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 119720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (entry_count > 1) { 11983b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // For 3GPP timed text, there could be multiple tx3g boxes contain 11993b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // multiple text display formats. These formats will be used to 12003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // display the timed text. 1201ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // For encrypted files, there may also be more than one entry. 12023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang const char *mime; 12033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 1204ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) && 1205ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen strcasecmp(mime, "application/octet-stream")) { 12063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // For now we only support a single type of media per track. 12073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang mLastTrack->skipTrack = true; 12083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang *offset += chunk_size; 12093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang break; 12103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 121120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1212c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 121320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + 8; 121420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (uint32_t i = 0; i < entry_count; ++i) { 121520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 121820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 121920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1220bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1221bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1222bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1223bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 122420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 122520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 122620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 122720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'a'): 122848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen case FOURCC('e', 'n', 'c', 'a'): 122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 1230371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber case FOURCC('s', 'a', 'w', 'b'): 123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[8 + 20]; 123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Basic AudioSampleEntry size. 123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 123920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 124020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 124120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 124220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 124320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 124448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t num_channels = U16_AT(&buffer[16]); 124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 124681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint16_t sample_size = U16_AT(&buffer[18]); 124781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint32_t sample_rate = U32_AT(&buffer[24]) >> 16; 124881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 124948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (chunk_type != FOURCC('e', 'n', 'c', 'a')) { 125048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // if the chunk type is enca, we'll get the type from the sinf/frma box later 125148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 125248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate); 125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 125448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen ALOGV("*** coding='%s' %d channels, size %d, rate %d\n", 125581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber chunk, num_channels, sample_size, sample_rate); 125620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 125720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 125820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1259c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 126020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + sizeof(buffer); 126120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 126220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 126320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 126420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 126520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 126620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1267bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1268bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1269bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1270bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 127120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 127220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 127320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'v'): 1275ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('e', 'n', 'c', 'v'): 127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', '2', '6', '3'): 1277e071b055cee301d71335519601474c62b10af411James Dong case FOURCC('H', '2', '6', '3'): 1278e071b055cee301d71335519601474c62b10af411James Dong case FOURCC('h', '2', '6', '3'): 127920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', '1'): 128020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 12817be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber mHasVideo = true; 12827be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 128320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[78]; 128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Basic VideoSampleEntry size. 128620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 128820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 128934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t width = U16_AT(&buffer[6 + 18]); 129620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t height = U16_AT(&buffer[6 + 20]); 129720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1298ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // The video sample is not standard-compliant if it has invalid dimension. 1299a6256238d9015c42129fe43791968768fe501efaJames Dong // Use some default width and height value, and 1300a6256238d9015c42129fe43791968768fe501efaJames Dong // let the decoder figure out the actual width and height (and thus 1301a6256238d9015c42129fe43791968768fe501efaJames Dong // be prepared for INFO_FOMRAT_CHANGED event). 1302a6256238d9015c42129fe43791968768fe501efaJames Dong if (width == 0) width = 352; 1303a6256238d9015c42129fe43791968768fe501efaJames Dong if (height == 0) height = 288; 1304a6256238d9015c42129fe43791968768fe501efaJames Dong 1305134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber // printf("*** coding='%s' width=%d height=%d\n", 1306134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber // chunk, width, height); 130720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1308ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (chunk_type != FOURCC('e', 'n', 'c', 'v')) { 1309ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // if the chunk type is encv, we'll get the type from the sinf/frma box later 1310ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 1311ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 131220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyWidth, width); 131320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyHeight, height); 131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1315c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + sizeof(buffer); 131720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1323bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1324bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1325bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1326bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 132720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 132820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'c', 'o'): 133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('c', 'o', '6', '4'): 133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 133320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setChunkOffsetParams( 133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_type, data_offset, chunk_data_size); 133620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 133820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 133920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'c'): 134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSampleToChunkParams( 134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 135820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'z'): 136020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'z', '2'): 136120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 136220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 136320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSampleSizeParams( 136420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_type, data_offset, chunk_data_size); 136520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 136620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 136820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 136920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1370738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber size_t max_size; 137149110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber err = mLastTrack->sampleTable->getMaxSampleSize(&max_size); 137249110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber 137349110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber if (err != OK) { 137449110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber return err; 137549110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber } 1376738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber 137705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (max_size != 0) { 137805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // Assume that a given buffer only contains at most 10 chunks, 137905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // each chunk originally prefixed with a 2 byte length will 138005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion, 138105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // and thus will grow by 2 bytes per chunk. 1382e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen if (max_size > SIZE_MAX - 10 * 2) { 1383e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen ALOGE("max sample size too big: %zu", max_size); 1384e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen return ERROR_MALFORMED; 1385e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen } 138605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2); 138705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 138805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // No size was specified. Pick a conservatively large size. 1389e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen uint32_t width, height; 1390e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen if (!mLastTrack->meta->findInt32(kKeyWidth, (int32_t*)&width) || 1391e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen !mLastTrack->meta->findInt32(kKeyHeight,(int32_t*) &height)) { 139205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGE("No width or height, assuming worst case 1080p"); 1393f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar width = 1920; 1394f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar height = 1080; 1395e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen } else { 1396e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen // A resolution was specified, check that it's not too big. The values below 1397e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen // were chosen so that the calculations below don't cause overflows, they're 1398e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen // not indicating that resolutions up to 32kx32k are actually supported. 1399e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen if (width > 32768 || height > 32768) { 1400e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen ALOGE("can't support %u x %u video", width, height); 1401e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen return ERROR_MALFORMED; 1402e6f5d47a7f9eab8a0009f8a563de473cd47d3110Marco Nelissen } 140305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 1404f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar 14054256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen const char *mime; 14064256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 1407f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 1408f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar // AVC requires compression ratio of at least 2, and uses 1409f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar // macroblocks 1410f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192; 1411f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar } else { 1412f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar // For all other formats there is no minimum compression 1413f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar // ratio. Use compression ratio of 1. 1414f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar max_size = width * height * 3 / 2; 1415f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar } 1416f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size); 141705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 1419113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong 14204256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen // NOTE: setting another piece of metadata invalidates any pointers (such as the 14214256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen // mimetype) previously obtained, so don't cache them. 14224256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen const char *mime; 14234256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 1424113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong // Calculate average frame rate. 1425113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong if (!strncasecmp("video/", mime, 6)) { 1426113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong size_t nSamples = mLastTrack->sampleTable->countSamples(); 1427113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong int64_t durationUs; 1428113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) { 1429113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong if (durationUs > 0) { 1430113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong int32_t frameRate = (nSamples * 1000000LL + 1431113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong (durationUs >> 1)) / durationUs; 1432113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong mLastTrack->meta->setInt32(kKeyFrameRate, frameRate); 1433113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong } 1434113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong } 1435113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong } 1436113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong 143720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 143820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 143920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 144020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 't', 's'): 144120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 144220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 144320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setTimeToSampleParams( 144420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 144520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 144620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 144720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 144820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 144920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 145020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 145120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 145220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 145320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14544931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber case FOURCC('c', 't', 't', 's'): 14554931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber { 14564931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber status_t err = 14574931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber mLastTrack->sampleTable->setCompositionTimeToSampleParams( 14584931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber data_offset, chunk_data_size); 14594931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 14604931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber if (err != OK) { 14614931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber return err; 14624931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 14634931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 14644931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber *offset += chunk_size; 14654931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber break; 14664931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 14674931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 146820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 's'): 146920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 147020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 147120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSyncSampleParams( 147220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 147320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 147420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 147520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 147620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 147720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 147820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 147920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 148020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 148120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14824948818cb91176df74c972ac27b2f392b5d148bcJames Dong // @xyz 14834948818cb91176df74c972ac27b2f392b5d148bcJames Dong case FOURCC('\xA9', 'x', 'y', 'z'): 14844948818cb91176df74c972ac27b2f392b5d148bcJames Dong { 14854948818cb91176df74c972ac27b2f392b5d148bcJames Dong // Best case the total data length inside "@xyz" box 14864948818cb91176df74c972ac27b2f392b5d148bcJames Dong // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/", 14874948818cb91176df74c972ac27b2f392b5d148bcJames Dong // where "\x00\x04" is the text string length with value = 4, 14884948818cb91176df74c972ac27b2f392b5d148bcJames Dong // "\0x15\xc7" is the language code = en, and "0+0" is a 14894948818cb91176df74c972ac27b2f392b5d148bcJames Dong // location (string) value with longitude = 0 and latitude = 0. 14904948818cb91176df74c972ac27b2f392b5d148bcJames Dong if (chunk_data_size < 8) { 14914948818cb91176df74c972ac27b2f392b5d148bcJames Dong return ERROR_MALFORMED; 14924948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 14934948818cb91176df74c972ac27b2f392b5d148bcJames Dong 14944948818cb91176df74c972ac27b2f392b5d148bcJames Dong // Worst case the location string length would be 18, 14954948818cb91176df74c972ac27b2f392b5d148bcJames Dong // for instance +90.0000-180.0000, without the trailing "/" and 14964948818cb91176df74c972ac27b2f392b5d148bcJames Dong // the string length + language code. 14974948818cb91176df74c972ac27b2f392b5d148bcJames Dong char buffer[18]; 14984948818cb91176df74c972ac27b2f392b5d148bcJames Dong 14994948818cb91176df74c972ac27b2f392b5d148bcJames Dong // Substracting 5 from the data size is because the text string length + 15004948818cb91176df74c972ac27b2f392b5d148bcJames Dong // language code takes 4 bytes, and the trailing slash "/" takes 1 byte. 15014948818cb91176df74c972ac27b2f392b5d148bcJames Dong off64_t location_length = chunk_data_size - 5; 15024948818cb91176df74c972ac27b2f392b5d148bcJames Dong if (location_length >= (off64_t) sizeof(buffer)) { 15034948818cb91176df74c972ac27b2f392b5d148bcJames Dong return ERROR_MALFORMED; 15044948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 15054948818cb91176df74c972ac27b2f392b5d148bcJames Dong 15064948818cb91176df74c972ac27b2f392b5d148bcJames Dong if (mDataSource->readAt( 15074948818cb91176df74c972ac27b2f392b5d148bcJames Dong data_offset + 4, buffer, location_length) < location_length) { 15084948818cb91176df74c972ac27b2f392b5d148bcJames Dong return ERROR_IO; 15094948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 15104948818cb91176df74c972ac27b2f392b5d148bcJames Dong 15114948818cb91176df74c972ac27b2f392b5d148bcJames Dong buffer[location_length] = '\0'; 15124948818cb91176df74c972ac27b2f392b5d148bcJames Dong mFileMetaData->setCString(kKeyLocation, buffer); 15134948818cb91176df74c972ac27b2f392b5d148bcJames Dong *offset += chunk_size; 15144948818cb91176df74c972ac27b2f392b5d148bcJames Dong break; 15154948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 15164948818cb91176df74c972ac27b2f392b5d148bcJames Dong 151720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('e', 's', 'd', 's'): 151820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 151920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 4) { 152020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 152320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[256]; 1524c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (chunk_data_size > (off64_t)sizeof(buffer)) { 152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_BUFFER_TOO_SMALL; 152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 152834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (U32_AT(buffer) != 0) { 153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Should be version 0, flags 0. 153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 153620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 153720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 153820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setData( 153920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); 154020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1541ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (mPath.size() >= 2 1542ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) { 1543ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // Information from the ESDS must be relied on for proper 1544ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // setup of sample rate and channel count for MPEG4 Audio. 1545ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // The generic header appears to only contain generic 1546ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // information... 1547ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1548ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio( 1549ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber &buffer[4], chunk_data_size - 4); 1550ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1551ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (err != OK) { 1552ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return err; 1553ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1554ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1555ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 155620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 155720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 155820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 155920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 156020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', 'C'): 156120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 1562d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson sp<ABuffer> buffer = new ABuffer(chunk_data_size); 156320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 156434769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 1565d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson data_offset, buffer->data(), chunk_data_size) < chunk_data_size) { 156620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 156720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 156820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 156920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setData( 1570d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size); 157120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 157220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 157320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 157420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 157520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1576244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong case FOURCC('d', '2', '6', '3'): 1577244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong { 157817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong /* 157917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * d263 contains a fixed 7 bytes part: 158017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * vendor - 4 bytes 158117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * version - 1 byte 158217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * level - 1 byte 158317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * profile - 1 byte 158417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * optionally, "d263" box itself may contain a 16-byte 158517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * bit rate box (bitr) 158617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * average bit rate - 4 bytes 158717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * max bit rate - 4 bytes 158817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong */ 158917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong char buffer[23]; 159017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong if (chunk_data_size != 7 && 159117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong chunk_data_size != 23) { 159229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Incorrect D263 box size %lld", chunk_data_size); 1593244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong return ERROR_MALFORMED; 1594244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong } 1595244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 1596244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong if (mDataSource->readAt( 1597244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong data_offset, buffer, chunk_data_size) < chunk_data_size) { 1598244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong return ERROR_IO; 1599244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong } 1600244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 1601244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size); 1602244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 1603244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong *offset += chunk_size; 1604244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong break; 1605244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong } 1606244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 160772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('m', 'e', 't', 'a'): 160872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 160972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint8_t buffer[4]; 1610c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (chunk_data_size < (off64_t)sizeof(buffer)) { 1611bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1612bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 1613bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 161472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 161572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber data_offset, buffer, 4) < 4) { 161672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 161772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 161872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 161972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (U32_AT(buffer) != 0) { 162072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber // Should be version 0, flags 0. 1621ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber 1622ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // If it's not, let's assume this is one of those 1623ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // apparently malformed chunks that don't have flags 1624ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // and completely different semantics than what's 1625ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // in the MPEG4 specs and skip it. 1626ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber *offset += chunk_size; 1627ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber return OK; 162872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 162972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1630c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 163172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset = data_offset + sizeof(buffer); 163272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber while (*offset < stop_offset) { 163372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseChunk(offset, depth + 1); 163472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 163572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 163672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 163772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 1638bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1639bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1640bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1641bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 164272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 164372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 164472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 16455d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('m', 'e', 'a', 'n'): 16465d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('n', 'a', 'm', 'e'): 164772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('d', 'a', 't', 'a'): 164872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 164972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mPath.size() == 6 && underMetaDataPath(mPath)) { 165072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseMetaData(data_offset, chunk_data_size); 165172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 165272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 165372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 165472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 165572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 165672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 165772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset += chunk_size; 165872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 165972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 166072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 166172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('m', 'v', 'h', 'd'): 166272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 1663fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen if (chunk_data_size < 24) { 166472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_MALFORMED; 166572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 166672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1667fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen uint8_t header[24]; 166872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 166972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber data_offset, header, sizeof(header)) 167072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber < (ssize_t)sizeof(header)) { 167172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 167272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 167372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1674fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen uint64_t creationTime; 167572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (header[0] == 1) { 167672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber creationTime = U64_AT(&header[4]); 1677fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen mHeaderTimescale = U32_AT(&header[20]); 1678bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (header[0] != 0) { 1679bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 168072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 168172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber creationTime = U32_AT(&header[4]); 1682fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen mHeaderTimescale = U32_AT(&header[12]); 168372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 168472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 168572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber String8 s; 168672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber convertTimeToDate(creationTime, &s); 168772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 168872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyDate, s.string()); 168972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 169072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset += chunk_size; 169172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 169272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 169372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang case FOURCC('m', 'd', 'a', 't'): 1695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang { 1696ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("mdat chunk, drm: %d", mIsDrm); 1697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (!mIsDrm) { 1698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang *offset += chunk_size; 1699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang break; 1700dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1701dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 1702dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (chunk_size < 8) { 1703dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 1704dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1705dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 1706dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return parseDrmSINF(offset, data_offset); 1707dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1708dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 17093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang case FOURCC('h', 'd', 'l', 'r'): 17103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang { 17113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint32_t buffer; 17123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if (mDataSource->readAt( 17133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang data_offset + 8, &buffer, 4) < 4) { 17143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang return ERROR_IO; 17153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint32_t type = ntohl(buffer); 17183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // For the 3GPP file format, the handler-type within the 'hdlr' box 1719e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang // shall be 'text'. We also want to support 'sbtl' handler type 1720e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang // for a practical reason as various MPEG4 containers use it. 1721e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) { 17223b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP); 17233b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17243b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17253b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang *offset += chunk_size; 17263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang break; 17273b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17283b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17297a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang case FOURCC('t', 'x', '3', 'g'): 17307a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang { 17313b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint32_t type; 17323b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang const void *data; 17333b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang size_t size = 0; 17343b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if (!mLastTrack->meta->findData( 17353b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang kKeyTextFormatData, &type, &data, &size)) { 17363b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang size = 0; 17373b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17383b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17390e20b2093aa2bbc93afed8d68d3765d18a431b74Nick Kralevich if ((chunk_size > SIZE_MAX) || (SIZE_MAX - chunk_size <= size)) { 1740e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake return ERROR_MALFORMED; 1741e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake } 1742e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake 17433b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint8_t *buffer = new uint8_t[size + chunk_size]; 1744e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake if (buffer == NULL) { 1745e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake return ERROR_MALFORMED; 1746e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake } 17473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if (size > 0) { 17493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang memcpy(buffer, data, size); 17503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17523b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size)) 17533b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang < chunk_size) { 17543b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang delete[] buffer; 17553b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang buffer = NULL; 17563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang return ERROR_IO; 17583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 17593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang mLastTrack->meta->setData( 17613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang kKeyTextFormatData, 0, buffer, size + chunk_size); 17623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 17633b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang delete[] buffer; 17647a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 17657a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang *offset += chunk_size; 17667a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang break; 17677a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 17687a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 1769515e855eae78aa495da58356486aaa666cb57fd1James Dong case FOURCC('c', 'o', 'v', 'r'): 1770515e855eae78aa495da58356486aaa666cb57fd1James Dong { 1771515e855eae78aa495da58356486aaa666cb57fd1James Dong if (mFileMetaData != NULL) { 17723856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("chunk_data_size = %lld and data_offset = %lld", 1773515e855eae78aa495da58356486aaa666cb57fd1James Dong chunk_data_size, data_offset); 177405ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake 17757e9ac3509d72e8dc6f1316b5ce0a0066638b9737Dan Albert if (chunk_data_size < 0 || static_cast<uint64_t>(chunk_data_size) >= SIZE_MAX - 1) { 177605ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake return ERROR_MALFORMED; 177705ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake } 17781552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1); 1779515e855eae78aa495da58356486aaa666cb57fd1James Dong if (mDataSource->readAt( 17801552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) { 1781515e855eae78aa495da58356486aaa666cb57fd1James Dong return ERROR_IO; 1782515e855eae78aa495da58356486aaa666cb57fd1James Dong } 1783515e855eae78aa495da58356486aaa666cb57fd1James Dong const int kSkipBytesOfDataBox = 16; 17844a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake if (chunk_data_size <= kSkipBytesOfDataBox) { 17854a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake return ERROR_MALFORMED; 17864a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake } 17874a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake 1788515e855eae78aa495da58356486aaa666cb57fd1James Dong mFileMetaData->setData( 1789515e855eae78aa495da58356486aaa666cb57fd1James Dong kKeyAlbumArt, MetaData::TYPE_NONE, 17901552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox); 1791515e855eae78aa495da58356486aaa666cb57fd1James Dong } 1792515e855eae78aa495da58356486aaa666cb57fd1James Dong 1793515e855eae78aa495da58356486aaa666cb57fd1James Dong *offset += chunk_size; 1794515e855eae78aa495da58356486aaa666cb57fd1James Dong break; 1795515e855eae78aa495da58356486aaa666cb57fd1James Dong } 1796515e855eae78aa495da58356486aaa666cb57fd1James Dong 17975d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('-', '-', '-', '-'): 17985d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen { 17995d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentMean.clear(); 18005d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentName.clear(); 18015d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentData.clear(); 18025d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen *offset += chunk_size; 18035d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 18045d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 18055d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen 180605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('s', 'i', 'd', 'x'): 180705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen { 180805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseSegmentIndex(data_offset, chunk_data_size); 180905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 181005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return UNKNOWN_ERROR; // stop parsing after sidx 181105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 181205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 181320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber default: 181420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 181520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 181620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 181720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 181820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 181920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 182020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 182120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 182220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 182305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) { 182405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Extractor::parseSegmentIndex"); 182505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 182605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 12) { 182705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 182805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 182905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 183005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t flags; 183105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &flags)) { 183205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 183305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 183405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 183505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t version = flags >> 24; 183605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen flags &= 0xffffff; 183705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 183805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("sidx version %d", version); 183905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 184005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t referenceId; 184105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, &referenceId)) { 184205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 184305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 184405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 184505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t timeScale; 184605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 8, &timeScale)) { 184705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 184805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 184905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale); 185005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 185105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t earliestPresentationTime; 185205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t firstOffset; 185305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 185405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 12; 185505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 12; 185605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 185705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (version == 0) { 185805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 185905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 186005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 186105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t tmp; 186205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 186305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 186405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 186505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen earliestPresentationTime = tmp; 186605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, &tmp)) { 186705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 186805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 186905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen firstOffset = tmp; 187005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 187105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 187205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 187305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 16) { 187405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 187505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 187605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) { 187705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 187805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 187905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt64(offset + 8, &firstOffset)) { 188005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 188105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 188205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 16; 188305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 16; 188405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 188505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("sidx pres/off: %Ld/%Ld", earliestPresentationTime, firstOffset); 188605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 188705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 188805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 188905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 189005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 189105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint16_t referenceCount; 189205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt16(offset + 2, &referenceCount)) { 189305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 189405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 189505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 189605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 189705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("refcount: %d", referenceCount); 189805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 189905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < referenceCount * 12) { 190005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 190105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 190205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 190305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t total_duration = 0; 190405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen for (unsigned int i = 0; i < referenceCount; i++) { 190505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t d1, d2, d3; 190605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 190705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &d1) || // size 190805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen !mDataSource->getUInt32(offset + 4, &d2) || // duration 190905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen !mDataSource->getUInt32(offset + 8, &d3)) { // flags 191005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 191105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 191205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 191305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (d1 & 0x80000000) { 191405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGW("sub-sidx boxes not supported yet"); 191505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 191605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool sap = d3 & 0x80000000; 191705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool saptype = d3 >> 28; 191805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!sap || saptype > 2) { 191905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGW("not a stream access point, or unsupported type"); 192005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 192105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen total_duration += d2; 192205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 12; 192305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3); 192405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen SidxEntry se; 192505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen se.mSize = d1 & 0x7fffffff; 192605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen se.mDurationUs = 1000000LL * d2 / timeScale; 192705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSidxEntries.add(se); 192805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 192905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 193005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSidxDuration = total_duration * 1000000 / timeScale; 193105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("duration: %lld", mSidxDuration); 193205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 193305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t metaDuration; 193405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) { 193505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mLastTrack->meta->setInt64(kKeyDuration, mSidxDuration); 193605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 193705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 193805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 193905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 194005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 194105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 1942ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader( 1943c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t data_offset, off64_t data_size) { 1944ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (data_size < 4) { 1945ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_MALFORMED; 1946ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1947ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1948ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint8_t version; 1949ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (mDataSource->readAt(data_offset, &version, 1) < 1) { 1950ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_IO; 1951ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1952ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1953ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber size_t dynSize = (version == 1) ? 36 : 24; 1954ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1955ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint8_t buffer[36 + 60]; 1956ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1957c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (data_size != (off64_t)dynSize + 60) { 1958ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_MALFORMED; 1959ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1960ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1961ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (mDataSource->readAt( 1962ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber data_offset, buffer, data_size) < (ssize_t)data_size) { 1963ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_IO; 1964ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1965ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1966ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint64_t ctime, mtime, duration; 1967ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t id; 1968ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1969ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (version == 1) { 1970ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber ctime = U64_AT(&buffer[4]); 1971ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mtime = U64_AT(&buffer[12]); 1972ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber id = U32_AT(&buffer[20]); 1973ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber duration = U64_AT(&buffer[28]); 197404022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen } else if (version == 0) { 1975ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber ctime = U32_AT(&buffer[4]); 1976ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mtime = U32_AT(&buffer[8]); 1977ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber id = U32_AT(&buffer[12]); 1978ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber duration = U32_AT(&buffer[20]); 197904022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen } else { 198004022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen return ERROR_UNSUPPORTED; 1981ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 1982ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1983ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mLastTrack->meta->setInt32(kKeyTrackID, id); 1984ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1985ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber size_t matrixOffset = dynSize + 16; 1986ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a00 = U32_AT(&buffer[matrixOffset]); 1987ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a01 = U32_AT(&buffer[matrixOffset + 4]); 1988ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t dx = U32_AT(&buffer[matrixOffset + 8]); 1989ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a10 = U32_AT(&buffer[matrixOffset + 12]); 1990ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a11 = U32_AT(&buffer[matrixOffset + 16]); 1991ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t dy = U32_AT(&buffer[matrixOffset + 20]); 1992ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 1993ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0 1994df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("x' = %.2f * x + %.2f * y + %.2f", 1995ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f); 1996df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("y' = %.2f * x + %.2f * y + %.2f", 1997ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f); 1998ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif 1999ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2000ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint32_t rotationDegrees; 2001ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2002ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber static const int32_t kFixedOne = 0x10000; 2003ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) { 2004ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber // Identity, no rotation 2005ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 0; 2006ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) { 2007ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 90; 2008ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) { 2009ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 270; 2010ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) { 2011ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 180; 2012ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else { 20135ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("We only support 0,90,180,270 degree rotation matrices"); 2014ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 0; 2015ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 2016ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2017ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (rotationDegrees != 0) { 2018ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees); 2019ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 2020ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2021b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong // Handle presentation display size, which could be different 2022b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong // from the image size indicated by kKeyWidth and kKeyHeight. 2023ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint32_t width = U32_AT(&buffer[dynSize + 52]); 2024ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint32_t height = U32_AT(&buffer[dynSize + 56]); 2025b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16); 2026b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16); 2027ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2028ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return OK; 2029ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber} 2030ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2031c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) { 2032a1e21653e86d21a4ab0946ee2761b6f0163d5742Nick Kralevich if (size < 4 || size == SIZE_MAX) { 203372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_MALFORMED; 203472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 203572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 203672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint8_t *buffer = new uint8_t[size + 1]; 203772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 203872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber offset, buffer, size) != (ssize_t)size) { 203972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber delete[] buffer; 204072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer = NULL; 204172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 204272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 204372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 204472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 204572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint32_t flags = U32_AT(buffer); 204672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 204772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint32_t metadataKey = 0; 20485d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen char chunk[5]; 20495d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen MakeFourCCString(mPath[4], chunk); 20505d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen ALOGV("meta: %s @ %lld", chunk, offset); 205172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber switch (mPath[4]) { 205272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'a', 'l', 'b'): 205372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 205472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyAlbum; 205572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 205672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 205772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'A', 'R', 'T'): 205872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 205972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyArtist; 206072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 206172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 206266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen case FOURCC('a', 'A', 'R', 'T'): 206366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen { 206466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen metadataKey = kKeyAlbumArtist; 206566ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen break; 206666ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen } 206772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'd', 'a', 'y'): 206872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 206972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyYear; 207072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 207172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 207272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'n', 'a', 'm'): 207372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 207472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyTitle; 207572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 207672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 207772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'w', 'r', 't'): 207872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 207972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyWriter; 208072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 208172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 208272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('c', 'o', 'v', 'r'): 208372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 208472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyAlbumArt; 208572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 208672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 208772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('g', 'n', 'r', 'e'): 208872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 208972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyGenre; 209072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 209172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 209226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen case FOURCC(0xa9, 'g', 'e', 'n'): 209326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen { 209426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen metadataKey = kKeyGenre; 209526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen break; 209626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 209711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen case FOURCC('c', 'p', 'i', 'l'): 209811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { 209911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen if (size == 9 && flags == 21) { 210011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen char tmp[16]; 210111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen sprintf(tmp, "%d", 210211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen (int)buffer[size - 1]); 210311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen 210411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen mFileMetaData->setCString(kKeyCompilation, tmp); 210511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen } 210611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen break; 210711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen } 210872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('t', 'r', 'k', 'n'): 210972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 211072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (size == 16 && flags == 0) { 211172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char tmp[16]; 2112afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pTrack = (uint16_t*)&buffer[10]; 2113afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pTotalTracks = (uint16_t*)&buffer[12]; 2114afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks)); 211572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 211672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyCDTrackNumber, tmp); 211772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 211872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 211972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 212026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen case FOURCC('d', 'i', 's', 'k'): 212126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen { 2122afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik if ((size == 14 || size == 16) && flags == 0) { 212326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen char tmp[16]; 2124afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pDisc = (uint16_t*)&buffer[10]; 2125afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pTotalDiscs = (uint16_t*)&buffer[12]; 2126afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs)); 212726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 212826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen mFileMetaData->setCString(kKeyDiscNumber, tmp); 212926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 213026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen break; 213126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 21325d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('-', '-', '-', '-'): 21335d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen { 21345d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen buffer[size] = '\0'; 21355d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen switch (mPath[5]) { 21365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('m', 'e', 'a', 'n'): 21375d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentMean.setTo((const char *)buffer + 4); 21385d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 21395d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('n', 'a', 'm', 'e'): 21405d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentName.setTo((const char *)buffer + 4); 21415d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 21425d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('d', 'a', 't', 'a'): 21435d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentData.setTo((const char *)buffer + 8); 21445d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 21455d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 21468c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman 21478c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // Once we have a set of mean/name/data info, go ahead and process 21488c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // it to see if its something we are interested in. Whether or not 21498c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // were are interested in the specific tag, make sure to clear out 21508c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // the set so we can be ready to process another tuple should one 21518c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // show up later in the file. 21528c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman if ((mLastCommentMean.length() != 0) && 21538c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman (mLastCommentName.length() != 0) && 21548c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman (mLastCommentData.length() != 0)) { 21558c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman 21568c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman if (mLastCommentMean == "com.apple.iTunes" 21578c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman && mLastCommentName == "iTunSMPB") { 21588c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman int32_t delay, padding; 21598c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman if (sscanf(mLastCommentData, 21608c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman " %*x %x %x %*x", &delay, &padding) == 2) { 21618c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman mLastTrack->meta->setInt32(kKeyEncoderDelay, delay); 21628c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman mLastTrack->meta->setInt32(kKeyEncoderPadding, padding); 21638c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman } 21645d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 21658c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman 21665d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentMean.clear(); 21675d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentName.clear(); 21685d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentData.clear(); 21695d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 21705d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 21715d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 217226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 217372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber default: 217472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 217572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 217672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 217772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (size >= 8 && metadataKey) { 217872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (metadataKey == kKeyAlbumArt) { 217972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setData( 218072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber kKeyAlbumArt, MetaData::TYPE_NONE, 218172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer + 8, size - 8); 218272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else if (metadataKey == kKeyGenre) { 218372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (flags == 0) { 218426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // uint8_t genre code, iTunes genre codes are 218526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // the standard id3 codes, except they start 218626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // at 1 instead of 0 (e.g. Pop is 14, not 13) 218726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // We use standard id3 numbering, so subtract 1. 218826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen int genrecode = (int)buffer[size - 1]; 218926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen genrecode--; 219026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen if (genrecode < 0) { 219126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen genrecode = 255; // reserved for 'unknown genre' 219226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 219372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char genre[10]; 219426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen sprintf(genre, "%d", genrecode); 219572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 219672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(metadataKey, genre); 219726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } else if (flags == 1) { 219826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // custom genre string 219926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen buffer[size] = '\0'; 220026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 220126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen mFileMetaData->setCString( 220226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen metadataKey, (const char *)buffer + 8); 220372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 220472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 220572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer[size] = '\0'; 220672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 220772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString( 220872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey, (const char *)buffer + 8); 220972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 221072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 221172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 221272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber delete[] buffer; 221372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer = NULL; 221472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 221572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return OK; 221672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 221772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 2218693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) { 221920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 222020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 2221693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return NULL; 222220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 222320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 222420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 222520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (index > 0) { 222620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (track == NULL) { 2227693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return NULL; 222820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 222920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 223020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 223120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber --index; 223220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 223320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2234371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber if (track == NULL) { 2235371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber return NULL; 2236371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber } 2237371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber 2238ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("getTrack called, pssh: %d", mPssh.size()); 2239ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2240693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return new MPEG4Source( 224105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen track->meta, mDataSource, track->timescale, track->sampleTable, 224205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSidxEntries, mMoofOffset); 224320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 224420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2245bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static 2246bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) { 2247bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber const char *mime; 2248bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 2249bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 2250bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber uint32_t type; 2251bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber const void *data; 2252bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber size_t size; 2253bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 2254bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!track->meta->findData(kKeyAVCC, &type, &data, &size) 2255bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || type != kTypeAVCC) { 2256bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 2257bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 2258bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 2259bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 2260bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!track->meta->findData(kKeyESDS, &type, &data, &size) 2261bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || type != kTypeESDS) { 2262bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 2263bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 2264bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 2265bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 2266169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber if (!track->sampleTable->isValid()) { 2267169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber // Make sure we have all the metadata we need. 2268169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber return ERROR_MALFORMED; 2269169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber } 2270169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber 2271bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return OK; 2272bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber} 2273bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 2274ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( 2275ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber const void *esds_data, size_t esds_size) { 2276ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber ESDS esds(esds_data, esds_size); 227781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 227881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint8_t objectTypeIndication; 227981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) { 228081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber return ERROR_MALFORMED; 228181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber } 228281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 228381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber if (objectTypeIndication == 0xe1) { 228481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber // This isn't MPEG4 audio at all, it's QCELP 14k... 228581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP); 228681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber return OK; 228781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber } 228881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 2289633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong if (objectTypeIndication == 0x6b) { 2290633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong // The media subtype is MP3 audio 2291633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong // Our software MP3 audio decoder may not be able to handle 2292633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED 229329357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("MP3 track in MP4/3GPP file is not supported"); 2294633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong return ERROR_UNSUPPORTED; 2295633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong } 2296633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong 2297ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber const uint8_t *csd; 2298ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber size_t csd_size; 2299ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (esds.getCodecSpecificInfo( 2300ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber (const void **)&csd, &csd_size) != OK) { 2301ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 2302ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2303ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2304ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0 2305ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber printf("ESD of size %d\n", csd_size); 2306ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber hexdump(csd, csd_size); 2307ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif 2308ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2309a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber if (csd_size == 0) { 2310a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber // There's no further information, i.e. no codec specific data 2311a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber // Let's assume that the information provided in the mpeg4 headers 2312a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber // is accurate and hope for the best. 2313a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber 2314a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber return OK; 2315a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber } 2316a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber 2317ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (csd_size < 2) { 2318ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 2319ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2320ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 23213c836e7882e88de42e0e600627de433b61e78621Eric Laurent static uint32_t kSamplingRate[] = { 23223c836e7882e88de42e0e600627de433b61e78621Eric Laurent 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 23233c836e7882e88de42e0e600627de433b61e78621Eric Laurent 16000, 12000, 11025, 8000, 7350 23243c836e7882e88de42e0e600627de433b61e78621Eric Laurent }; 23253c836e7882e88de42e0e600627de433b61e78621Eric Laurent 2326aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke ABitReader br(csd, csd_size); 2327aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke uint32_t objectType = br.getBits(5); 2328ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2329aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke if (objectType == 31) { // AAC-ELD => additional 6 bits 2330aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke objectType = 32 + br.getBits(6); 2331ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2332ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2333f590f948e6c0fe3c54008dd7802fd513f127792dEric Laurent //keep AOT type 2334f590f948e6c0fe3c54008dd7802fd513f127792dEric Laurent mLastTrack->meta->setInt32(kKeyAACAOT, objectType); 2335f590f948e6c0fe3c54008dd7802fd513f127792dEric Laurent 2336aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke uint32_t freqIndex = br.getBits(4); 2337aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke 2338ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t sampleRate = 0; 2339ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t numChannels = 0; 2340ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (freqIndex == 15) { 2341ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (csd_size < 5) { 2342ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 2343ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2344aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke sampleRate = br.getBits(24); 2345aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke numChannels = br.getBits(4); 2346ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } else { 2347595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen numChannels = br.getBits(4); 23483c836e7882e88de42e0e600627de433b61e78621Eric Laurent 23493c836e7882e88de42e0e600627de433b61e78621Eric Laurent if (freqIndex == 13 || freqIndex == 14) { 23503c836e7882e88de42e0e600627de433b61e78621Eric Laurent return ERROR_MALFORMED; 2351ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2352ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 23533c836e7882e88de42e0e600627de433b61e78621Eric Laurent sampleRate = kSamplingRate[freqIndex]; 23543c836e7882e88de42e0e600627de433b61e78621Eric Laurent } 2355595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen 23563c836e7882e88de42e0e600627de433b61e78621Eric Laurent if (objectType == 5 || objectType == 29) { // SBR specific config per 14496-3 table 1.13 23573c836e7882e88de42e0e600627de433b61e78621Eric Laurent uint32_t extFreqIndex = br.getBits(4); 23583c836e7882e88de42e0e600627de433b61e78621Eric Laurent int32_t extSampleRate; 23593c836e7882e88de42e0e600627de433b61e78621Eric Laurent if (extFreqIndex == 15) { 23603c836e7882e88de42e0e600627de433b61e78621Eric Laurent if (csd_size < 8) { 2361595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen return ERROR_MALFORMED; 2362595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen } 23633c836e7882e88de42e0e600627de433b61e78621Eric Laurent extSampleRate = br.getBits(24); 23643c836e7882e88de42e0e600627de433b61e78621Eric Laurent } else { 23653c836e7882e88de42e0e600627de433b61e78621Eric Laurent if (extFreqIndex == 13 || extFreqIndex == 14) { 23663c836e7882e88de42e0e600627de433b61e78621Eric Laurent return ERROR_MALFORMED; 23673c836e7882e88de42e0e600627de433b61e78621Eric Laurent } 23683c836e7882e88de42e0e600627de433b61e78621Eric Laurent extSampleRate = kSamplingRate[extFreqIndex]; 2369595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen } 23703c836e7882e88de42e0e600627de433b61e78621Eric Laurent //TODO: save the extension sampling rate value in meta data => 23713c836e7882e88de42e0e600627de433b61e78621Eric Laurent // mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate); 2372ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2373ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2374ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (numChannels == 0) { 2375ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_UNSUPPORTED; 2376ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2377ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2378ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t prevSampleRate; 2379ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate)); 2380ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2381ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (prevSampleRate != sampleRate) { 23823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("mpeg4 audio sample rate different from previous setting. " 2383ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber "was: %d, now: %d", prevSampleRate, sampleRate); 2384ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2385ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2386ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sampleRate); 2387ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2388ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t prevChannelCount; 2389ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount)); 2390ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2391ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (prevChannelCount != numChannels) { 23923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("mpeg4 audio channel count different from previous setting. " 2393ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber "was: %d, now: %d", prevChannelCount, numChannels); 2394ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2395ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2396ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, numChannels); 2397ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2398ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return OK; 2399ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber} 2400ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 240120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 240220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 240320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source( 240420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const sp<MetaData> &format, 2405693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &dataSource, 240648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int32_t timeScale, 240705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const sp<SampleTable> &sampleTable, 240805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<SidxEntry> &sidx, 240905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t firstMoofOffset) 241020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFormat(format), 241120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDataSource(dataSource), 241248c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mTimescale(timeScale), 241320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSampleTable(sampleTable), 241420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCurrentSampleIndex(0), 241505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentFragmentIndex(0), 241605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSegments(sidx), 241705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mFirstMoofOffset(firstMoofOffset), 241805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentMoofOffset(firstMoofOffset), 241905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentTime(0), 2420ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoAllocSize(0), 2421ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoSizes(NULL), 2422ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsetsAllocSize(0), 2423ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets(NULL), 242420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mIsAVC(false), 24256064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mNALLengthSize(0), 242620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted(false), 242720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup(NULL), 242820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer(NULL), 2429dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments(false), 24300024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer(NULL) { 2431ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2432ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mFormat->findInt32(kKeyCryptoMode, &mCryptoMode); 243348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mDefaultIVSize = 0; 2434ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize); 2435ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t keytype; 2436ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen const void *key; 2437ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen size_t keysize; 2438ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) { 2439ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen CHECK(keysize <= 16); 2440ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(mCryptoKey, 0, 16); 2441ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memcpy(mCryptoKey, key, keysize); 2442ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2443ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 244420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 244520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mFormat->findCString(kKeyMIMEType, &mime); 2446dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(success); 244720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 244818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 24496064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 24506064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber if (mIsAVC) { 24516064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber uint32_t type; 24526064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber const void *data; 24536064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t size; 24546064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(format->findData(kKeyAVCC, &type, &data, &size)); 24556064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 24566064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber const uint8_t *ptr = (const uint8_t *)data; 24576064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 24586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(size >= 7); 2459ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 24606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 24616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // The number of bytes used to encode the length of a NAL unit. 24626064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mNALLengthSize = 1 + (ptr[4] & 3); 24636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber } 246405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 246505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(format->findInt32(kKeyTrackID, &mTrackId)); 246605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 246705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mFirstMoofOffset != 0) { 246805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t offset = mFirstMoofOffset; 246905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(&offset); 247005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 247120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 247220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 247320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() { 247420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mStarted) { 247520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 247620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 2477ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen free(mCurrentSampleInfoSizes); 2478ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen free(mCurrentSampleInfoOffsets); 247920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 248020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 248120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) { 24827b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 24837b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 2484dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(!mStarted); 248520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 248620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t val; 2487dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (params && params->findInt32(kKeyWantsNALFragments, &val) 248820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && val != 0) { 2489dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments = true; 249020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 2491dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments = false; 249220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 249320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 249420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup = new MediaBufferGroup; 249520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2496738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber int32_t max_size; 2497738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size)); 249820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2499738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber mGroup->add_buffer(new MediaBuffer(max_size)); 25000024245e134467d120b40099da16c467dc365e76Andreas Huber 25010024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer = new uint8_t[max_size]; 250220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 250320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = true; 250420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 250520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 250620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 250720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 250820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() { 25097b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 25107b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 2511dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(mStarted); 251220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 251320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mBuffer != NULL) { 251420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 251520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 251620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 251720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 25180024245e134467d120b40099da16c467dc365e76Andreas Huber delete[] mSrcBuffer; 25190024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer = NULL; 25200024245e134467d120b40099da16c467dc365e76Andreas Huber 252120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete mGroup; 252220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup = NULL; 252320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 252420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = false; 252520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCurrentSampleIndex = 0; 252620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 252720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 252820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 252920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 253005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) { 253105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t hdr[2]; 253205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mDataSource->readAt(*offset, hdr, 8) < 8) { 253305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 253405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 253505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t chunk_size = ntohl(hdr[0]); 253605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t chunk_type = ntohl(hdr[1]); 253705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t data_offset = *offset + 8; 253805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 253905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_size == 1) { 254005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { 254105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 254205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 254305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen chunk_size = ntoh64(chunk_size); 254405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen data_offset += 8; 254505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 254605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_size < 16) { 254705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // The smallest valid chunk is 16 bytes long in this case. 254805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 254905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 255005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (chunk_size < 8) { 255105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // The smallest valid chunk is 8 bytes long. 255205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 255305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 255405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 255505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen char chunk[5]; 255605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MakeFourCCString(chunk_type, chunk); 255705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset); 255805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 255905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t chunk_data_size = *offset + chunk_size - data_offset; 256005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 256105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen switch(chunk_type) { 256205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 256305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('t', 'r', 'a', 'f'): 256405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('m', 'o', 'o', 'f'): { 256505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t stop_offset = *offset + chunk_size; 256605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset = data_offset; 256705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen while (*offset < stop_offset) { 256805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err = parseChunk(offset); 256905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (err != OK) { 257005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 257105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 257205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 257305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_type == FOURCC('m', 'o', 'o', 'f')) { 2574ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // *offset points to the mdat box following this moof 257505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(offset); // doesn't actually parse it, just updates offset 257605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mNextMoofOffset = *offset; 257705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 257805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 257905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 258005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 258105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('t', 'f', 'h', 'd'): { 258205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err; 258305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) { 258405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 258505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 258605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 258705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 258805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 258905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 259005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('t', 'r', 'u', 'n'): { 259105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err; 259205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mLastParsedTrackId == mTrackId) { 259305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) { 259405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 259505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 259605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 259705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 259805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 259905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 260005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 260105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 2602ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'a', 'i', 'z'): { 2603ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t err; 2604ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) { 2605ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return err; 2606ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2607ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 2608ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 2609ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2610ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'a', 'i', 'o'): { 2611ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t err; 2612ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) { 2613ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return err; 2614ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2615ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 2616ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 2617ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2618ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2619ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('m', 'd', 'a', 't'): { 2620ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // parse DRM info if present 2621ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("MPEG4Source::parseChunk mdat"); 2622ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // if saiz/saoi was previously observed, do something with the sampleinfos 2623ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 2624ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 2625ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2626ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 262705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen default: { 262805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 262905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 263005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 263105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 263205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 263305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 263405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 2635ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size) { 2636ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("parseSampleAuxiliaryInformationSizes"); 2637ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // 14496-12 8.7.12 2638ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t version; 2639ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt( 2640ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset, &version, sizeof(version)) 2641ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen < (ssize_t)sizeof(version)) { 2642ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2643ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2644ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2645ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (version != 0) { 2646ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_UNSUPPORTED; 2647ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2648ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset++; 2649ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2650ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t flags; 2651ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt24(offset, &flags)) { 2652ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2653ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2654ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 3; 2655ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2656ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (flags & 1) { 2657ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t tmp; 2658ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 2659ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 2660ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2661ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentAuxInfoType = tmp; 2662ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2663ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 2664ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 2665ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2666ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentAuxInfoTypeParameter = tmp; 2667ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2668ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2669ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2670ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t defsize; 2671ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(offset, &defsize, 1) != 1) { 2672ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 2673ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2674ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentDefaultSampleInfoSize = defsize; 2675ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset++; 2676ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2677ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t smplcnt; 2678ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &smplcnt)) { 2679ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 2680ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 268148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mCurrentSampleInfoCount = smplcnt; 2682ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2683ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 268448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (mCurrentDefaultSampleInfoSize != 0) { 268548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize); 268648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return OK; 268748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 2688ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (smplcnt > mCurrentSampleInfoAllocSize) { 2689ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt); 2690ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoAllocSize = smplcnt; 2691ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2692ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2693ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt); 2694ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return OK; 2695ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen} 2696ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2697ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissenstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size) { 2698ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("parseSampleAuxiliaryInformationOffsets"); 2699ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // 14496-12 8.7.13 2700ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t version; 2701ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) { 2702ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2703ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2704ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset++; 2705ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2706ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t flags; 2707ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt24(offset, &flags)) { 2708ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2709ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2710ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 3; 2711ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2712ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t entrycount; 2713ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &entrycount)) { 2714ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2715ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2716ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2717ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2718ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (entrycount > mCurrentSampleInfoOffsetsAllocSize) { 2719ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8); 2720ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsetsAllocSize = entrycount; 2721ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2722ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsetCount = entrycount; 2723ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2724ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < entrycount; i++) { 2725ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (version == 0) { 2726ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t tmp; 2727ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 2728ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2729ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2730ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets[i] = tmp; 2731ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 2732ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } else { 2733ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint64_t tmp; 2734ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt64(offset, &tmp)) { 2735ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2736ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2737ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets[i] = tmp; 2738ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 8; 2739ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2740ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2741ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2742ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // parse clear/encrypted data 2743ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2744ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof 2745ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2746ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen drmoffset += mCurrentMoofOffset; 2747ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int ivlength; 2748ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength)); 274948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 275048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // read CencSampleAuxiliaryDataFormats 2751ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mCurrentSampleInfoCount; i++) { 2752ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen Sample *smpl = &mCurrentSamples.editItemAt(i); 2753ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2754ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(smpl->iv, 0, 16); 2755ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) { 2756ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2757ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2758ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2759ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen drmoffset += ivlength; 2760ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 276148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen int32_t smplinfosize = mCurrentDefaultSampleInfoSize; 276248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (smplinfosize == 0) { 276348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smplinfosize = mCurrentSampleInfoSizes[i]; 2764ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 276548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (smplinfosize > ivlength) { 276648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint16_t numsubsamples; 276748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) { 2768ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 2769ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2770ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen drmoffset += 2; 277148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen for (size_t j = 0; j < numsubsamples; j++) { 277248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint16_t numclear; 277348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t numencrypted; 277448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!mDataSource->getUInt16(drmoffset, &numclear)) { 277548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return ERROR_IO; 277648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 277748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen drmoffset += 2; 277848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!mDataSource->getUInt32(drmoffset, &numencrypted)) { 277948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return ERROR_IO; 278048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 278148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen drmoffset += 4; 278248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->clearsizes.add(numclear); 278348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->encryptedsizes.add(numencrypted); 2784ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 278548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } else { 278648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->clearsizes.add(0); 278748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->encryptedsizes.add(smpl->size); 2788ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2789ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 2790ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2791ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2792ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return OK; 2793ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen} 2794ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 279505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) { 279605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 279705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 279805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 279905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 280005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 280105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t flags; 2802ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags 280305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 280405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 280505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 280605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & 0xff000000) { 280705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 280805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 280905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 281005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) { 281105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 281205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 281305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 281405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mLastParsedTrackId != mTrackId) { 281505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // this is not the right track, skip it 281605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 281705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 281805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 281905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mFlags = flags; 282005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId; 282105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 282205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 282305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 282405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID); 282505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 282605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) { 282705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 282805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 282905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 283005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 283105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) { 283205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 283305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 283405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 283505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 283605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 283705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 283805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) { 283905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 284005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 284105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 284205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 284305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) { 284405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 284505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 284605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 284705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 284805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 284905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 285005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) { 285105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 285205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 285305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 285405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 285505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) { 285605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 285705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 285805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 285905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 286005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 286105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 286205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) { 286305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 286405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 286505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 286605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 286705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) { 286805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 286905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 287005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 287105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 287205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 287305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 287405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) { 287505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 287605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 287705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 287805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 287905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) { 288005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 288105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 288205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 288305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 288405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 288505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 288605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) { 288705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset; 288805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 288905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 289005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mDataOffset = 0; 289105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 289205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 289305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 289405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) { 289505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 289605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Extractor::parseTrackFragmentRun"); 289705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 289805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 289905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 290005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 290105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen enum { 290205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDataOffsetPresent = 0x01, 290305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kFirstSampleFlagsPresent = 0x04, 290405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleDurationPresent = 0x100, 290505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleSizePresent = 0x200, 290605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleFlagsPresent = 0x400, 290705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleCompositionTimeOffsetPresent = 0x800, 290805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 290905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 291005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t flags; 291105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &flags)) { 291205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 291305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 291405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("fragment run flags: %08x", flags); 291505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 291605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & 0xff000000) { 291705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 291805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 291905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 292005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) { 292105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // These two shall not be used together. 292205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 292305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 292405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 292505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleCount; 292605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, &sampleCount)) { 292705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 292805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 292905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 293005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 293105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 293205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset; 293305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 293405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t firstSampleFlags = 0; 293505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 293605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kDataOffsetPresent) { 293705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 293805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 293905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 294005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 294105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t dataOffsetDelta; 294205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) { 294305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 294405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 294505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 294605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta; 294705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 294805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 294905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 295005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 295105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 295205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kFirstSampleFlagsPresent) { 295305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 295405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 295505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 295605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 295705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &firstSampleFlags)) { 295805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 295905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 296005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 296105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 296205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 296305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 296405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0, 296505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleCtsOffset = 0; 296605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 296705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t bytesPerSample = 0; 296805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleDurationPresent) { 296905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 297005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (mTrackFragmentHeaderInfo.mFlags 297105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) { 297205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration; 297305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 297405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration; 297505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 297605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 297705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleSizePresent) { 297805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 297905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (mTrackFragmentHeaderInfo.mFlags 298005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) { 298105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize; 298205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 298305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize; 298405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 298505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 298605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleFlagsPresent) { 298705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 298805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (mTrackFragmentHeaderInfo.mFlags 298905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) { 299005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags; 299105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 299205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags; 299305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 299405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 299505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleCompositionTimeOffsetPresent) { 299605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 299705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 299805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleCtsOffset = 0; 299905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 300005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 300105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < sampleCount * bytesPerSample) { 300205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 300305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 300405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 300505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Sample tmp; 300605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen for (uint32_t i = 0; i < sampleCount; ++i) { 300705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleDurationPresent) { 300805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleDuration)) { 300905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 301005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 301105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 301205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 301305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 301405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleSizePresent) { 301505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleSize)) { 301605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 301705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 301805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 301905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 302005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 302105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleFlagsPresent) { 302205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleFlags)) { 302305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 302405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 302505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 302605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 302705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 302805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleCompositionTimeOffsetPresent) { 302905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) { 303005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 303105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 303205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 303305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 303405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 3035ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("adding sample %d at offset 0x%08llx, size %u, duration %u, " 3036ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen " flags 0x%08x", i + 1, 303705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dataOffset, sampleSize, sampleDuration, 303805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (flags & kFirstSampleFlagsPresent) && i == 0 303905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ? firstSampleFlags : sampleFlags); 304005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen tmp.offset = dataOffset; 304105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen tmp.size = sampleSize; 304205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen tmp.duration = sampleDuration; 304305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSamples.add(tmp); 304405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 304505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dataOffset += sampleSize; 304605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 304705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 304805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mDataOffset = dataOffset; 304905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 305005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 305105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 305205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 305320111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() { 30547b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 30557b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 305620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return mFormat; 305720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 305820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const { 30606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber switch (mNALLengthSize) { 30616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 1: 30626064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return *data; 30636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 2: 30646064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return U16_AT(data); 30656064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 3: 30666064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return ((size_t)data[0] << 16) | U16_AT(&data[1]); 30676064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 4: 30686064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return U32_AT(data); 30696064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber } 30706064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 30716064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // This cannot happen, mNALLengthSize springs to life by adding 1 to 30726064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // a 2-bit integer. 30736064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(!"Should not be here."); 30746064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 30756064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return 0; 30766064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber} 30776064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 307820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read( 307920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer **out, const ReadOptions *options) { 30807b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 30817b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 3082dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(mStarted); 308320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 308405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mFirstMoofOffset > 0) { 308505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return fragmentedRead(out, options); 308605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 308705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 308820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *out = NULL; 308920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3090abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber int64_t targetSampleTimeUs = -1; 3091abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 309220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t seekTimeUs; 3093abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 3094abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 3095abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t findFlags = 0; 3096abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber switch (mode) { 3097abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_PREVIOUS_SYNC: 3098abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagBefore; 3099abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3100abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_NEXT_SYNC: 3101abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagAfter; 3102abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3103abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_CLOSEST_SYNC: 3104abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_CLOSEST: 3105abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagClosest; 3106abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3107abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber default: 3108abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber CHECK(!"Should not be here."); 3109abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3110abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3111abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 311220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t sampleIndex; 3113abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber status_t err = mSampleTable->findSampleAtTime( 311420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber seekTimeUs * mTimescale / 1000000, 3115abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber &sampleIndex, findFlags); 3116abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3117abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 3118abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber // We found the closest sample already, now we want the sync 3119abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber // sample preceding it (or the sample itself of course), even 3120abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber // if the subsequent sync sample is closer. 3121abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagBefore; 3122abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3123abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3124abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t syncSampleIndex; 3125abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (err == OK) { 3126abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber err = mSampleTable->findSyncSampleNear( 3127abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber sampleIndex, &syncSampleIndex, findFlags); 3128abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 312920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3130788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber uint32_t sampleTime; 3131788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber if (err == OK) { 3132788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber err = mSampleTable->getMetaDataForSample( 3133788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber sampleIndex, NULL, NULL, &sampleTime); 3134788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber } 3135788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber 313620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 31375295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber if (err == ERROR_OUT_OF_RANGE) { 31385295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // An attempt to seek past the end of the stream would 31395295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // normally cause this ERROR_OUT_OF_RANGE error. Propagating 31405295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // this all the way to the MediaPlayer would cause abnormal 31415295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // termination. Legacy behaviour appears to be to behave as if 31425295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // we had seeked to the end of stream, ending normally. 31435295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber err = ERROR_END_OF_STREAM; 31445295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber } 314505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("end of stream"); 314620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 314720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 314820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3149abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 3150abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale; 3151abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3152abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3153abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0 3154abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t syncSampleTime; 3155abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber CHECK_EQ(OK, mSampleTable->getMetaDataForSample( 3156abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber syncSampleIndex, NULL, NULL, &syncSampleTime)); 3157abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3158df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("seek to time %lld us => sample at time %lld us, " 3159abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber "sync sample at time %lld us", 3160abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber seekTimeUs, 3161abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber sampleTime * 1000000ll / mTimescale, 3162abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber syncSampleTime * 1000000ll / mTimescale); 3163abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif 3164abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3165abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mCurrentSampleIndex = syncSampleIndex; 316620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mBuffer != NULL) { 316720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 316820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 316920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 317020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 317120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // fall through 317220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 317320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3174c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset; 31750024245e134467d120b40099da16c467dc365e76Andreas Huber size_t size; 31764678a6dc5f09008481524949a9667af5a6190374Andreas Huber uint32_t cts; 31778bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber bool isSyncSample; 3178dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber bool newBuffer = false; 3179dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (mBuffer == NULL) { 3180dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber newBuffer = true; 318120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3182c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber status_t err = 3183c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber mSampleTable->getMetaDataForSample( 31844678a6dc5f09008481524949a9667af5a6190374Andreas Huber mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample); 318520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3186dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (err != OK) { 3187dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return err; 3188dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3189dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3190dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber err = mGroup->acquire_buffer(&mBuffer); 3191c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 3192dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (err != OK) { 3193ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber CHECK(mBuffer == NULL); 3194dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return err; 3195dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 31960024245e134467d120b40099da16c467dc365e76Andreas Huber } 319720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3198dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (!mIsAVC || mWantsNALFragments) { 3199dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (newBuffer) { 3200dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber ssize_t num_bytes_read = 320134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 3202dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3203dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (num_bytes_read < (ssize_t)size) { 3204dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->release(); 3205dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 3206dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3207dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return ERROR_IO; 3208dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3209dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 32107b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(mBuffer != NULL); 3211dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->set_range(0, size); 3212dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->meta_data()->clear(); 321348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mBuffer->meta_data()->setInt64( 32144678a6dc5f09008481524949a9667af5a6190374Andreas Huber kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 3215abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3216abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (targetSampleTimeUs >= 0) { 3217abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mBuffer->meta_data()->setInt64( 3218abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber kKeyTargetTime, targetSampleTimeUs); 3219abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3220abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 32218bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber if (isSyncSample) { 32228bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 32238bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 32248bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 3225dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber ++mCurrentSampleIndex; 3226dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3227dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3228dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (!mIsAVC) { 3229dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber *out = mBuffer; 3230dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 3231dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3232dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return OK; 3233dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3234dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3235dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // Each NAL unit is split up into its constituent fragments and 3236dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // each one of them returned in its own buffer. 3237dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 32386064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(mBuffer->range_length() >= mNALLengthSize); 3239dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3240dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber const uint8_t *src = 3241dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 3242dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 32436064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t nal_size = parseNALSize(src); 3244e8a084958c27327b0aca749f69095605d2a21309Andreas Huber if (mBuffer->range_length() < mNALLengthSize + nal_size) { 324529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("incomplete NAL unit."); 3246e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 3247e8a084958c27327b0aca749f69095605d2a21309Andreas Huber mBuffer->release(); 3248e8a084958c27327b0aca749f69095605d2a21309Andreas Huber mBuffer = NULL; 3249e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 3250e8a084958c27327b0aca749f69095605d2a21309Andreas Huber return ERROR_MALFORMED; 3251e8a084958c27327b0aca749f69095605d2a21309Andreas Huber } 3252dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3253dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber MediaBuffer *clone = mBuffer->clone(); 32547b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(clone != NULL); 32556064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 3256dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 32577b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(mBuffer != NULL); 3258dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->set_range( 32596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mBuffer->range_offset() + mNALLengthSize + nal_size, 32606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mBuffer->range_length() - mNALLengthSize - nal_size); 3261dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3262dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (mBuffer->range_length() == 0) { 3263dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->release(); 3264dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 3265dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3266dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3267dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber *out = clone; 3268dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3269dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return OK; 3270dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } else { 3271dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // Whole NAL units are returned but each fragment is prefixed by 3272dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // the start code (0x00 00 00 01). 3273dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang ssize_t num_bytes_read = 0; 3274dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t drm = 0; 3275dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0); 3276dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (usesDRM) { 3277dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang num_bytes_read = 3278dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size); 3279dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else { 3280dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size); 3281dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 328220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 328320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (num_bytes_read < (ssize_t)size) { 328420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 328520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 328620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3287dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return ERROR_IO; 328820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 328920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3290dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (usesDRM) { 3291dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK(mBuffer != NULL); 3292dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer->set_range(0, size); 32936064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 3294dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else { 3295dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t *dstData = (uint8_t *)mBuffer->data(); 3296dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size_t srcOffset = 0; 3297dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size_t dstOffset = 0; 3298e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 3299dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (srcOffset < size) { 330067a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar bool isMalFormed = !isInRange(0u, size, srcOffset, mNALLengthSize); 330134fe252c89e33572d01fea981b58d7b115e76164James Dong size_t nalLength = 0; 330234fe252c89e33572d01fea981b58d7b115e76164James Dong if (!isMalFormed) { 330334fe252c89e33572d01fea981b58d7b115e76164James Dong nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 330434fe252c89e33572d01fea981b58d7b115e76164James Dong srcOffset += mNALLengthSize; 330567a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar isMalFormed = !isInRange(0u, size, srcOffset, nalLength); 330634fe252c89e33572d01fea981b58d7b115e76164James Dong } 3307e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 330834fe252c89e33572d01fea981b58d7b115e76164James Dong if (isMalFormed) { 330929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Video is malformed"); 3310dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer->release(); 3311dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer = NULL; 3312dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 3313dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 3314dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 3315dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (nalLength == 0) { 3316dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang continue; 3317dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 3318dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3319dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK(dstOffset + 4 <= mBuffer->size()); 3320dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3321dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 0; 3322dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 0; 3323dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 0; 3324dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 1; 3325dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 3326dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang srcOffset += nalLength; 3327dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstOffset += nalLength; 3328dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 3329dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK_EQ(srcOffset, size); 3330dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK(mBuffer != NULL); 3331dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer->set_range(0, dstOffset); 3332dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3333dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 333420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->meta_data()->clear(); 333548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mBuffer->meta_data()->setInt64( 33364678a6dc5f09008481524949a9667af5a6190374Andreas Huber kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 3337abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3338abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (targetSampleTimeUs >= 0) { 3339abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mBuffer->meta_data()->setInt64( 3340abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber kKeyTargetTime, targetSampleTimeUs); 3341abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3342abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 33438bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber if (isSyncSample) { 33448bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 33458bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 33468bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 334720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++mCurrentSampleIndex; 334820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 334920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *out = mBuffer; 335020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 335120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 335220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 335320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 335420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 335520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 335605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead( 335705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MediaBuffer **out, const ReadOptions *options) { 335805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 335905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Source::fragmentedRead"); 336005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 336105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mStarted); 336205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 336305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = NULL; 336405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 336505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t targetSampleTimeUs = -1; 336605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 336705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t seekTimeUs; 336805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ReadOptions::SeekMode mode; 336905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (options && options->getSeekTo(&seekTimeUs, &mode)) { 337005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 337105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int numSidxEntries = mSegments.size(); 337205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (numSidxEntries != 0) { 337305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t totalTime = 0; 337405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t totalOffset = mFirstMoofOffset; 337505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen for (int i = 0; i < numSidxEntries; i++) { 337605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const SidxEntry *se = &mSegments[i]; 337705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (totalTime + se->mDurationUs > seekTimeUs) { 337805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // The requested time is somewhere in this segment 337905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((mode == ReadOptions::SEEK_NEXT_SYNC) || 338005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (mode == ReadOptions::SEEK_CLOSEST_SYNC && 338105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) { 338205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // requested next sync, or closest sync and it was closer to the end of 338305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // this segment 338405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalTime += se->mDurationUs; 338505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalOffset += se->mSize; 338605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 338705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 338805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 338905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalTime += se->mDurationUs; 339005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalOffset += se->mSize; 339105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 339205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentMoofOffset = totalOffset; 339305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSamples.clear(); 339405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSampleIndex = 0; 339505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(&totalOffset); 339605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentTime = totalTime * mTimescale / 1000000ll; 339705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 339805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 339905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer != NULL) { 340005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 340105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 340205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 340305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 340405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // fall through 340505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 340605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 340705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t offset = 0; 340805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t size; 340905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t cts = 0; 341005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool isSyncSample = false; 341105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool newBuffer = false; 341205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer == NULL) { 341305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen newBuffer = true; 341405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 341505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mCurrentSampleIndex >= mCurrentSamples.size()) { 341605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // move to next fragment 341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Sample lastSample = mCurrentSamples[mCurrentSamples.size() - 1]; 341805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t nextMoof = mNextMoofOffset; // lastSample.offset + lastSample.size; 341905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentMoofOffset = nextMoof; 342005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSamples.clear(); 342105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSampleIndex = 0; 342205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(&nextMoof); 342305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mCurrentSampleIndex >= mCurrentSamples.size()) { 342405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_END_OF_STREAM; 342505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 342605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 342705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 342805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex]; 342905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset = smpl->offset; 343005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size = smpl->size; 343105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen cts = mCurrentTime; 343205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentTime += smpl->duration; 343305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen isSyncSample = (mCurrentSampleIndex == 0); // XXX 343405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 343505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err = mGroup->acquire_buffer(&mBuffer); 343605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 343705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (err != OK) { 343805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer == NULL); 343905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("acquire_buffer returned %d", err); 344005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 344105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 344205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 344305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 344448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex]; 344548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen const sp<MetaData> bufmeta = mBuffer->meta_data(); 344648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->clear(); 344748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (smpl->encryptedsizes.size()) { 344848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // store clear/encrypted lengths in metadata 344948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyPlainSizes, 0, 345048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->clearsizes.array(), smpl->clearsizes.size() * 4); 345148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyEncryptedSizes, 0, 345248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4); 345348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size? 345448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize); 345548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setInt32(kKeyCryptoMode, mCryptoMode); 345648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16); 345748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 345848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 345905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mIsAVC || mWantsNALFragments) { 346005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (newBuffer) { 346105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ssize_t num_bytes_read = 346205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 346305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 346405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (num_bytes_read < (ssize_t)size) { 346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 346705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("i/o error"); 346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 347105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 347205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 347305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range(0, size); 347405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 347505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 347605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 347705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (targetSampleTimeUs >= 0) { 347805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 347905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTargetTime, targetSampleTimeUs); 348005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 348105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 348205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (isSyncSample) { 348305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 348405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 348505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 348605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ++mCurrentSampleIndex; 348705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 348805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 348905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mIsAVC) { 349005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = mBuffer; 349105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 349205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 349305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 349405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 349505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 349605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // Each NAL unit is split up into its constituent fragments and 349705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // each one of them returned in its own buffer. 349805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 349905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer->range_length() >= mNALLengthSize); 350005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 350105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const uint8_t *src = 350205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 350305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 350405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t nal_size = parseNALSize(src); 350505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer->range_length() < mNALLengthSize + nal_size) { 350605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGE("incomplete NAL unit."); 350705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 350805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 350905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 351005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 351105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 351205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 351305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 351405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MediaBuffer *clone = mBuffer->clone(); 351505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(clone != NULL); 351605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 351705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 351805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 351905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range( 352005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->range_offset() + mNALLengthSize + nal_size, 352105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->range_length() - mNALLengthSize - nal_size); 352205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 352305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer->range_length() == 0) { 352405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 352505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 352605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 352705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 352805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = clone; 352905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 353005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 353105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 353205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("whole NAL"); 353305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // Whole NAL units are returned but each fragment is prefixed by 353405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // the start code (0x00 00 00 01). 353505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ssize_t num_bytes_read = 0; 353605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t drm = 0; 353705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0); 353805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (usesDRM) { 353905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen num_bytes_read = 354005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size); 354105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 354205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size); 354305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 354405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 354505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (num_bytes_read < (ssize_t)size) { 354605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 354705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 354805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 354905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("i/o error"); 355005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 355105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 355205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 355305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (usesDRM) { 355405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 355505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range(0, size); 355605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 355705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 355805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint8_t *dstData = (uint8_t *)mBuffer->data(); 355905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t srcOffset = 0; 356005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t dstOffset = 0; 356105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 356205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen while (srcOffset < size) { 356367a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar bool isMalFormed = !isInRange(0u, size, srcOffset, mNALLengthSize); 356405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t nalLength = 0; 356505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!isMalFormed) { 356605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 356705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen srcOffset += mNALLengthSize; 356867a30ebfe785f7cd5ecfb0d2fb487e54536a3d48Lajos Molnar isMalFormed = !isInRange(0u, size, srcOffset, nalLength); 356905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 357005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 357105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (isMalFormed) { 357205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGE("Video is malformed"); 357305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 357405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 357505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 357605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 357705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 357805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (nalLength == 0) { 357905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen continue; 358005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 358105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 358205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(dstOffset + 4 <= mBuffer->size()); 358305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 358405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 0; 358505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 0; 358605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 0; 358705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 1; 358805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 358905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen srcOffset += nalLength; 359005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstOffset += nalLength; 359105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 359205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK_EQ(srcOffset, size); 359305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 359405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range(0, dstOffset); 359505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 359605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 359705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 359805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 359905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 360005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (targetSampleTimeUs >= 0) { 360105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 360205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTargetTime, targetSampleTimeUs); 360305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 360405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 360505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (isSyncSample) { 360605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 360705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 360805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 360905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ++mCurrentSampleIndex; 361005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 361105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = mBuffer; 361205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 361305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 361405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 361505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 361605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 361705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 3618bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix( 3619bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber const char *mimePrefix) { 3620bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber for (Track *track = mFirstTrack; track != NULL; track = track->next) { 3621bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber const char *mime; 3622bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber if (track->meta != NULL 3623bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber && track->meta->findCString(kKeyMIMEType, &mime) 3624bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) { 3625bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return track; 3626bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber } 3627bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber } 3628bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber 3629bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return NULL; 3630bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber} 3631bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber 36321b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4( 3633693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 363420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t header[8]; 363520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 363634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber ssize_t n = source->readAt(4, header, sizeof(header)); 363720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (n < (ssize_t)sizeof(header)) { 363820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return false; 363920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 364020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 364120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8) 3642b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8) 3643b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8) 36440dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8) 3645ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8) 3646983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) { 364718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 36485a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber *confidence = 0.4; 364920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 365020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return true; 365120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 365220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 365320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return false; 365420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 365520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36561b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) { 36571b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber static const uint32_t kCompatibleBrands[] = { 36581b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('i', 's', 'o', 'm'), 36591b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('i', 's', 'o', '2'), 36601b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('a', 'v', 'c', '1'), 36611b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('3', 'g', 'p', '4'), 36621b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('m', 'p', '4', '1'), 36631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('m', 'p', '4', '2'), 36644cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong 36654cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong // Won't promise that the following file types can be played. 36664cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong // Just give these file types a chance. 36674cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong FOURCC('q', 't', ' ', ' '), // Apple's QuickTime 36684cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong FOURCC('M', 'S', 'N', 'V'), // Sony's PSP 366958fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber 367058fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber FOURCC('3', 'g', '2', 'a'), // 3GPP2 367158fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber FOURCC('3', 'g', '2', 'b'), 36721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber }; 36731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 36741b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber for (size_t i = 0; 36751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]); 36761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber ++i) { 36771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (kCompatibleBrands[i] == fourcc) { 36781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 36791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 36801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 36811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 36821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 36831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 36841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 36851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable 36861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present. 3687a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends 3688a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of 3689a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata. 36901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4( 3691a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 3692a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber sp<AMessage> *meta) { 3693a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // We scan up to 128 bytes to identify this file as an MP4. 3694a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber static const off64_t kMaxScanOffset = 128ll; 36951b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3696a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t offset = 0ll; 3697a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber bool foundGoodFileType = false; 3698a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t moovAtomEndOffset = -1ll; 3699a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber bool done = false; 37001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3701a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber while (!done && offset < kMaxScanOffset) { 3702a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t hdr[2]; 3703a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (source->readAt(offset, hdr, 8) < 8) { 3704a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3705a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3706a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3707a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint64_t chunkSize = ntohl(hdr[0]); 3708a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t chunkType = ntohl(hdr[1]); 3709a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t chunkDataOffset = offset + 8; 3710a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3711a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (chunkSize == 1) { 3712a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (source->readAt(offset + 8, &chunkSize, 8) < 8) { 37131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 37141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 37151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3716a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber chunkSize = ntoh64(chunkSize); 3717a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber chunkDataOffset += 8; 3718a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3719a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (chunkSize < 16) { 3720a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // The smallest valid chunk is 16 bytes long in this case. 3721a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3722a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3723a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } else if (chunkSize < 8) { 3724a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // The smallest valid chunk is 8 bytes long. 3725a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3726a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3727a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3728a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t chunkDataSize = offset + chunkSize - chunkDataOffset; 3729a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 373005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen char chunkstring[5]; 373105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MakeFourCCString(chunkType, chunkstring); 373205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("saw chunk type %s, size %lld @ %lld", chunkstring, chunkSize, offset); 3733a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber switch (chunkType) { 3734a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber case FOURCC('f', 't', 'y', 'p'): 3735a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber { 3736a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (chunkDataSize < 8) { 3737a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3738a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3739a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3740a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4; 3741a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber for (size_t i = 0; i < numCompatibleBrands + 2; ++i) { 3742a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (i == 1) { 3743a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // Skip this index, it refers to the minorVersion, 3744a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // not a brand. 3745a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber continue; 3746a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3747a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3748a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t brand; 3749a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (source->readAt( 3750a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber chunkDataOffset + 4 * i, &brand, 4) < 4) { 3751a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3752a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3753a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3754a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber brand = ntohl(brand); 3755a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3756a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (isCompatibleBrand(brand)) { 3757a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber foundGoodFileType = true; 3758a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber break; 3759a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3760a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3761a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3762a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (!foundGoodFileType) { 3763a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 3764a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3765a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 37661b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber break; 37671b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 3768a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3769a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber case FOURCC('m', 'o', 'o', 'v'): 3770a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber { 3771a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber moovAtomEndOffset = offset + chunkSize; 3772a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3773a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber done = true; 3774a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber break; 3775a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3776a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3777a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber default: 3778a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber break; 37791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 3780a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3781a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber offset += chunkSize; 37821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 37831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3784a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (!foundGoodFileType) { 37851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 37861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 37871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 37881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 37895a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber *confidence = 0.4f; 37901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 3791a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (moovAtomEndOffset >= 0) { 3792a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber *meta = new AMessage; 3793a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber (*meta)->setInt64("meta-data-size", moovAtomEndOffset); 3794a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 3795456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber ALOGV("found metadata size: %lld", moovAtomEndOffset); 3796a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 3797a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 37981b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 37991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 38001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 38011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4( 38025a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 3803a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber sp<AMessage> *meta) { 3804a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (BetterSniffMPEG4(source, mimeType, confidence, meta)) { 38051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 38061b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 38071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 38081b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (LegacySniffMPEG4(source, mimeType, confidence)) { 38095ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Identified supported mpeg4 through LegacySniffMPEG4."); 38101b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 38111b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 38121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 38131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 38141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 38151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 381620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 3817