MPEG4Extractor.cpp revision c570778430a22b5488cae72982cf9fb8033dbda3
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" 1989e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber 2020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h> 21a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <inttypes.h> 2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdint.h> 2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdlib.h> 2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <string.h> 2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 26a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include <utils/Log.h> 27a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn 28a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include "include/MPEG4Extractor.h" 29a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include "include/SampleTable.h" 30a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn#include "include/ESDS.h" 31a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn 32aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke#include <media/stagefright/foundation/ABitReader.h> 33d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson#include <media/stagefright/foundation/ABuffer.h> 34ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#include <media/stagefright/foundation/ADebug.h> 35a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber#include <media/stagefright/foundation/AMessage.h> 36bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar#include <media/stagefright/foundation/AUtils.h> 3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h> 3918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h> 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 44fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé#include <byteswap.h> 45328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé#include "include/ID3.h" 46fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 4720111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 4820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource { 5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Caller retains ownership of both "dataSource" and "sampleTable". 52942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen MPEG4Source(const sp<MPEG4Extractor> &owner, 53942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen const sp<MetaData> &format, 54693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &dataSource, 5548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int32_t timeScale, 5605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const sp<SampleTable> &sampleTable, 5705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<SidxEntry> &sidx, 58c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen const Trex *trex, 5905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t firstMoofOffset); 6020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual status_t start(MetaData *params = NULL); 6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual status_t stop(); 6320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual sp<MetaData> getFormat(); 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 6605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL); 6705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL); 6820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 69693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected: 70693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber virtual ~MPEG4Source(); 71693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 7220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 737b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex mLock; 747b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 75942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen // keep the MPEG4Extractor around, since we're referencing its data 76942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen sp<MPEG4Extractor> mOwner; 7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mFormat; 78693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<DataSource> mDataSource; 7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t mTimescale; 80693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<SampleTable> mSampleTable; 8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t mCurrentSampleIndex; 8205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mCurrentFragmentIndex; 8305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<SidxEntry> &mSegments; 84c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen const Trex *mTrex; 8505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t mFirstMoofOffset; 8605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t mCurrentMoofOffset; 8705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t mNextMoofOffset; 8805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mCurrentTime; 8905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t mLastParsedTrackId; 9005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t mTrackId; 9120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 92ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int32_t mCryptoMode; // passed in from extractor 93ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int32_t mDefaultIVSize; // passed in from extractor 94ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t mCryptoKey[16]; // passed in from extractor 95ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentAuxInfoType; 96ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentAuxInfoTypeParameter; 9748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen int32_t mCurrentDefaultSampleInfoSize; 98ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentSampleInfoCount; 99ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentSampleInfoAllocSize; 100ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t* mCurrentSampleInfoSizes; 101ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentSampleInfoOffsetCount; 102ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t mCurrentSampleInfoOffsetsAllocSize; 103ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint64_t* mCurrentSampleInfoOffsets; 104ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 10520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool mIsAVC; 1063b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar bool mIsHEVC; 1076064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t mNALLengthSize; 1086064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 10920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool mStarted; 11020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBufferGroup *mGroup; 11220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 11320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *mBuffer; 11420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber bool mWantsNALFragments; 11620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1170024245e134467d120b40099da16c467dc365e76Andreas Huber uint8_t *mSrcBuffer; 1180024245e134467d120b40099da16c467dc365e76Andreas Huber 1196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t parseNALSize(const uint8_t *data) const; 12005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t parseChunk(off64_t *offset); 12105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t parseTrackFragmentHeader(off64_t offset, off64_t size); 12205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t parseTrackFragmentRun(off64_t offset, off64_t size); 123ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size); 124ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size); 12505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 12605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen struct TrackFragmentHeaderInfo { 12705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen enum Flags { 12805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kBaseDataOffsetPresent = 0x01, 12905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleDescriptionIndexPresent = 0x02, 13005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDefaultSampleDurationPresent = 0x08, 13105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDefaultSampleSizePresent = 0x10, 13205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDefaultSampleFlagsPresent = 0x20, 13305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDurationIsEmpty = 0x10000, 13405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 13505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 13605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mTrackID; 13705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mFlags; 13805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t mBaseDataOffset; 13905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mSampleDescriptionIndex; 14005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mDefaultSampleDuration; 14105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mDefaultSampleSize; 14205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t mDefaultSampleFlags; 14305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 14405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t mDataOffset; 14505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 14605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen TrackFragmentHeaderInfo mTrackFragmentHeaderInfo; 14705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 14805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen struct Sample { 14905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t offset; 15005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t size; 15105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t duration; 152c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen int32_t compositionOffset; 153ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t iv[16]; 154ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen Vector<size_t> clearsizes; 155ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen Vector<size_t> encryptedsizes; 15605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 15705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<Sample> mCurrentSamples; 1586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 15920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Source(const MPEG4Source &); 16020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Source &operator=(const MPEG4Source &); 16120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 16220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests 16450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding 16550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource. 16650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track, 16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e. 16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track. 16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource { 17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber MPEG4DataSource(const sp<DataSource> &source); 17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual status_t initCheck() const; 174c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong virtual ssize_t readAt(off64_t offset, void *data, size_t size); 175c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong virtual status_t getSize(off64_t *size); 17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual uint32_t flags(); 17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 178c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong status_t setCachedRange(off64_t offset, size_t size); 17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected: 18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual ~MPEG4DataSource(); 18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate: 18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber Mutex mLock; 18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber sp<DataSource> mSource; 187c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t mCachedOffset; 18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber size_t mCachedSize; 18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber uint8_t *mCache; 19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber void clearCache(); 19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber MPEG4DataSource(const MPEG4DataSource &); 19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber MPEG4DataSource &operator=(const MPEG4DataSource &); 19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}; 19650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 19750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source) 19850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber : mSource(source), 19950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedOffset(0), 20050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedSize(0), 20150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCache(NULL) { 20250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 20350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 20450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() { 20550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber clearCache(); 20650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 20750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 20850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() { 20950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (mCache) { 21050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber free(mCache); 21150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCache = NULL; 21250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 21350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 21450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedOffset = 0; 21550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedSize = 0; 21650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 21750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 21850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const { 21950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->initCheck(); 22050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 22150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 222c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) { 22350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber Mutex::Autolock autoLock(mLock); 22450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 225bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar if (isInRange(mCachedOffset, mCachedSize, offset, size)) { 22650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber memcpy(data, &mCache[offset - mCachedOffset], size); 22750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return size; 22850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 22950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 23050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->readAt(offset, data, size); 23150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 23250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 233c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::getSize(off64_t *size) { 23450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->getSize(size); 23550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 23650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 23750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() { 23850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->flags(); 23950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 24050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 241c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) { 24250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber Mutex::Autolock autoLock(mLock); 24350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 24450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber clearCache(); 24550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 24650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCache = (uint8_t *)malloc(size); 24750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 24850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (mCache == NULL) { 24950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return -ENOMEM; 25050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 25150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 25250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedOffset = offset; 25350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedSize = size; 25450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 25550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize); 25650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 25750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (err < (ssize_t)size) { 25850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber clearCache(); 25950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 26050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return ERROR_IO; 26150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 26250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 26350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return OK; 26450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 26550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 26650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber//////////////////////////////////////////////////////////////////////////////// 26750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) { 26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *data = (const uint8_t *)_data; 27020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t offset = 0; 27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (offset < size) { 272377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT printf("0x%04zx ", offset); 27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = size - offset; 27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (n > 16) { 27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber n = 16; 27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (size_t i = 0; i < 16; ++i) { 28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (i == 8) { 28120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf(" "); 28220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 28320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 28420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (offset + i < size) { 28520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("%02x ", data[offset + i]); 28620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 28720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf(" "); 28820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 28920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 29020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf(" "); 29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 29320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (size_t i = 0; i < n; ++i) { 29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (isprint(data[offset + i])) { 29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("%c", data[offset + i]); 29620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("."); 29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 29920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("\n"); 30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber offset += 16; 30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 30620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 30718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) { 30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber switch (fourcc) { 30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'a'): 31018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_AUDIO_AAC; 31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 31318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_AUDIO_AMR_NB; 31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 315371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber case FOURCC('s', 'a', 'w', 'b'): 31618291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_AUDIO_AMR_WB; 317371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber 31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'v'): 31918291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_VIDEO_MPEG4; 32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', '2', '6', '3'): 322e071b055cee301d71335519601474c62b10af411James Dong case FOURCC('h', '2', '6', '3'): 323e071b055cee301d71335519601474c62b10af411James Dong case FOURCC('H', '2', '6', '3'): 32418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_VIDEO_H263; 32520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 32620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', '1'): 32718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_VIDEO_AVC; 32820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3293b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar case FOURCC('h', 'v', 'c', '1'): 3303b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar case FOURCC('h', 'e', 'v', '1'): 3313b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar return MEDIA_MIMETYPE_VIDEO_HEVC; 33220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber default: 333dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(!"should not be here."); 33420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 33520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 33620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 33720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 33848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic bool AdjustChannelsAndRate(uint32_t fourcc, uint32_t *channels, uint32_t *rate) { 33948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, FourCC2MIME(fourcc))) { 34048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // AMR NB audio is always mono, 8kHz 34148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen *channels = 1; 34248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen *rate = 8000; 34348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return true; 34448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, FourCC2MIME(fourcc))) { 34548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // AMR WB audio is always mono, 16kHz 34648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen *channels = 1; 34748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen *rate = 16000; 34848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return true; 34948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 35048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return false; 35148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen} 35248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 353693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source) 354c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen : mMoofOffset(0), 35505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mDataSource(source), 356bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber mInitCheck(NO_INIT), 3577be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber mHasVideo(false), 358fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen mHeaderTimescale(0), 35920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFirstTrack(NULL), 36072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mLastTrack(NULL), 361dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mFileMetaData(new MetaData), 362dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mFirstSINF(NULL), 363dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mIsDrm(false) { 36420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 36520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() { 36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (track) { 36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *next = track->next; 37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete track; 37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = next; 37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFirstTrack = mLastTrack = NULL; 375dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 376dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *sinf = mFirstSINF; 377dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (sinf) { 378dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *next = sinf->next; 3798da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen delete[] sinf->IPMPData; 380dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang delete sinf; 381dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf = next; 382dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 383dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mFirstSINF = NULL; 384ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 385ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mPssh.size(); i++) { 386ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen delete [] mPssh[i].data; 387ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 38820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 38920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 39005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenuint32_t MPEG4Extractor::flags() const { 39105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return CAN_PAUSE | 39205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ((mMoofOffset == 0 || mSidxEntries.size() != 0) ? 39305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0); 39405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 39505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 3967be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() { 3977be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber status_t err; 3987be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber if ((err = readMetaData()) != OK) { 39972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return new MetaData; 4007be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber } 4017be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 40272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return mFileMetaData; 4037be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber} 4047be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 405693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() { 40620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 40720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 408ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("MPEG4Extractor::countTracks: no tracks"); 409693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return 0; 41020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 41120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 412693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber size_t n = 0; 41320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 41420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (track) { 415693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber ++n; 41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 41820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 419a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("MPEG4Extractor::countTracks: %zu tracks", n); 420693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return n; 42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4237e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData( 4247e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber size_t index, uint32_t flags) { 42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 42620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (index > 0) { 43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (track == NULL) { 43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber --index; 43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 440371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber if (track == NULL) { 441371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber return NULL; 442371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber } 443371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber 4447e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber if ((flags & kIncludeExtensiveMetaData) 4457e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber && !track->includes_expensive_metadata) { 4467e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber track->includes_expensive_metadata = true; 4477e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 4487e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber const char *mime; 4497e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 4507e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber if (!strncasecmp("video/", mime, 6)) { 45105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mMoofOffset > 0) { 45205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t duration; 45305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (track->meta->findInt64(kKeyDuration, &duration)) { 45405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // nothing fancy, just pick a frame near 1/4th of the duration 45505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen track->meta->setInt64( 45605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyThumbnailTime, duration / 4); 45705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 45805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 45905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleIndex; 46005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleTime; 46105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK 46205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen && track->sampleTable->getMetaDataForSample( 46305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleIndex, NULL /* offset */, NULL /* size */, 46405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen &sampleTime) == OK) { 46505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen track->meta->setInt64( 46605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyThumbnailTime, 46705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ((int64_t)sampleTime * 1000000) / track->timescale); 46805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 4697e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 4707e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 4717e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 4727e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 47320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return track->meta; 47420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 47520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 47648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) { 47748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[0] = x >> 24; 47848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[1] = (x >> 16) & 0xff; 47948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[2] = (x >> 8) & 0xff; 48048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[3] = x & 0xff; 48148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen s[4] = '\0'; 48248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen} 48348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() { 485bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber if (mInitCheck != NO_INIT) { 486bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return mInitCheck; 48720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 48820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 489c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset = 0; 49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 49105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen while (true) { 492a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen off64_t orig_offset = offset; 49305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen err = parseChunk(&offset, 0); 494a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen 4954ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar if (err != OK && err != UNKNOWN_ERROR) { 4964ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar break; 4974ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar } else if (offset <= orig_offset) { 498a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen // only continue parsing if the offset was advanced, 499a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen // otherwise we might end up in an infinite loop 500a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen ALOGE("did not advance: 0x%lld->0x%lld", orig_offset, offset); 501a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen err = ERROR_MALFORMED; 502a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen break; 503a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen } else if (err == OK) { 50405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen continue; 50505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 5064ff2a0dbb178c4ea652f30aa4f1d3deb9fdbc832Lajos Molnar 50705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t hdr[2]; 50805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mDataSource->readAt(offset, hdr, 8) < 8) { 50905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 51005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 51105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t chunk_type = ntohl(hdr[1]); 5123f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen if (chunk_type == FOURCC('m', 'o', 'o', 'f')) { 51305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // store the offset of the first segment 51405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mMoofOffset = offset; 5153f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen } else if (chunk_type != FOURCC('m', 'd', 'a', 't')) { 5163f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen // keep parsing until we get to the data 5173f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen continue; 51805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 51905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 52020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 5217be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 522bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber if (mInitCheck == OK) { 52372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mHasVideo) { 524bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber mFileMetaData->setCString( 525bc8b5faec8a0a9ad7c8d94945e7b000d63f0afe6Andreas Huber kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4); 52672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 52772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyMIMEType, "audio/mp4"); 52872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 529bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber } else { 530bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber mInitCheck = err; 53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 533bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber CHECK_NE(err, (status_t)NO_INIT); 534ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 535ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // copy pssh data into file metadata 536ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int psshsize = 0; 537ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mPssh.size(); i++) { 538ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen psshsize += 20 + mPssh[i].datalen; 539ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 540ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (psshsize) { 541ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen char *buf = (char*)malloc(psshsize); 542ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen char *ptr = buf; 543ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mPssh.size(); i++) { 544ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memcpy(ptr, mPssh[i].uuid, 20); // uuid + length 545ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memcpy(ptr + 20, mPssh[i].data, mPssh[i].datalen); 546ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ptr += (20 + mPssh[i].datalen); 547ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 548ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mFileMetaData->setData(kKeyPssh, 'pssh', buf, psshsize); 549ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen free(buf); 550ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 551bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return mInitCheck; 55220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 55320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 554dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) { 555dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mFirstSINF == NULL) { 556dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return NULL; 557dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 558dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 559dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *sinf = mFirstSINF; 560dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (sinf && (trackID != sinf->trackID)) { 561dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf = sinf->next; 562dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 563dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 564dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (sinf == NULL) { 565dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return NULL; 566dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 567dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 568dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang *len = sinf->len; 569dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return sinf->IPMPData; 570dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang} 571dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 572dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear. 57356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic int32_t readSize(off64_t offset, 574dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang const sp<DataSource> DataSource, uint8_t *numOfBytes) { 575dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint32_t size = 0; 576dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t data; 577dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang bool moreData = true; 578dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang *numOfBytes = 0; 579dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 580dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (moreData) { 581dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (DataSource->readAt(offset, &data, 1) < 1) { 582dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return -1; 583dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 584dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang offset ++; 585dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang moreData = (data >= 128) ? true : false; 586dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size = (size << 7) | (data & 0x7f); // Take last 7 bits 587dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang (*numOfBytes) ++; 588dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 589dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 590dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return size; 591dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang} 592dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 59384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Extractor::parseDrmSINF( 59484333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber off64_t * /* offset */, off64_t data_offset) { 595dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t updateIdTag; 596dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) { 597dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 598dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 599dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 600dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 601dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) { 602dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 603dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 604dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 605dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t numOfBytes; 606dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t size = readSize(data_offset, mDataSource, &numOfBytes); 607dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (size < 0) { 608dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 609dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 610dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t classSize = size; 611dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += numOfBytes; 612dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 613dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while(size >= 11 ) { 614dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t descriptorTag; 615dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) { 616dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 617dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 618dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 619dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 620dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) { 621dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 622dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 623dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 624dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t buffer[8]; 625dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang //ObjectDescriptorID and ObjectDescriptor url flag 626dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, buffer, 2) < 2) { 627dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 628dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 629dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += 2; 630dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 631dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if ((buffer[1] >> 5) & 0x0001) { //url flag is set 632dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 633dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 634dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 635dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, buffer, 8) < 8) { 636dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 637dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 638dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += 8; 639dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 640dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1]) 641dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) { 642dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 643dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 644dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 645dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *sinf = new SINF; 646dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->trackID = U16_AT(&buffer[3]); 647dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->IPMPDescriptorID = buffer[7]; 648dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->next = mFirstSINF; 649dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mFirstSINF = sinf; 650dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 651dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size -= (8 + 2 + 1); 652dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 653dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 654dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (size != 0) { 655dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 656dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 657dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 658dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) { 659dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 660dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 661dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 662dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 663dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) { 664dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 665dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 666dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 667dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size = readSize(data_offset, mDataSource, &numOfBytes); 668dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (size < 0) { 669dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 670dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 671dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang classSize = size; 672dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += numOfBytes; 673dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 674dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (size > 0) { 675dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t tag; 676dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t dataLen; 677dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &tag, 1) < 1) { 678dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 679dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 680dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 681dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 682dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) { 683dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t id; 684dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dataLen = readSize(data_offset, mDataSource, &numOfBytes); 685dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (dataLen < 0) { 686dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 687dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else if (dataLen < 4) { 688dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 689dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 690dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += numOfBytes; 691dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 692dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (mDataSource->readAt(data_offset, &id, 1) < 1) { 693dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 694dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 695dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset ++; 696dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 697dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang SINF *sinf = mFirstSINF; 698dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (sinf && (sinf->IPMPDescriptorID != id)) { 699dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf = sinf->next; 700dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 701dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (sinf == NULL) { 702dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 703dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 704dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang sinf->len = dataLen - 3; 7058da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen sinf->IPMPData = new (std::nothrow) char[sinf->len]; 7068da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen if (sinf->IPMPData == NULL) { 7078da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen return ERROR_MALFORMED; 7088da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen } 709f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara data_offset += 2; 710dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 711f7df9ab3187a3c02bffe1fba10d3fb95197e4a07Ichitaro Kohara if (mDataSource->readAt(data_offset, sinf->IPMPData, sinf->len) < sinf->len) { 712dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_IO; 713dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 714dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang data_offset += sinf->len; 715dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 716dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size -= (dataLen + numOfBytes + 1); 717dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 718dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 719dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 720dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (size != 0) { 721dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 722dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 723dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 724dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return UNKNOWN_ERROR; // Return a dummy error. 725dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang} 726dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 72772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder { 72872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder(Vector<uint32_t> *path, uint32_t chunkType) 72972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber : mPath(path) { 73072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mPath->push(chunkType); 73172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 73272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 73372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber ~PathAdder() { 73472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mPath->pop(); 73572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 73672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 73772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate: 73872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber Vector<uint32_t> *mPath; 73972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 74072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder(const PathAdder &); 74172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder &operator=(const PathAdder &); 74272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}; 74372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 74472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) { 74572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return path.size() >= 5 74672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[0] == FOURCC('m', 'o', 'o', 'v') 74772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[1] == FOURCC('u', 'd', 't', 'a') 74872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[2] == FOURCC('m', 'e', 't', 'a') 74972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[3] == FOURCC('i', 'l', 's', 't'); 75072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 75172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 75272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string. 75372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) { 75472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600); 75572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 75672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char tmp[32]; 75772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970)); 75872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 75972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber s->setTo(tmp); 76072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 76172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 762c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { 7635d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen ALOGV("entering parseChunk %lld/%d", *offset, depth); 76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t hdr[2]; 76534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt(*offset, hdr, 8) < 8) { 76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint64_t chunk_size = ntohl(hdr[0]); 76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t chunk_type = ntohl(hdr[1]); 770c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t data_offset = *offset + 8; 77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_size == 1) { 77334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { 77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_size = ntoh64(chunk_size); 77720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset += 8; 77871b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber 77971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber if (chunk_size < 16) { 78071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber // The smallest valid chunk is 16 bytes long in this case. 78171b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber return ERROR_MALFORMED; 78271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber } 783a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen } else if (chunk_size == 0) { 784a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen if (depth == 0) { 785a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen // atom extends to end of file 786a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen off64_t sourceSize; 787a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen if (mDataSource->getSize(&sourceSize) == OK) { 788a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen chunk_size = (sourceSize - *offset); 789a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen } else { 790a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen // XXX could we just pick a "sufficiently large" value here? 791a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen ALOGE("atom size is 0, and data source has no size"); 792a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen return ERROR_MALFORMED; 793a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen } 794a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen } else { 795a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen // not allowed for non-toplevel atoms, skip it 796a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen *offset += 4; 797a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen return OK; 798a91b538853e94191fbceab5f5050940dd6b96577Marco Nelissen } 79971b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber } else if (chunk_size < 8) { 80071b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber // The smallest valid chunk is 8 bytes long. 801a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGE("invalid chunk size: %" PRIu64, chunk_size); 80271b1a4e975dfb65660a0119b9d6bf6db77eca09eAndreas Huber return ERROR_MALFORMED; 80320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 80520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber char chunk[5]; 80620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MakeFourCCString(chunk_type, chunk); 80705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("chunk: %s @ %lld, %d", chunk, *offset, depth); 80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0 81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const char kWhitespace[] = " "; 81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth]; 812a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn printf("%sfound chunk '%s' of size %" PRIu64 "\n", indent, chunk, chunk_size); 81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber char buffer[256]; 815ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber size_t n = chunk_size; 816ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber if (n > sizeof(buffer)) { 817ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber n = sizeof(buffer); 818ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber } 819ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber if (mDataSource->readAt(*offset, buffer, n) 820ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber < (ssize_t)n) { 821ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber return ERROR_IO; 82220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 823ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber 824ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber hexdump(buffer, n); 82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif 82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 82772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder autoAdder(&mPath, chunk_type); 82872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 829c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t chunk_data_size = *offset + chunk_size - data_offset; 83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 83172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (chunk_type != FOURCC('c', 'p', 'r', 't') 832515e855eae78aa495da58356486aaa666cb57fd1James Dong && chunk_type != FOURCC('c', 'o', 'v', 'r') 83372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && mPath.size() == 5 && underMetaDataPath(mPath)) { 834c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 83572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset = data_offset; 83672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber while (*offset < stop_offset) { 83772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseChunk(offset, depth + 1); 83872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 83972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 84072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 84172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 842bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 843bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 844bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 845bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 84672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 84772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return OK; 84872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 84972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber switch(chunk_type) { 85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'o', 'o', 'v'): 85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'r', 'a', 'k'): 85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'd', 'i', 'a'): 85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'i', 'n', 'f'): 85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('d', 'i', 'n', 'f'): 85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'b', 'l'): 85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'v', 'e', 'x'): 85820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'o', 'o', 'f'): 85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'r', 'a', 'f'): 86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'f', 'r', 'a'): 86172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('u', 'd', 't', 'a'): 86272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('i', 'l', 's', 't'): 863ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'i', 'n', 'f'): 864ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'c', 'h', 'i'): 8650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen case FOURCC('e', 'd', 't', 's'): 86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 86750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (chunk_type == FOURCC('s', 't', 'b', 'l')) { 868a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("sampleTable chunk is %" PRIu64 " bytes long.", chunk_size); 86950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 870b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber if (mDataSource->flags() 871b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber & (DataSource::kWantsPrefetching 872b9d3038ec950665639e26acd51329ebc800e780dAndreas Huber | DataSource::kIsCachingDataSource)) { 87350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber sp<MPEG4DataSource> cachedSource = 87450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber new MPEG4DataSource(mDataSource); 87550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 87650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (cachedSource->setCachedRange(*offset, chunk_size) == OK) { 87750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mDataSource = cachedSource; 87850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 87950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 8801edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber 8811edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber mLastTrack->sampleTable = new SampleTable(mDataSource); 88250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 88350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 8846f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber bool isTrack = false; 885bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (chunk_type == FOURCC('t', 'r', 'a', 'k')) { 8866f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber isTrack = true; 8876f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 888bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber Track *track = new Track; 889bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->next = NULL; 890bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (mLastTrack) { 891bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber mLastTrack->next = track; 892bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else { 893bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber mFirstTrack = track; 894bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 895bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber mLastTrack = track; 896bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 897bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->meta = new MetaData; 898bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->includes_expensive_metadata = false; 8996f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber track->skipTrack = false; 900bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->timescale = 0; 901bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->meta->setCString(kKeyMIMEType, "application/octet-stream"); 902bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 903bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 904c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset; 90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 913bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 914bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 915bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 916bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 9176f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber if (isTrack) { 9186f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber if (mLastTrack->skipTrack) { 9196f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber Track *cur = mFirstTrack; 9206f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 9216f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber if (cur == mLastTrack) { 9226f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber delete cur; 9236f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber mFirstTrack = mLastTrack = NULL; 9246f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } else { 9256f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber while (cur && cur->next != mLastTrack) { 9266f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber cur = cur->next; 9276f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } 9286f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber cur->next = NULL; 9296f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber delete mLastTrack; 9306f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber mLastTrack = cur; 9316f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } 9326f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 9336f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber return OK; 9346f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } 9356f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 936bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber status_t err = verifyTrack(mLastTrack); 937bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 938bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (err != OK) { 939bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return err; 940bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 941bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { 942bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber mInitCheck = OK; 94320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 944dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (!mIsDrm) { 945dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return UNKNOWN_ERROR; // Return a dummy error. 946dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else { 947dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return OK; 948dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9530a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen case FOURCC('e', 'l', 's', 't'): 9540a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen { 9550517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 9560517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 9570a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen // See 14496-12 8.6.6 9580a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint8_t version; 9590a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (mDataSource->readAt(data_offset, &version, 1) < 1) { 9600a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9610a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9620a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9630a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint32_t entry_count; 9640a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (!mDataSource->getUInt32(data_offset + 4, &entry_count)) { 9650a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9660a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9670a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9680a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (entry_count != 1) { 9690a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen // we only support a single entry at the moment, for gapless playback 9700a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen ALOGW("ignoring edit list with %d entries", entry_count); 971fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen } else if (mHeaderTimescale == 0) { 972210efd48ed21ca0084d9440f9a1db7d9878f8094Marco Nelissen ALOGW("ignoring edit list because timescale is 0"); 9730a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } else { 9740a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen off64_t entriesoffset = data_offset + 8; 9750a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint64_t segment_duration; 9760a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t media_time; 9770a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 9780a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (version == 1) { 9790a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (!mDataSource->getUInt64(entriesoffset, &segment_duration) || 9800a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen !mDataSource->getUInt64(entriesoffset + 8, (uint64_t*)&media_time)) { 9810a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9820a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9830a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } else if (version == 0) { 9840a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen uint32_t sd; 9850a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int32_t mt; 9860a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (!mDataSource->getUInt32(entriesoffset, &sd) || 9870a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen !mDataSource->getUInt32(entriesoffset + 4, (uint32_t*)&mt)) { 9880a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9890a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9900a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen segment_duration = sd; 9910a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen media_time = mt; 9920a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } else { 9930a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen return ERROR_IO; 9940a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 9950a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 996fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen uint64_t halfscale = mHeaderTimescale / 2; 997fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen segment_duration = (segment_duration * 1000000 + halfscale)/ mHeaderTimescale; 998fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen media_time = (media_time * 1000000 + halfscale) / mHeaderTimescale; 9990a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 10000a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t duration; 10010a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int32_t samplerate; 10020a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen if (mLastTrack->meta->findInt64(kKeyDuration, &duration) && 10030a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen mLastTrack->meta->findInt32(kKeySampleRate, &samplerate)) { 10040a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 10050a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t delay = (media_time * samplerate + 500000) / 1000000; 10060a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen mLastTrack->meta->setInt32(kKeyEncoderDelay, delay); 10070a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 10080a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t paddingus = duration - (segment_duration + media_time); 1009465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen if (paddingus < 0) { 1010465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen // track duration from media header (which is what kKeyDuration is) might 1011465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen // be slightly shorter than the segment duration, which would make the 1012465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen // padding negative. Clamp to zero. 1013465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen paddingus = 0; 1014465127fa3dfba81d8ad2a164ba6036478f71c8a6Marco Nelissen } 10150a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen int64_t paddingsamples = (paddingus * samplerate + 500000) / 1000000; 10160a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen mLastTrack->meta->setInt32(kKeyEncoderPadding, paddingsamples); 10170a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 10180a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 10190a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen break; 10200a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen } 10210a69bd281c76bf777ddb51d0c6c08519634b192dMarco Nelissen 1022ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('f', 'r', 'm', 'a'): 1023ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen { 10240517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 10250517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 102648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t original_fourcc; 1027ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset, &original_fourcc, 4) < 4) { 1028ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1029ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1030ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen original_fourcc = ntohl(original_fourcc); 1031ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("read original format: %d", original_fourcc); 1032ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(original_fourcc)); 103348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t num_channels = 0; 103448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t sample_rate = 0; 103548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (AdjustChannelsAndRate(original_fourcc, &num_channels, &sample_rate)) { 103648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 103748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 103848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 1039ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 1040ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1041ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1042ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('t', 'e', 'n', 'c'): 1043ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen { 10440517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 10450517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 1046ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (chunk_size < 32) { 1047ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1048ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1049ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1050ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // tenc box contains 1 byte version, 3 byte flags, 3 byte default algorithm id, one byte 1051ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // default IV size, 16 bytes default KeyID 1052ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // (ISO 23001-7) 1053ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen char buf[4]; 1054ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(buf, 0, 4); 1055ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 4, buf + 1, 3) < 3) { 1056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1058ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t defaultAlgorithmId = ntohl(*((int32_t*)buf)); 1059ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (defaultAlgorithmId > 1) { 1060ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // only 0 (clear) and 1 (AES-128) are valid 1061ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1062ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1063ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1064ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(buf, 0, 4); 1065ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 7, buf + 3, 1) < 1) { 1066ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1067ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1068ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t defaultIVSize = ntohl(*((int32_t*)buf)); 1069ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1070ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if ((defaultAlgorithmId == 0 && defaultIVSize != 0) || 1071ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen (defaultAlgorithmId != 0 && defaultIVSize == 0)) { 1072ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // only unencrypted data must have 0 IV size 1073ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1074ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } else if (defaultIVSize != 0 && 1075ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen defaultIVSize != 8 && 1076ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen defaultIVSize != 16) { 1077ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // only supported sizes are 0, 8 and 16 1078ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1079ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1080ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1081ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t defaultKeyId[16]; 1082ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1083ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 8, &defaultKeyId, 16) < 16) { 1084ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1085ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1086ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1087ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setInt32(kKeyCryptoMode, defaultAlgorithmId); 1088ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setInt32(kKeyCryptoDefaultIVSize, defaultIVSize); 1089ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setData(kKeyCryptoKey, 'tenc', defaultKeyId, 16); 1090ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 1091ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1092ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 109320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'k', 'h', 'd'): 109420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 10950517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 10960517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 1097ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber status_t err; 1098ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) { 1099ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return err; 110020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 110120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 110220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 110320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 110420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1105ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('p', 's', 's', 'h'): 1106ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen { 11070517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 11080517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 1109ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen PsshInfo pssh; 1110ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1111ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 4, &pssh.uuid, 16) < 16) { 1112ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1113ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1114ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1115ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t psshdatalen = 0; 1116ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 20, &psshdatalen, 4) < 4) { 1117ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1118ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1119ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen pssh.datalen = ntohl(psshdatalen); 1120ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("pssh data size: %d", pssh.datalen); 1121ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (pssh.datalen + 20 > chunk_size) { 1122ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // pssh data length exceeds size of containing box 1123ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 1124ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1125ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 11268da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen pssh.data = new (std::nothrow) uint8_t[pssh.datalen]; 11278da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen if (pssh.data == NULL) { 11288da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen return ERROR_MALFORMED; 11298da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen } 1130ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("allocated pssh @ %p", pssh.data); 1131ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ssize_t requested = (ssize_t) pssh.datalen; 1132ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(data_offset + 24, pssh.data, requested) < requested) { 1133ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 1134ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1135ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mPssh.push_back(pssh); 1136ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 1137ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 1138ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 1139ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 114020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'd', 'h', 'd'): 114120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 11420517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 11430517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 114420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 4) { 114520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 114620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 114720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 114820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t version; 114934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 115020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, &version, sizeof(version)) 115120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(version)) { 115220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 115320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 115420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1155c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t timescale_offset; 115620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 115720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (version == 1) { 115820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset = data_offset + 4 + 16; 115920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else if (version == 0) { 116020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset = data_offset + 4 + 8; 116120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 116220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 116320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 116420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 116520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t timescale; 116634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 116720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset, ×cale, sizeof(timescale)) 116820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(timescale)) { 116920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 117020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 117120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 117220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->timescale = ntohl(timescale); 117320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1174c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen // 14496-12 says all ones means indeterminate, but some files seem to use 1175c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen // 0 instead. We treat both the same. 117605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t duration = 0; 117720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (version == 1) { 117834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 117920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset + 4, &duration, sizeof(duration)) 118020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(duration)) { 118120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 118220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1183c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (duration != -1) { 1184c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen duration = ntoh64(duration); 1185c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 118620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 118705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t duration32; 118834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 118920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset + 4, &duration32, sizeof(duration32)) 119020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(duration32)) { 119120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 119220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 119305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (duration32 != 0xffffffff) { 119405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen duration = ntohl(duration32); 119505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1197c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (duration != 0) { 1198c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen mLastTrack->meta->setInt64( 1199c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen kKeyDuration, (duration * 1000000) / mLastTrack->timescale); 1200c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 12027a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang uint8_t lang[2]; 12037a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang off64_t lang_offset; 12047a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang if (version == 1) { 12057a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_offset = timescale_offset + 4 + 8; 12067a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } else if (version == 0) { 12077a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_offset = timescale_offset + 4 + 4; 12087a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } else { 12097a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang return ERROR_IO; 12107a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 12117a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 12127a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang if (mDataSource->readAt(lang_offset, &lang, sizeof(lang)) 12137a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang < (ssize_t)sizeof(lang)) { 12147a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang return ERROR_IO; 12157a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 12167a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 12177a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // To get the ISO-639-2/T three character language code 12187a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // 1 bit pad followed by 3 5-bits characters. Each character 12197a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang // is packed as the difference between its ASCII value and 0x60. 12207a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang char lang_code[4]; 12217a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60; 12227a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60; 12237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[2] = (lang[1] & 0x1f) + 0x60; 12247a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang lang_code[3] = '\0'; 12257a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 12267a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang mLastTrack->meta->setCString( 12277a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang kKeyMediaLanguage, lang_code); 12287a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 122920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 123020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 123120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'd'): 123320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 123420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 8) { 123520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 123620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 123720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 123820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[8]; 1239c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (chunk_data_size < (off64_t)sizeof(buffer)) { 1240bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1241bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 1242bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 124334769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 124420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, 8) < 8) { 124520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 124620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 124720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 124820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (U32_AT(buffer) != 0) { 124920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Should be version 0, flags 0. 125020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 125120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 125220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 125320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t entry_count = U32_AT(&buffer[4]); 125420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 125520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (entry_count > 1) { 12563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // For 3GPP timed text, there could be multiple tx3g boxes contain 12573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // multiple text display formats. These formats will be used to 12583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // display the timed text. 1259ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // For encrypted files, there may also be more than one entry. 12603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang const char *mime; 12613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 1262ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP) && 1263ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen strcasecmp(mime, "application/octet-stream")) { 12643b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // For now we only support a single type of media per track. 12653b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang mLastTrack->skipTrack = true; 12663b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang *offset += chunk_size; 12673b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang break; 12683b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 126920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1270c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 127120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + 8; 127220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (uint32_t i = 0; i < entry_count; ++i) { 127320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 127420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 127520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 127620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 127720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1278bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1279bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1280bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1281bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 128220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 128320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 128420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 128520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'a'): 128648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen case FOURCC('e', 'n', 'c', 'a'): 128720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 1288371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber case FOURCC('s', 'a', 'w', 'b'): 128920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 129020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[8 + 20]; 129120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 129220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Basic AudioSampleEntry size. 129320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 129420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 129520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 129634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 129720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 129820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 129920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 130020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 130120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 130248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t num_channels = U16_AT(&buffer[16]); 130320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 130481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint16_t sample_size = U16_AT(&buffer[18]); 130581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint32_t sample_rate = U32_AT(&buffer[24]) >> 16; 130681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 130748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (chunk_type != FOURCC('e', 'n', 'c', 'a')) { 130848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // if the chunk type is enca, we'll get the type from the sinf/frma box later 130948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 131048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate); 131120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 131248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen ALOGV("*** coding='%s' %d channels, size %d, rate %d\n", 131381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber chunk, num_channels, sample_size, sample_rate); 131420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 131520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 131620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1317c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 131820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + sizeof(buffer); 131920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 132020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 132120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 132220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 132320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 132420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1325bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1326bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1327bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1328bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 132920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 133020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 133120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'v'): 1333ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('e', 'n', 'c', 'v'): 133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', '2', '6', '3'): 1335e071b055cee301d71335519601474c62b10af411James Dong case FOURCC('H', '2', '6', '3'): 1336e071b055cee301d71335519601474c62b10af411James Dong case FOURCC('h', '2', '6', '3'): 133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', '1'): 13383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar case FOURCC('h', 'v', 'c', '1'): 13393b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar case FOURCC('h', 'e', 'v', '1'): 134020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 13417be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber mHasVideo = true; 13427be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 134320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[78]; 134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Basic VideoSampleEntry size. 134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 134720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 134934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 135120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 135220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 135520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t width = U16_AT(&buffer[6 + 18]); 135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t height = U16_AT(&buffer[6 + 20]); 135720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1358ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // The video sample is not standard-compliant if it has invalid dimension. 1359a6256238d9015c42129fe43791968768fe501efaJames Dong // Use some default width and height value, and 1360a6256238d9015c42129fe43791968768fe501efaJames Dong // let the decoder figure out the actual width and height (and thus 1361a6256238d9015c42129fe43791968768fe501efaJames Dong // be prepared for INFO_FOMRAT_CHANGED event). 1362a6256238d9015c42129fe43791968768fe501efaJames Dong if (width == 0) width = 352; 1363a6256238d9015c42129fe43791968768fe501efaJames Dong if (height == 0) height = 288; 1364a6256238d9015c42129fe43791968768fe501efaJames Dong 1365134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber // printf("*** coding='%s' width=%d height=%d\n", 1366134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber // chunk, width, height); 136720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1368ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (chunk_type != FOURCC('e', 'n', 'c', 'v')) { 1369ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // if the chunk type is encv, we'll get the type from the sinf/frma box later 1370ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 1371ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 137220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyWidth, width); 137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyHeight, height); 137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1375c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + sizeof(buffer); 137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 137820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 138120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 138220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 1383bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1384bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1385bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1386bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 138720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 138920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 139020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'c', 'o'): 139120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('c', 'o', '6', '4'): 139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setChunkOffsetParams( 139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_type, data_offset, chunk_data_size); 139620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 13970517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 13980517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 139920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 140020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 140120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 140220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 140320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 140420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'c'): 140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 140920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSampleToChunkParams( 141020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 141120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14120517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 14130517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 141420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 141820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 141920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 142020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 142120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'z'): 142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'z', '2'): 142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 142420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 142520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSampleSizeParams( 142620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_type, data_offset, chunk_data_size); 142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14280517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 14290517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 143120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 143220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1434738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber size_t max_size; 143549110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber err = mLastTrack->sampleTable->getMaxSampleSize(&max_size); 143649110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber 143749110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber if (err != OK) { 143849110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber return err; 143949110ce0ed95918c85eebe6e09e900b905b37e23Andreas Huber } 1440738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber 144105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (max_size != 0) { 144205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // Assume that a given buffer only contains at most 10 chunks, 144305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // each chunk originally prefixed with a 2 byte length will 144405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion, 144505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // and thus will grow by 2 bytes per chunk. 144605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2); 144705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 144805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // No size was specified. Pick a conservatively large size. 144905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t width, height; 1450f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar if (!mLastTrack->meta->findInt32(kKeyWidth, &width) || 1451f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar !mLastTrack->meta->findInt32(kKeyHeight, &height)) { 145205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGE("No width or height, assuming worst case 1080p"); 1453f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar width = 1920; 1454f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar height = 1080; 145505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 1456f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar 14574256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen const char *mime; 14584256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 1459f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar if (!strcmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 1460f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar // AVC requires compression ratio of at least 2, and uses 1461f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar // macroblocks 1462f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar max_size = ((width + 15) / 16) * ((height + 15) / 16) * 192; 1463f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar } else { 1464f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar // For all other formats there is no minimum compression 1465f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar // ratio. Use compression ratio of 1. 1466f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar max_size = width * height * 3 / 2; 146705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 1468f40cde132d14a260f4f7e08ae2bf29d8c55848aeLajos Molnar mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size); 146905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 1470113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong 14714256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen // NOTE: setting another piece of metadata invalidates any pointers (such as the 14724256c970ad90bc555eccfd585048669bb69bca1cMarco Nelissen // mimetype) previously obtained, so don't cache them. 1473113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong const char *mime; 1474113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 1475113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong // Calculate average frame rate. 1476113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong if (!strncasecmp("video/", mime, 6)) { 1477113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong size_t nSamples = mLastTrack->sampleTable->countSamples(); 1478113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong int64_t durationUs; 1479113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) { 1480113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong if (durationUs > 0) { 1481113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong int32_t frameRate = (nSamples * 1000000LL + 1482113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong (durationUs >> 1)) / durationUs; 1483113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong mLastTrack->meta->setInt32(kKeyFrameRate, frameRate); 1484113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong } 1485113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong } 1486113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong } 1487113a95462d2018c62b9e6bc86e7f643ff46f29cfJames Dong 148820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 149020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 149120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 't', 's'): 149220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 14930517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 14940517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 149520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 149620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setTimeToSampleParams( 149720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 149820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 149920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 150020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 150220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 150320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 150420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 150520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15064931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber case FOURCC('c', 't', 't', 's'): 15074931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber { 15080517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 15090517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 15104931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber status_t err = 15114931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber mLastTrack->sampleTable->setCompositionTimeToSampleParams( 15124931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber data_offset, chunk_data_size); 15134931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 15144931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber if (err != OK) { 15154931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber return err; 15164931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 15174931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 15184931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber break; 15194931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber } 15204931bb5259d10c1fa01e7405fb7aaef58a8ffb22Andreas Huber 152120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 's'): 152220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 15230517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 15240517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 152520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 152620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSyncSampleParams( 152720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 152820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 152920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 153020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 153120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 153220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 153320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 153420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 153520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 15364948818cb91176df74c972ac27b2f392b5d148bcJames Dong // @xyz 15374948818cb91176df74c972ac27b2f392b5d148bcJames Dong case FOURCC('\xA9', 'x', 'y', 'z'): 15384948818cb91176df74c972ac27b2f392b5d148bcJames Dong { 15390517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 15400517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 15414948818cb91176df74c972ac27b2f392b5d148bcJames Dong // Best case the total data length inside "@xyz" box 15424948818cb91176df74c972ac27b2f392b5d148bcJames Dong // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/", 15434948818cb91176df74c972ac27b2f392b5d148bcJames Dong // where "\x00\x04" is the text string length with value = 4, 15444948818cb91176df74c972ac27b2f392b5d148bcJames Dong // "\0x15\xc7" is the language code = en, and "0+0" is a 15454948818cb91176df74c972ac27b2f392b5d148bcJames Dong // location (string) value with longitude = 0 and latitude = 0. 15464948818cb91176df74c972ac27b2f392b5d148bcJames Dong if (chunk_data_size < 8) { 15474948818cb91176df74c972ac27b2f392b5d148bcJames Dong return ERROR_MALFORMED; 15484948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 15494948818cb91176df74c972ac27b2f392b5d148bcJames Dong 15504948818cb91176df74c972ac27b2f392b5d148bcJames Dong // Worst case the location string length would be 18, 15514948818cb91176df74c972ac27b2f392b5d148bcJames Dong // for instance +90.0000-180.0000, without the trailing "/" and 15524948818cb91176df74c972ac27b2f392b5d148bcJames Dong // the string length + language code. 15534948818cb91176df74c972ac27b2f392b5d148bcJames Dong char buffer[18]; 15544948818cb91176df74c972ac27b2f392b5d148bcJames Dong 15554948818cb91176df74c972ac27b2f392b5d148bcJames Dong // Substracting 5 from the data size is because the text string length + 15564948818cb91176df74c972ac27b2f392b5d148bcJames Dong // language code takes 4 bytes, and the trailing slash "/" takes 1 byte. 15574948818cb91176df74c972ac27b2f392b5d148bcJames Dong off64_t location_length = chunk_data_size - 5; 15584948818cb91176df74c972ac27b2f392b5d148bcJames Dong if (location_length >= (off64_t) sizeof(buffer)) { 15594948818cb91176df74c972ac27b2f392b5d148bcJames Dong return ERROR_MALFORMED; 15604948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 15614948818cb91176df74c972ac27b2f392b5d148bcJames Dong 15624948818cb91176df74c972ac27b2f392b5d148bcJames Dong if (mDataSource->readAt( 15634948818cb91176df74c972ac27b2f392b5d148bcJames Dong data_offset + 4, buffer, location_length) < location_length) { 15644948818cb91176df74c972ac27b2f392b5d148bcJames Dong return ERROR_IO; 15654948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 15664948818cb91176df74c972ac27b2f392b5d148bcJames Dong 15674948818cb91176df74c972ac27b2f392b5d148bcJames Dong buffer[location_length] = '\0'; 15684948818cb91176df74c972ac27b2f392b5d148bcJames Dong mFileMetaData->setCString(kKeyLocation, buffer); 15694948818cb91176df74c972ac27b2f392b5d148bcJames Dong break; 15704948818cb91176df74c972ac27b2f392b5d148bcJames Dong } 15714948818cb91176df74c972ac27b2f392b5d148bcJames Dong 157220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('e', 's', 'd', 's'): 157320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 15740517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 15750517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 157620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 4) { 157720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 157820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 157920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 158020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[256]; 1581c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (chunk_data_size > (off64_t)sizeof(buffer)) { 158220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_BUFFER_TOO_SMALL; 158320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 158420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 158534769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 158620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 158720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 158920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 159020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (U32_AT(buffer) != 0) { 159120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Should be version 0, flags 0. 159220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 159320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 159420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 159520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setData( 159620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); 159720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1598ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (mPath.size() >= 2 1599ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) { 1600ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // Information from the ESDS must be relied on for proper 1601ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // setup of sample rate and channel count for MPEG4 Audio. 1602ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // The generic header appears to only contain generic 1603ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // information... 1604ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1605ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio( 1606ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber &buffer[4], chunk_data_size - 4); 1607ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1608ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (err != OK) { 1609ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return err; 1610ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1611ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1612ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 161320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 161420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 161520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 161620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', 'C'): 161720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 16180517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 16190517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 1620d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson sp<ABuffer> buffer = new ABuffer(chunk_data_size); 162120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 162234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 1623d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson data_offset, buffer->data(), chunk_data_size) < chunk_data_size) { 162420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 162520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 162620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 162720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setData( 1628d2f6b04578432fa4e27bacf860b78bf29a099b73Jan Olof Svensson kKeyAVCC, kTypeAVCC, buffer->data(), chunk_data_size); 162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 16323b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar case FOURCC('h', 'v', 'c', 'C'): 16333b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar { 16343b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar sp<ABuffer> buffer = new ABuffer(chunk_data_size); 16353b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar 16363b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar if (mDataSource->readAt( 16373b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar data_offset, buffer->data(), chunk_data_size) < chunk_data_size) { 16383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar return ERROR_IO; 16393b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar } 16403b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar 16413b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar mLastTrack->meta->setData( 16423b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar kKeyHVCC, kTypeHVCC, buffer->data(), chunk_data_size); 16433b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar 16443b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar *offset += chunk_size; 16453b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar break; 16463b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar } 164720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1648244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong case FOURCC('d', '2', '6', '3'): 1649244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong { 16500517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 165117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong /* 165217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * d263 contains a fixed 7 bytes part: 165317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * vendor - 4 bytes 165417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * version - 1 byte 165517e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * level - 1 byte 165617e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * profile - 1 byte 165717e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * optionally, "d263" box itself may contain a 16-byte 165817e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * bit rate box (bitr) 165917e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * average bit rate - 4 bytes 166017e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong * max bit rate - 4 bytes 166117e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong */ 166217e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong char buffer[23]; 166317e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong if (chunk_data_size != 7 && 166417e89b555a41aa591f1a01ecd51a7cb5a7bcfc0eJames Dong chunk_data_size != 23) { 166529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Incorrect D263 box size %lld", chunk_data_size); 1666244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong return ERROR_MALFORMED; 1667244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong } 1668244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 1669244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong if (mDataSource->readAt( 1670244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong data_offset, buffer, chunk_data_size) < chunk_data_size) { 1671244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong return ERROR_IO; 1672244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong } 1673244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 1674244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size); 1675244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 1676244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong break; 1677244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong } 1678244ba87d20aeb29c9cad727820fa1e803ec3643cJames Dong 167972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('m', 'e', 't', 'a'): 168072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 168172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint8_t buffer[4]; 1682c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (chunk_data_size < (off64_t)sizeof(buffer)) { 16830517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 1684bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1685bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 1686bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 168772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 168872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber data_offset, buffer, 4) < 4) { 16890517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 169072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 169172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 169272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 169372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (U32_AT(buffer) != 0) { 169472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber // Should be version 0, flags 0. 1695ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber 1696ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // If it's not, let's assume this is one of those 1697ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // apparently malformed chunks that don't have flags 1698ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // and completely different semantics than what's 1699ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // in the MPEG4 specs and skip it. 1700ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber *offset += chunk_size; 1701ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber return OK; 170272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 170372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1704c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t stop_offset = *offset + chunk_size; 170572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset = data_offset + sizeof(buffer); 170672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber while (*offset < stop_offset) { 170772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseChunk(offset, depth + 1); 170872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 170972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 171072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 171172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 1712bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1713bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1714bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1715bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 171672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 171772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 171872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 17195d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('m', 'e', 'a', 'n'): 17205d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('n', 'a', 'm', 'e'): 172172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('d', 'a', 't', 'a'): 172272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 17230517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 17240517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 172572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mPath.size() == 6 && underMetaDataPath(mPath)) { 1726fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé status_t err = parseITunesMetaData(data_offset, chunk_data_size); 172772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 172872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 172972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 173072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 173172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 173272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 173372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 173472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 173572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 173672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('m', 'v', 'h', 'd'): 173772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 17380517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 17390517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 1740c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (chunk_data_size < 32) { 174172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_MALFORMED; 174272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 174372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1744c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen uint8_t header[32]; 174572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 174672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber data_offset, header, sizeof(header)) 174772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber < (ssize_t)sizeof(header)) { 174872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 174972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 175072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1751fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen uint64_t creationTime; 1752c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen uint64_t duration = 0; 175372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (header[0] == 1) { 175472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber creationTime = U64_AT(&header[4]); 1755fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen mHeaderTimescale = U32_AT(&header[20]); 1756c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen duration = U64_AT(&header[24]); 1757c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (duration == 0xffffffffffffffff) { 1758c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen duration = 0; 1759c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1760bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (header[0] != 0) { 1761bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 176272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 176372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber creationTime = U32_AT(&header[4]); 1764fc80e9ec5582770cb5a7fef172af3b52625ecce7Marco Nelissen mHeaderTimescale = U32_AT(&header[12]); 1765c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen uint32_t d32 = U32_AT(&header[16]); 1766c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (d32 == 0xffffffff) { 1767c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen d32 = 0; 1768c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1769c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen duration = d32; 1770c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1771c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (duration != 0) { 1772c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale); 177372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 177472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 177572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber String8 s; 177672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber convertTimeToDate(creationTime, &s); 177772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 177872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyDate, s.string()); 177972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 178072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 178172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 178272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1783c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen case FOURCC('m', 'e', 'h', 'd'): 1784c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen { 1785c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen *offset += chunk_size; 1786c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen 1787c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (chunk_data_size < 8) { 1788c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen return ERROR_MALFORMED; 1789c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1790c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen 1791c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen uint8_t flags[4]; 1792c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (mDataSource->readAt( 1793c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen data_offset, flags, sizeof(flags)) 1794c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen < (ssize_t)sizeof(flags)) { 1795c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen return ERROR_IO; 1796c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1797c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen 1798c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen uint64_t duration = 0; 1799c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (flags[0] == 1) { 1800c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen // 64 bit 1801c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (chunk_data_size < 12) { 1802c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen return ERROR_MALFORMED; 1803c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1804c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen mDataSource->getUInt64(data_offset + 4, &duration); 1805c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (duration == 0xffffffffffffffff) { 1806c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen duration = 0; 1807c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1808c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } else if (flags[0] == 0) { 1809c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen // 32 bit 1810c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen uint32_t d32; 1811c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen mDataSource->getUInt32(data_offset + 4, &d32); 1812c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (d32 == 0xffffffff) { 1813c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen d32 = 0; 1814c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1815c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen duration = d32; 1816c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } else { 1817c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen return ERROR_MALFORMED; 1818c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1819c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen 1820c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (duration != 0) { 1821c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen mFileMetaData->setInt64(kKeyDuration, duration * 1000000 / mHeaderTimescale); 1822c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1823c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen 1824c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen break; 1825c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1826c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen 1827dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang case FOURCC('m', 'd', 'a', 't'): 1828dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang { 1829ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("mdat chunk, drm: %d", mIsDrm); 1830dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (!mIsDrm) { 1831dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang *offset += chunk_size; 1832dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang break; 1833dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1834dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 1835dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (chunk_size < 8) { 1836dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 1837dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1838dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 1839dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return parseDrmSINF(offset, data_offset); 1840dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 1841dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 18423b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang case FOURCC('h', 'd', 'l', 'r'): 18433b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang { 18440517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 18450517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 18463b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint32_t buffer; 18473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if (mDataSource->readAt( 18483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang data_offset + 8, &buffer, 4) < 4) { 18493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang return ERROR_IO; 18503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 18513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 18523b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint32_t type = ntohl(buffer); 18533b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang // For the 3GPP file format, the handler-type within the 'hdlr' box 1854e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang // shall be 'text'. We also want to support 'sbtl' handler type 1855e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang // for a practical reason as various MPEG4 containers use it. 1856e26dd87f87be5016777bf92e498a26d545d3926aInsun Kang if (type == FOURCC('t', 'e', 'x', 't') || type == FOURCC('s', 'b', 't', 'l')) { 18573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP); 18583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 18593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 18603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang break; 18613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 18623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 1863c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen case FOURCC('t', 'r', 'e', 'x'): 1864c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen { 1865c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen *offset += chunk_size; 1866c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen 1867c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (chunk_data_size < 24) { 1868c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen return ERROR_IO; 1869c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1870c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen uint32_t duration; 1871c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen Trex trex; 1872c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (!mDataSource->getUInt32(data_offset + 4, &trex.track_ID) || 1873c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen !mDataSource->getUInt32(data_offset + 8, &trex.default_sample_description_index) || 1874c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen !mDataSource->getUInt32(data_offset + 12, &trex.default_sample_duration) || 1875c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen !mDataSource->getUInt32(data_offset + 16, &trex.default_sample_size) || 1876c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen !mDataSource->getUInt32(data_offset + 20, &trex.default_sample_flags)) { 1877c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen return ERROR_IO; 1878c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1879c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen mTrex.add(trex); 1880c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen break; 1881c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 1882c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen 18837a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang case FOURCC('t', 'x', '3', 'g'): 18847a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang { 18853b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang uint32_t type; 18863b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang const void *data; 18873b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang size_t size = 0; 18883b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if (!mLastTrack->meta->findData( 18893b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang kKeyTextFormatData, &type, &data, &size)) { 18903b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang size = 0; 18913b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 18923b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 1893e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake if (SIZE_MAX - chunk_size <= size) { 1894e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake return ERROR_MALFORMED; 1895e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake } 1896e5f0966c76bd0a7e81e4205c8d8b55e6b34c833eJoshua J. Drake 18978da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen uint8_t *buffer = new (std::nothrow) uint8_t[size + chunk_size]; 18988da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen if (buffer == NULL) { 18998da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen return ERROR_MALFORMED; 19008da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen } 19013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 19023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if (size > 0) { 19033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang memcpy(buffer, data, size); 19043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 19053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 19063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size)) 19073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang < chunk_size) { 19083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang delete[] buffer; 19093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang buffer = NULL; 19103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 19110517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen // advance read pointer so we don't end up reading this again 19120517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 19133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang return ERROR_IO; 19143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang } 19153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 19163b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang mLastTrack->meta->setData( 19173b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang kKeyTextFormatData, 0, buffer, size + chunk_size); 19183b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang 19193b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang delete[] buffer; 19207a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 19217a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang *offset += chunk_size; 19227a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang break; 19237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang } 19247a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang 1925515e855eae78aa495da58356486aaa666cb57fd1James Dong case FOURCC('c', 'o', 'v', 'r'): 1926515e855eae78aa495da58356486aaa666cb57fd1James Dong { 19270517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 19280517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 1929515e855eae78aa495da58356486aaa666cb57fd1James Dong if (mFileMetaData != NULL) { 19303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("chunk_data_size = %lld and data_offset = %lld", 1931515e855eae78aa495da58356486aaa666cb57fd1James Dong chunk_data_size, data_offset); 193205ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake 193305ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake if (chunk_data_size >= SIZE_MAX - 1) { 193405ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake return ERROR_MALFORMED; 193505ddc499b9d50c90f552ed1333110f28a1406e7cJoshua J. Drake } 19361552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1); 1937515e855eae78aa495da58356486aaa666cb57fd1James Dong if (mDataSource->readAt( 19381552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) { 1939515e855eae78aa495da58356486aaa666cb57fd1James Dong return ERROR_IO; 1940515e855eae78aa495da58356486aaa666cb57fd1James Dong } 1941515e855eae78aa495da58356486aaa666cb57fd1James Dong const int kSkipBytesOfDataBox = 16; 19424a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake if (chunk_data_size <= kSkipBytesOfDataBox) { 19434a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake return ERROR_MALFORMED; 19444a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake } 19454a492bf2ac47b9844d2527e1fcdf0064c3d8d52eJoshua J. Drake 1946515e855eae78aa495da58356486aaa666cb57fd1James Dong mFileMetaData->setData( 1947515e855eae78aa495da58356486aaa666cb57fd1James Dong kKeyAlbumArt, MetaData::TYPE_NONE, 19481552217cca4d949bba4b2cf6194a0936bbb10fa4Jens Gulin buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox); 1949515e855eae78aa495da58356486aaa666cb57fd1James Dong } 1950515e855eae78aa495da58356486aaa666cb57fd1James Dong 1951515e855eae78aa495da58356486aaa666cb57fd1James Dong break; 1952515e855eae78aa495da58356486aaa666cb57fd1James Dong } 1953515e855eae78aa495da58356486aaa666cb57fd1James Dong 1954fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé case FOURCC('t', 'i', 't', 'l'): 1955fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé case FOURCC('p', 'e', 'r', 'f'): 1956fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé case FOURCC('a', 'u', 't', 'h'): 1957fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé case FOURCC('g', 'n', 'r', 'e'): 1958fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé case FOURCC('a', 'l', 'b', 'm'): 1959fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé case FOURCC('y', 'r', 'r', 'c'): 1960fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé { 19610517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 19620517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 1963fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé status_t err = parse3GPPMetaData(data_offset, chunk_data_size, depth); 1964fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 1965fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé if (err != OK) { 1966fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé return err; 1967fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 1968fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 1969fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé break; 1970fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 1971fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 1972328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé case FOURCC('I', 'D', '3', '2'): 1973328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé { 19740517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen *offset += chunk_size; 19750517e0b6e4a86f34388631416dd6b3b4fcb91ff8Marco Nelissen 1976328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé if (chunk_data_size < 6) { 1977328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé return ERROR_MALFORMED; 1978328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé } 1979328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé 1980328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé parseID3v2MetaData(data_offset + 6); 1981328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé 1982328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé break; 1983328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé } 1984328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé 19855d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('-', '-', '-', '-'): 19865d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen { 19875d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentMean.clear(); 19885d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentName.clear(); 19895d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentData.clear(); 19905d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen *offset += chunk_size; 19915d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 19925d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 19935d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen 199405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('s', 'i', 'd', 'x'): 199505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen { 199605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseSegmentIndex(data_offset, chunk_data_size); 199705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 199805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return UNKNOWN_ERROR; // stop parsing after sidx 199905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 200005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 200120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber default: 200220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 200320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 200420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 200520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 200620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 200720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 200820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 200920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 201020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 201105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) { 201205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Extractor::parseSegmentIndex"); 201305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 201405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 12) { 201505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 201605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 201705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 201805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t flags; 201905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &flags)) { 202005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 202105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 202205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 202305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t version = flags >> 24; 202405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen flags &= 0xffffff; 202505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 202605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("sidx version %d", version); 202705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 202805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t referenceId; 202905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, &referenceId)) { 203005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 203105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 203205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 203305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t timeScale; 203405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 8, &timeScale)) { 203505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 203605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 203705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("sidx refid/timescale: %d/%d", referenceId, timeScale); 203805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 203905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t earliestPresentationTime; 204005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t firstOffset; 204105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 204205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 12; 204305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 12; 204405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 204505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (version == 0) { 204605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 204705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 204805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 204905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t tmp; 205005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 205105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 205205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 205305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen earliestPresentationTime = tmp; 205405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, &tmp)) { 205505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 205605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 205705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen firstOffset = tmp; 205805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 205905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 206005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 206105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 16) { 206205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 206305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 206405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt64(offset, &earliestPresentationTime)) { 206505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 206605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 206705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt64(offset + 8, &firstOffset)) { 206805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 206905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 207005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 16; 207105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 16; 207205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 2073a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("sidx pres/off: %" PRIu64 "/%" PRIu64, earliestPresentationTime, firstOffset); 207405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 207505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 207605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 207705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 207805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 207905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint16_t referenceCount; 208005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt16(offset + 2, &referenceCount)) { 208105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 208205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 208305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 208405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 208505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("refcount: %d", referenceCount); 208605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 208705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < referenceCount * 12) { 208805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 208905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 209005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 209105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t total_duration = 0; 209205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen for (unsigned int i = 0; i < referenceCount; i++) { 209305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t d1, d2, d3; 209405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 209505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &d1) || // size 209605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen !mDataSource->getUInt32(offset + 4, &d2) || // duration 209705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen !mDataSource->getUInt32(offset + 8, &d3)) { // flags 209805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 209905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 210005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 210105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (d1 & 0x80000000) { 210205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGW("sub-sidx boxes not supported yet"); 210305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 210405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool sap = d3 & 0x80000000; 21053f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen uint32_t saptype = (d3 >> 28) & 7; 21063f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen if (!sap || (saptype != 1 && saptype != 2)) { 21073f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen // type 1 and 2 are sync samples 21083f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen ALOGW("not a stream access point, or unsupported type: %08x", d3); 210905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 211005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen total_duration += d2; 211105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 12; 211205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV(" item %d, %08x %08x %08x", i, d1, d2, d3); 211305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen SidxEntry se; 211405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen se.mSize = d1 & 0x7fffffff; 211505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen se.mDurationUs = 1000000LL * d2 / timeScale; 211605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSidxEntries.add(se); 211705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 211805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 2119c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen uint64_t sidxDuration = total_duration * 1000000 / timeScale; 212005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 212105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t metaDuration; 212205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mLastTrack->meta->findInt64(kKeyDuration, &metaDuration) || metaDuration == 0) { 2123c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen mLastTrack->meta->setInt64(kKeyDuration, sidxDuration); 212405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 212505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 212605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 212705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 212805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 212905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 2130ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader( 2131c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t data_offset, off64_t data_size) { 2132ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (data_size < 4) { 2133ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_MALFORMED; 2134ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 2135ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2136ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint8_t version; 2137ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (mDataSource->readAt(data_offset, &version, 1) < 1) { 2138ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_IO; 2139ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 2140ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2141ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber size_t dynSize = (version == 1) ? 36 : 24; 2142ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2143ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint8_t buffer[36 + 60]; 2144ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2145c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong if (data_size != (off64_t)dynSize + 60) { 2146ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_MALFORMED; 2147ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 2148ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2149ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (mDataSource->readAt( 2150ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber data_offset, buffer, data_size) < (ssize_t)data_size) { 2151ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return ERROR_IO; 2152ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 2153ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2154ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint64_t ctime, mtime, duration; 2155ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t id; 2156ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2157ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (version == 1) { 2158ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber ctime = U64_AT(&buffer[4]); 2159ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mtime = U64_AT(&buffer[12]); 2160ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber id = U32_AT(&buffer[20]); 2161ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber duration = U64_AT(&buffer[28]); 216204022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen } else if (version == 0) { 2163ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber ctime = U32_AT(&buffer[4]); 2164ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mtime = U32_AT(&buffer[8]); 2165ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber id = U32_AT(&buffer[12]); 2166ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber duration = U32_AT(&buffer[20]); 216704022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen } else { 216804022b34d2b97938b0926ab62e6c283418da3bbaMarco Nelissen return ERROR_UNSUPPORTED; 2169ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 2170ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2171ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mLastTrack->meta->setInt32(kKeyTrackID, id); 2172ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2173ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber size_t matrixOffset = dynSize + 16; 2174ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a00 = U32_AT(&buffer[matrixOffset]); 2175ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a01 = U32_AT(&buffer[matrixOffset + 4]); 2176ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t dx = U32_AT(&buffer[matrixOffset + 8]); 2177ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a10 = U32_AT(&buffer[matrixOffset + 12]); 2178ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t a11 = U32_AT(&buffer[matrixOffset + 16]); 2179ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber int32_t dy = U32_AT(&buffer[matrixOffset + 20]); 2180ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2181ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#if 0 2182df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("x' = %.2f * x + %.2f * y + %.2f", 2183ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f); 2184df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("y' = %.2f * x + %.2f * y + %.2f", 2185ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f); 2186ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber#endif 2187ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2188ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint32_t rotationDegrees; 2189ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2190ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber static const int32_t kFixedOne = 0x10000; 2191ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) { 2192ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber // Identity, no rotation 2193ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 0; 2194ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) { 2195ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 90; 2196ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) { 2197ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 270; 2198ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) { 2199ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 180; 2200ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } else { 22015ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("We only support 0,90,180,270 degree rotation matrices"); 2202ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber rotationDegrees = 0; 2203ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 2204ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2205ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber if (rotationDegrees != 0) { 2206ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees); 2207ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber } 2208ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2209b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong // Handle presentation display size, which could be different 2210b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong // from the image size indicated by kKeyWidth and kKeyHeight. 2211ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint32_t width = U32_AT(&buffer[dynSize + 52]); 2212ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber uint32_t height = U32_AT(&buffer[dynSize + 56]); 2213b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16); 2214b45c01c2b8588ff431b511151666a55a39f0a6aeJames Dong mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16); 2215ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2216ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber return OK; 2217ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber} 2218ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber 2219fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) { 2220c570778430a22b5488cae72982cf9fb8033dbda3Nick Kralevich if (size < 4 || size == SIZE_MAX) { 222172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_MALFORMED; 222272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 222372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 22248da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen uint8_t *buffer = new (std::nothrow) uint8_t[size + 1]; 22258da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen if (buffer == NULL) { 22268da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen return ERROR_MALFORMED; 22278da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen } 222872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 222972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber offset, buffer, size) != (ssize_t)size) { 223072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber delete[] buffer; 223172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer = NULL; 223272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 223372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 223472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 223572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 223672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint32_t flags = U32_AT(buffer); 223772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 223872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint32_t metadataKey = 0; 22395d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen char chunk[5]; 22405d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen MakeFourCCString(mPath[4], chunk); 22415d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen ALOGV("meta: %s @ %lld", chunk, offset); 224272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber switch (mPath[4]) { 224372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'a', 'l', 'b'): 224472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 224572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyAlbum; 224672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 224772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 224872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'A', 'R', 'T'): 224972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 225072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyArtist; 225172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 225272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 225366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen case FOURCC('a', 'A', 'R', 'T'): 225466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen { 225566ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen metadataKey = kKeyAlbumArtist; 225666ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen break; 225766ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen } 225872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'd', 'a', 'y'): 225972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 226072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyYear; 226172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 226272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 226372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'n', 'a', 'm'): 226472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 226572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyTitle; 226672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 226772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 226872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'w', 'r', 't'): 226972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 227072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyWriter; 227172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 227272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 227372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('c', 'o', 'v', 'r'): 227472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 227572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyAlbumArt; 227672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 227772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 227872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('g', 'n', 'r', 'e'): 227972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 228072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyGenre; 228172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 228272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 228326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen case FOURCC(0xa9, 'g', 'e', 'n'): 228426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen { 228526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen metadataKey = kKeyGenre; 228626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen break; 228726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 228811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen case FOURCC('c', 'p', 'i', 'l'): 228911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { 229011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen if (size == 9 && flags == 21) { 229111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen char tmp[16]; 229211f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen sprintf(tmp, "%d", 229311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen (int)buffer[size - 1]); 229411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen 229511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen mFileMetaData->setCString(kKeyCompilation, tmp); 229611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen } 229711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen break; 229811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen } 229972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('t', 'r', 'k', 'n'): 230072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 230172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (size == 16 && flags == 0) { 230272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char tmp[16]; 2303afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pTrack = (uint16_t*)&buffer[10]; 2304afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pTotalTracks = (uint16_t*)&buffer[12]; 2305afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik sprintf(tmp, "%d/%d", ntohs(*pTrack), ntohs(*pTotalTracks)); 230672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 230772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyCDTrackNumber, tmp); 230872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 230972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 231072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 231126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen case FOURCC('d', 'i', 's', 'k'): 231226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen { 2313afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik if ((size == 14 || size == 16) && flags == 0) { 231426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen char tmp[16]; 2315afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pDisc = (uint16_t*)&buffer[10]; 2316afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik uint16_t* pTotalDiscs = (uint16_t*)&buffer[12]; 2317afa28a823724a2f76e1a53b15358533388003666Andreas Lillvik sprintf(tmp, "%d/%d", ntohs(*pDisc), ntohs(*pTotalDiscs)); 231826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 231926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen mFileMetaData->setCString(kKeyDiscNumber, tmp); 232026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 232126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen break; 232226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 23235d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('-', '-', '-', '-'): 23245d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen { 23255d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen buffer[size] = '\0'; 23265d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen switch (mPath[5]) { 23275d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('m', 'e', 'a', 'n'): 23285d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentMean.setTo((const char *)buffer + 4); 23295d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 23305d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('n', 'a', 'm', 'e'): 23315d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentName.setTo((const char *)buffer + 4); 23325d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 23335d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen case FOURCC('d', 'a', 't', 'a'): 23345d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentData.setTo((const char *)buffer + 8); 23355d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 23365d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 23378c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman 23388c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // Once we have a set of mean/name/data info, go ahead and process 23398c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // it to see if its something we are interested in. Whether or not 23408c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // were are interested in the specific tag, make sure to clear out 23418c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // the set so we can be ready to process another tuple should one 23428c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman // show up later in the file. 23438c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman if ((mLastCommentMean.length() != 0) && 23448c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman (mLastCommentName.length() != 0) && 23458c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman (mLastCommentData.length() != 0)) { 23468c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman 23478c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman if (mLastCommentMean == "com.apple.iTunes" 23488c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman && mLastCommentName == "iTunSMPB") { 23498c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman int32_t delay, padding; 23508c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman if (sscanf(mLastCommentData, 23518c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman " %*x %x %x %*x", &delay, &padding) == 2) { 23528c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman mLastTrack->meta->setInt32(kKeyEncoderDelay, delay); 23538c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman mLastTrack->meta->setInt32(kKeyEncoderPadding, padding); 23548c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman } 23555d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 23568c7d147cca17961a71209c105a2676a552d3d69fJohn Grossman 23575d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentMean.clear(); 23585d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentName.clear(); 23595d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen mLastCommentData.clear(); 23605d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 23615d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen break; 23625d2f8ba30c24ea597d54468cda01c7ec5f6a0e66Marco Nelissen } 236326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 236472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber default: 236572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 236672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 236772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 2368328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé if (size >= 8 && metadataKey && !mFileMetaData->hasData(metadataKey)) { 236972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (metadataKey == kKeyAlbumArt) { 237072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setData( 237172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber kKeyAlbumArt, MetaData::TYPE_NONE, 237272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer + 8, size - 8); 237372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else if (metadataKey == kKeyGenre) { 237472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (flags == 0) { 237526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // uint8_t genre code, iTunes genre codes are 237626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // the standard id3 codes, except they start 237726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // at 1 instead of 0 (e.g. Pop is 14, not 13) 237826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // We use standard id3 numbering, so subtract 1. 237926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen int genrecode = (int)buffer[size - 1]; 238026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen genrecode--; 238126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen if (genrecode < 0) { 238226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen genrecode = 255; // reserved for 'unknown genre' 238326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 238472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char genre[10]; 238526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen sprintf(genre, "%d", genrecode); 238672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 238772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(metadataKey, genre); 238826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } else if (flags == 1) { 238926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // custom genre string 239026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen buffer[size] = '\0'; 239126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 239226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen mFileMetaData->setCString( 239326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen metadataKey, (const char *)buffer + 8); 239472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 239572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 239672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer[size] = '\0'; 239772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 239872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString( 239972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey, (const char *)buffer + 8); 240072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 240172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 240272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 240372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber delete[] buffer; 240472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer = NULL; 240572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 240672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return OK; 240772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 240872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 2409fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhéstatus_t MPEG4Extractor::parse3GPPMetaData(off64_t offset, size_t size, int depth) { 2410d89104a3d5a16298742110bff1d10b43d16fef7bJoshua J. Drake if (size < 4 || size == SIZE_MAX) { 2411fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé return ERROR_MALFORMED; 2412fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2413fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2414d89104a3d5a16298742110bff1d10b43d16fef7bJoshua J. Drake uint8_t *buffer = new (std::nothrow) uint8_t[size + 1]; 24158da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen if (buffer == NULL) { 24168da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen return ERROR_MALFORMED; 24178da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen } 2418fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé if (mDataSource->readAt( 2419fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé offset, buffer, size) != (ssize_t)size) { 2420fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé delete[] buffer; 2421fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé buffer = NULL; 2422fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2423fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé return ERROR_IO; 2424fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2425fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2426fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé uint32_t metadataKey = 0; 2427fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé switch (mPath[depth]) { 2428fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé case FOURCC('t', 'i', 't', 'l'): 2429fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé { 2430fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé metadataKey = kKeyTitle; 2431fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé break; 2432fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2433fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé case FOURCC('p', 'e', 'r', 'f'): 2434fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé { 2435fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé metadataKey = kKeyArtist; 2436fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé break; 2437fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2438fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé case FOURCC('a', 'u', 't', 'h'): 2439fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé { 2440fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé metadataKey = kKeyWriter; 2441fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé break; 2442fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2443fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé case FOURCC('g', 'n', 'r', 'e'): 2444fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé { 2445fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé metadataKey = kKeyGenre; 2446fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé break; 2447fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2448fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé case FOURCC('a', 'l', 'b', 'm'): 2449fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé { 2450fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé if (buffer[size - 1] != '\0') { 2451fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé char tmp[4]; 2452fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé sprintf(tmp, "%u", buffer[size - 1]); 2453fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2454fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé mFileMetaData->setCString(kKeyCDTrackNumber, tmp); 2455fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2456fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2457fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé metadataKey = kKeyAlbum; 2458fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé break; 2459fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2460fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé case FOURCC('y', 'r', 'r', 'c'): 2461fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé { 2462fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé char tmp[5]; 2463fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé uint16_t year = U16_AT(&buffer[4]); 2464fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2465fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé if (year < 10000) { 2466fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé sprintf(tmp, "%u", year); 2467fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2468fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé mFileMetaData->setCString(kKeyYear, tmp); 2469fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2470fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé break; 2471fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2472fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2473fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé default: 2474fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé break; 2475fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2476fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2477fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé if (metadataKey > 0) { 2478fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé bool isUTF8 = true; // Common case 2479fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé char16_t *framedata = NULL; 2480fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé int len16 = 0; // Number of UTF-16 characters 2481fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2482fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé // smallest possible valid UTF-16 string w BOM: 0xfe 0xff 0x00 0x00 24834d8ed149894eff1e21195a29d939f2ec389fe5d7Joshua J. Drake if (size < 6) { 24844d8ed149894eff1e21195a29d939f2ec389fe5d7Joshua J. Drake return ERROR_MALFORMED; 24854d8ed149894eff1e21195a29d939f2ec389fe5d7Joshua J. Drake } 24864d8ed149894eff1e21195a29d939f2ec389fe5d7Joshua J. Drake 2487fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé if (size - 6 >= 4) { 2488fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé len16 = ((size - 6) / 2) - 1; // don't include 0x0000 terminator 2489fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé framedata = (char16_t *)(buffer + 6); 2490fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé if (0xfffe == *framedata) { 2491fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé // endianness marker (BOM) doesn't match host endianness 2492fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé for (int i = 0; i < len16; i++) { 2493fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé framedata[i] = bswap_16(framedata[i]); 2494fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2495fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé // BOM is now swapped to 0xfeff, we will execute next block too 2496fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2497fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2498fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé if (0xfeff == *framedata) { 2499fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé // Remove the BOM 2500fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé framedata++; 2501fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé len16--; 2502fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé isUTF8 = false; 2503fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2504fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé // else normal non-zero-length UTF-8 string 2505fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé // we can't handle UTF-16 without BOM as there is no other 2506fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé // indication of encoding. 2507fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2508fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2509fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé if (isUTF8) { 2510d89104a3d5a16298742110bff1d10b43d16fef7bJoshua J. Drake buffer[size] = 0; 2511fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé mFileMetaData->setCString(metadataKey, (const char *)buffer + 6); 2512fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } else { 2513fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé // Convert from UTF-16 string to UTF-8 string. 2514fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé String8 tmpUTF8str(framedata, len16); 2515fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé mFileMetaData->setCString(metadataKey, tmpUTF8str.string()); 2516fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2517fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé } 2518fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2519fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé delete[] buffer; 2520fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé buffer = NULL; 2521fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2522fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé return OK; 2523fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé} 2524fbc9d2b9cda433d98c36acb842c4a91fdeeb75e0Oscar Rydhé 2525328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhévoid MPEG4Extractor::parseID3v2MetaData(off64_t offset) { 2526328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé ID3 id3(mDataSource, true /* ignorev1 */, offset); 2527328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé 2528328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé if (id3.isValid()) { 2529328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé struct Map { 2530328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé int key; 2531328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé const char *tag1; 2532328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé const char *tag2; 2533328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé }; 2534328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé static const Map kMap[] = { 2535328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé { kKeyAlbum, "TALB", "TAL" }, 2536328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé { kKeyArtist, "TPE1", "TP1" }, 2537328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé { kKeyAlbumArtist, "TPE2", "TP2" }, 2538328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé { kKeyComposer, "TCOM", "TCM" }, 2539328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé { kKeyGenre, "TCON", "TCO" }, 2540328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé { kKeyTitle, "TIT2", "TT2" }, 2541328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé { kKeyYear, "TYE", "TYER" }, 2542328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé { kKeyAuthor, "TXT", "TEXT" }, 2543328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé { kKeyCDTrackNumber, "TRK", "TRCK" }, 2544328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé { kKeyDiscNumber, "TPA", "TPOS" }, 2545328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé { kKeyCompilation, "TCP", "TCMP" }, 2546328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé }; 2547328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé static const size_t kNumMapEntries = sizeof(kMap) / sizeof(kMap[0]); 2548328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé 2549328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé for (size_t i = 0; i < kNumMapEntries; ++i) { 2550328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé if (!mFileMetaData->hasData(kMap[i].key)) { 2551328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé ID3::Iterator *it = new ID3::Iterator(id3, kMap[i].tag1); 2552328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé if (it->done()) { 2553328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé delete it; 2554328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé it = new ID3::Iterator(id3, kMap[i].tag2); 2555328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé } 2556328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé 2557328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé if (it->done()) { 2558328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé delete it; 2559328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé continue; 2560328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé } 2561328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé 2562328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé String8 s; 2563328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé it->getString(&s); 2564328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé delete it; 2565328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé 2566328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé mFileMetaData->setCString(kMap[i].key, s); 2567328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé } 2568328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé } 2569328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé 2570328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé size_t dataSize; 2571328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé String8 mime; 2572328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé const void *data = id3.getAlbumArt(&dataSize, &mime); 2573328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé 2574328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé if (data) { 2575328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé mFileMetaData->setData(kKeyAlbumArt, MetaData::TYPE_NONE, data, dataSize); 2576328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé mFileMetaData->setCString(kKeyAlbumArtMIME, mime.string()); 2577328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé } 2578328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé } 2579328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé} 2580328abde67f57c026ac44e927f9244c40832499c8Oscar Rydhé 2581693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) { 258220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 258320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 2584693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return NULL; 258520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 258620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 258720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 258820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (index > 0) { 258920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (track == NULL) { 2590693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return NULL; 259120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 259220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 259320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 259420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber --index; 259520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 259620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2597371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber if (track == NULL) { 2598371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber return NULL; 2599371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber } 2600371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber 2601c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen 2602c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen Trex *trex = NULL; 2603c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen int32_t trackId; 2604c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (track->meta->findInt32(kKeyTrackID, &trackId)) { 2605c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen for (size_t i = 0; i < mTrex.size(); i++) { 2606c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen Trex *t = &mTrex.editItemAt(index); 2607c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen if (t->track_ID == (uint32_t) trackId) { 2608c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen trex = t; 2609c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen break; 2610c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 2611c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 2612c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } 2613c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen 2614a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("getTrack called, pssh: %zu", mPssh.size()); 2615ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2616942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen return new MPEG4Source(this, 261705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen track->meta, mDataSource, track->timescale, track->sampleTable, 2618c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen mSidxEntries, trex, mMoofOffset); 261920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 262020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2621bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static 2622bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) { 2623bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber const char *mime; 2624bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 2625bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 2626bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber uint32_t type; 2627bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber const void *data; 2628bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber size_t size; 2629bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 2630bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!track->meta->findData(kKeyAVCC, &type, &data, &size) 2631bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || type != kTypeAVCC) { 2632bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 2633bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 26343b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC)) { 26353b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar if (!track->meta->findData(kKeyHVCC, &type, &data, &size) 26363b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar || type != kTypeHVCC) { 26373b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar return ERROR_MALFORMED; 26383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar } 2639bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 2640bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 2641bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!track->meta->findData(kKeyESDS, &type, &data, &size) 2642bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || type != kTypeESDS) { 2643bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 2644bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 2645bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 2646bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 2647ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih if (track->sampleTable == NULL || !track->sampleTable->isValid()) { 2648169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber // Make sure we have all the metadata we need. 2649ce171998009e1abcb0c718c0aee495fcd33645e2Robert Shih ALOGE("stbl atom missing/invalid."); 2650169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber return ERROR_MALFORMED; 2651169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber } 2652169c286ed166499c5099d2b336967e0bf3d25551Andreas Huber 2653bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return OK; 2654bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber} 2655bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 2656f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivitypedef enum { 2657f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_NONE = -1, 2658f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_NULL_OBJECT = 0, 2659f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_AAC_MAIN = 1, /**< Main profile */ 2660f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi AOT_AAC_LC = 2, /**< Low Complexity object */ 2661f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_AAC_SSR = 3, 2662f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_AAC_LTP = 4, 2663f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi AOT_SBR = 5, 2664f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_AAC_SCAL = 6, 2665f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_TWIN_VQ = 7, 2666f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_CELP = 8, 2667f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_HVXC = 9, 2668f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_RSVD_10 = 10, /**< (reserved) */ 2669f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_RSVD_11 = 11, /**< (reserved) */ 2670f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_TTSI = 12, /**< TTSI Object */ 2671f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_MAIN_SYNTH = 13, /**< Main Synthetic object */ 2672f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_WAV_TAB_SYNTH = 14, /**< Wavetable Synthesis object */ 2673f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_GEN_MIDI = 15, /**< General MIDI object */ 2674f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */ 2675f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi AOT_ER_AAC_LC = 17, /**< Error Resilient(ER) AAC Low Complexity */ 2676f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_RSVD_18 = 18, /**< (reserved) */ 2677f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_ER_AAC_LTP = 19, /**< Error Resilient(ER) AAC LTP object */ 2678f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi AOT_ER_AAC_SCAL = 20, /**< Error Resilient(ER) AAC Scalable object */ 2679f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_ER_TWIN_VQ = 21, /**< Error Resilient(ER) TwinVQ object */ 2680f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi AOT_ER_BSAC = 22, /**< Error Resilient(ER) BSAC object */ 2681f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi AOT_ER_AAC_LD = 23, /**< Error Resilient(ER) AAC LowDelay object */ 2682f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_ER_CELP = 24, /**< Error Resilient(ER) CELP object */ 2683f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_ER_HVXC = 25, /**< Error Resilient(ER) HVXC object */ 2684f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_ER_HILN = 26, /**< Error Resilient(ER) HILN object */ 2685f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_ER_PARA = 27, /**< Error Resilient(ER) Parametric object */ 2686f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_RSVD_28 = 28, /**< might become SSC */ 2687f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi AOT_PS = 29, /**< PS, Parametric Stereo (includes SBR) */ 2688f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_MPEGS = 30, /**< MPEG Surround */ 2689f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2690f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi AOT_ESCAPE = 31, /**< Signal AOT uses more than 5 bits */ 2691f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2692f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_MP3ONMP4_L1 = 32, /**< MPEG-Layer1 in mp4 */ 2693f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_MP3ONMP4_L2 = 33, /**< MPEG-Layer2 in mp4 */ 2694f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_MP3ONMP4_L3 = 34, /**< MPEG-Layer3 in mp4 */ 2695f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_RSVD_35 = 35, /**< might become DST */ 2696f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_RSVD_36 = 36, /**< might become ALS */ 2697f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_AAC_SLS = 37, /**< AAC + SLS */ 2698f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_SLS = 38, /**< SLS */ 2699f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_ER_AAC_ELD = 39, /**< AAC Enhanced Low Delay */ 2700f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2701f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_USAC = 42, /**< USAC */ 2702f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_SAOC = 43, /**< SAOC */ 2703f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_LD_MPEGS = 44, /**< Low Delay MPEG Surround */ 2704f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2705f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //AOT_RSVD50 = 50, /**< Interim AOT for Rsvd50 */ 2706f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi} AUDIO_OBJECT_TYPE; 2707f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2708ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( 2709ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber const void *esds_data, size_t esds_size) { 2710ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber ESDS esds(esds_data, esds_size); 271181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 271281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint8_t objectTypeIndication; 271381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) { 271481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber return ERROR_MALFORMED; 271581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber } 271681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 271781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber if (objectTypeIndication == 0xe1) { 271881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber // This isn't MPEG4 audio at all, it's QCELP 14k... 271981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP); 272081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber return OK; 272181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber } 272281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 2723633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong if (objectTypeIndication == 0x6b) { 2724633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong // The media subtype is MP3 audio 2725633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong // Our software MP3 audio decoder may not be able to handle 2726633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED 272729357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("MP3 track in MP4/3GPP file is not supported"); 2728633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong return ERROR_UNSUPPORTED; 2729633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong } 2730633b4c8cc1f41370576aa43e6c5a70e4865a36dfJames Dong 2731ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber const uint8_t *csd; 2732ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber size_t csd_size; 2733ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (esds.getCodecSpecificInfo( 2734ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber (const void **)&csd, &csd_size) != OK) { 2735ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 2736ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2737ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2738ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0 2739ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber printf("ESD of size %d\n", csd_size); 2740ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber hexdump(csd, csd_size); 2741ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif 2742ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2743a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber if (csd_size == 0) { 2744a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber // There's no further information, i.e. no codec specific data 2745a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber // Let's assume that the information provided in the mpeg4 headers 2746a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber // is accurate and hope for the best. 2747a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber 2748a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber return OK; 2749a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber } 2750a65ccbff6e8eb301c0d325b2ec080aeda8df2024Andreas Huber 2751ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (csd_size < 2) { 2752ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 2753ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2754ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 275500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent static uint32_t kSamplingRate[] = { 275600307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 275700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent 16000, 12000, 11025, 8000, 7350 275800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent }; 275900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent 2760aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke ABitReader br(csd, csd_size); 2761aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke uint32_t objectType = br.getBits(5); 2762ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2763aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke if (objectType == 31) { // AAC-ELD => additional 6 bits 2764aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke objectType = 32 + br.getBits(6); 2765ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2766ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2767db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent //keep AOT type 2768db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent mLastTrack->meta->setInt32(kKeyAACAOT, objectType); 2769db170bb1cae145d07efc803a3c208963de0c6087Eric Laurent 2770aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke uint32_t freqIndex = br.getBits(4); 2771aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke 2772ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t sampleRate = 0; 2773ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t numChannels = 0; 2774ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (freqIndex == 15) { 2775ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (csd_size < 5) { 2776ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 2777ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2778aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke sampleRate = br.getBits(24); 2779aeb8fd460ed87d032b3fb8bb61e21eb542ce0f5bDave Burke numChannels = br.getBits(4); 2780ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } else { 2781595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen numChannels = br.getBits(4); 278200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent 278300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent if (freqIndex == 13 || freqIndex == 14) { 278400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent return ERROR_MALFORMED; 2785ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2786ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 278700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent sampleRate = kSamplingRate[freqIndex]; 278800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent } 2789595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen 2790f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi if (objectType == AOT_SBR || objectType == AOT_PS) {//SBR specific config per 14496-3 table 1.13 279100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent uint32_t extFreqIndex = br.getBits(4); 279200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent int32_t extSampleRate; 279300307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent if (extFreqIndex == 15) { 279400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent if (csd_size < 8) { 2795595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen return ERROR_MALFORMED; 2796595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen } 279700307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent extSampleRate = br.getBits(24); 279800307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent } else { 279900307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent if (extFreqIndex == 13 || extFreqIndex == 14) { 280000307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent return ERROR_MALFORMED; 280100307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent } 280200307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent extSampleRate = kSamplingRate[extFreqIndex]; 2803595ee7ba5f988ff34527226d0142a109ca3b049eMarco Nelissen } 280400307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent //TODO: save the extension sampling rate value in meta data => 280500307ade843ac9219ffb9a351a3145ec2927ea51Eric Laurent // mLastTrack->meta->setInt32(kKeyExtSampleRate, extSampleRate); 2806ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2807ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2808f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi switch (numChannels) { 2809f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi // values defined in 14496-3_2009 amendment-4 Table 1.19 - Channel Configuration 2810f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi case 0: 2811f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi case 1:// FC 2812f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi case 2:// FL FR 2813f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi case 3:// FC, FL FR 2814f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi case 4:// FC, FL FR, RC 2815f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi case 5:// FC, FL FR, SL SR 2816f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi case 6:// FC, FL FR, SL SR, LFE 2817f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi //numChannels already contains the right value 2818f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi break; 2819f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi case 11:// FC, FL FR, SL SR, RC, LFE 2820f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi numChannels = 7; 2821f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi break; 2822f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi case 7: // FC, FCL FCR, FL FR, SL SR, LFE 2823f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi case 12:// FC, FL FR, SL SR, RL RR, LFE 2824f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi case 14:// FC, FL FR, SL SR, LFE, FHL FHR 2825f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi numChannels = 8; 2826f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi break; 2827f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi default: 2828f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi return ERROR_UNSUPPORTED; 2829f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2830f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2831f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi { 2832f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi if (objectType == AOT_SBR || objectType == AOT_PS) { 2833f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi objectType = br.getBits(5); 2834f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2835f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi if (objectType == AOT_ESCAPE) { 2836f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi objectType = 32 + br.getBits(6); 2837f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2838f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2839f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi if (objectType == AOT_AAC_LC || objectType == AOT_ER_AAC_LC || 2840f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi objectType == AOT_ER_AAC_LD || objectType == AOT_ER_AAC_SCAL || 2841f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi objectType == AOT_ER_BSAC) { 2842f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t frameLengthFlag = br.getBits(1); 2843f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2844f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t dependsOnCoreCoder = br.getBits(1); 2845f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2846f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi if (dependsOnCoreCoder ) { 2847f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t coreCoderDelay = br.getBits(14); 2848f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2849f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 285045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih int32_t extensionFlag = -1; 285145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih if (br.numBitsLeft() > 0) { 285245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih extensionFlag = br.getBits(1); 285345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih } else { 285445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih switch (objectType) { 285545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih // 14496-3 4.5.1.1 extensionFlag 285645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih case AOT_AAC_LC: 285745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih extensionFlag = 0; 285845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih break; 285945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih case AOT_ER_AAC_LC: 286045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih case AOT_ER_AAC_SCAL: 286145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih case AOT_ER_BSAC: 286245452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih case AOT_ER_AAC_LD: 286345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih extensionFlag = 1; 286445452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih break; 286545452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih default: 286645452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih TRESPASS(); 286745452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih break; 286845452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih } 286945452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih ALOGW("csd missing extension flag; assuming %d for object type %u.", 287045452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih extensionFlag, objectType); 287145452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih } 2872f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 287345452ffeb3827dd3c955aca1b4ab3522b70cf8ccRobert Shih if (numChannels == 0) { 2874f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi int32_t channelsEffectiveNum = 0; 2875f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi int32_t channelsNum = 0; 2876f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t ElementInstanceTag = br.getBits(4); 2877f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t Profile = br.getBits(2); 2878f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t SamplingFrequencyIndex = br.getBits(4); 2879f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t NumFrontChannelElements = br.getBits(4); 2880f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t NumSideChannelElements = br.getBits(4); 2881f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t NumBackChannelElements = br.getBits(4); 2882f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t NumLfeChannelElements = br.getBits(2); 2883f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t NumAssocDataElements = br.getBits(3); 2884f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t NumValidCcElements = br.getBits(4); 2885f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2886f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t MonoMixdownPresent = br.getBits(1); 2887f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi if (MonoMixdownPresent != 0) { 2888f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t MonoMixdownElementNumber = br.getBits(4); 2889f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2890f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2891f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t StereoMixdownPresent = br.getBits(1); 2892f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi if (StereoMixdownPresent != 0) { 2893f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t StereoMixdownElementNumber = br.getBits(4); 2894f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2895f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2896f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t MatrixMixdownIndexPresent = br.getBits(1); 2897f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi if (MatrixMixdownIndexPresent != 0) { 2898f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t MatrixMixdownIndex = br.getBits(2); 2899f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t PseudoSurroundEnable = br.getBits(1); 2900f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2901f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2902f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi int i; 2903f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi for (i=0; i < NumFrontChannelElements; i++) { 2904f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t FrontElementIsCpe = br.getBits(1); 2905f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t FrontElementTagSelect = br.getBits(4); 2906f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi channelsNum += FrontElementIsCpe ? 2 : 1; 2907f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2908f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2909f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi for (i=0; i < NumSideChannelElements; i++) { 2910f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t SideElementIsCpe = br.getBits(1); 2911f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t SideElementTagSelect = br.getBits(4); 2912f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi channelsNum += SideElementIsCpe ? 2 : 1; 2913f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2914f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2915f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi for (i=0; i < NumBackChannelElements; i++) { 2916f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t BackElementIsCpe = br.getBits(1); 2917f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t BackElementTagSelect = br.getBits(4); 2918f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi channelsNum += BackElementIsCpe ? 2 : 1; 2919f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2920f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi channelsEffectiveNum = channelsNum; 2921f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2922f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi for (i=0; i < NumLfeChannelElements; i++) { 2923f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi const int32_t LfeElementTagSelect = br.getBits(4); 2924f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi channelsNum += 1; 2925f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2926f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi ALOGV("mpeg4 audio channelsNum = %d", channelsNum); 2927f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi ALOGV("mpeg4 audio channelsEffectiveNum = %d", channelsEffectiveNum); 2928f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi numChannels = channelsNum; 2929f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2930f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2931f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi } 2932f4512c9672110c11b7bdeea0073a54bfae9c8f87Jean-Michel Trivi 2933ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (numChannels == 0) { 2934ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_UNSUPPORTED; 2935ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2936ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2937ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t prevSampleRate; 2938ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate)); 2939ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2940ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (prevSampleRate != sampleRate) { 29413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("mpeg4 audio sample rate different from previous setting. " 2942ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber "was: %d, now: %d", prevSampleRate, sampleRate); 2943ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2944ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2945ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sampleRate); 2946ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2947ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t prevChannelCount; 2948ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount)); 2949ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2950ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (prevChannelCount != numChannels) { 29513856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("mpeg4 audio channel count different from previous setting. " 2952ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber "was: %d, now: %d", prevChannelCount, numChannels); 2953ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 2954ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2955ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, numChannels); 2956ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 2957ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return OK; 2958ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber} 2959ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 296020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 296120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 296220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source( 2963942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen const sp<MPEG4Extractor> &owner, 296420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const sp<MetaData> &format, 2965693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &dataSource, 296648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int32_t timeScale, 296705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const sp<SampleTable> &sampleTable, 296805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Vector<SidxEntry> &sidx, 2969c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen const Trex *trex, 297005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t firstMoofOffset) 2971942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen : mOwner(owner), 2972942481eee58cb1e81853bc79e25359a7ee8a59e1Marco Nelissen mFormat(format), 297320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDataSource(dataSource), 297448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mTimescale(timeScale), 297520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSampleTable(sampleTable), 297620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCurrentSampleIndex(0), 297705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentFragmentIndex(0), 297805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mSegments(sidx), 2979c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen mTrex(trex), 298005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mFirstMoofOffset(firstMoofOffset), 298105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentMoofOffset(firstMoofOffset), 298205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentTime(0), 2983ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoAllocSize(0), 2984ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoSizes(NULL), 2985ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsetsAllocSize(0), 2986ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets(NULL), 298720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mIsAVC(false), 29883b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar mIsHEVC(false), 29896064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mNALLengthSize(0), 299020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted(false), 299120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup(NULL), 299220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer(NULL), 2993dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments(false), 29940024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer(NULL) { 2995ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 2996c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen memset(&mTrackFragmentHeaderInfo, 0, sizeof(mTrackFragmentHeaderInfo)); 2997c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen 2998ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mFormat->findInt32(kKeyCryptoMode, &mCryptoMode); 299948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mDefaultIVSize = 0; 3000ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mFormat->findInt32(kKeyCryptoDefaultIVSize, &mDefaultIVSize); 3001ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t keytype; 3002ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen const void *key; 3003ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen size_t keysize; 3004ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mFormat->findData(kKeyCryptoKey, &keytype, &key, &keysize)) { 3005ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen CHECK(keysize <= 16); 3006ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(mCryptoKey, 0, 16); 3007ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memcpy(mCryptoKey, key, keysize); 3008ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3009ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 301020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 301120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mFormat->findCString(kKeyMIMEType, &mime); 3012dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(success); 301320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 301418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 30153b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar mIsHEVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_HEVC); 30166064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 30176064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber if (mIsAVC) { 30186064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber uint32_t type; 30196064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber const void *data; 30206064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t size; 30216064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(format->findData(kKeyAVCC, &type, &data, &size)); 30226064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 30236064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber const uint8_t *ptr = (const uint8_t *)data; 30246064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 30256064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(size >= 7); 3026ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 30276064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 30286064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // The number of bytes used to encode the length of a NAL unit. 30296064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mNALLengthSize = 1 + (ptr[4] & 3); 30303b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar } else if (mIsHEVC) { 30313b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar uint32_t type; 30323b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar const void *data; 30333b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar size_t size; 30343b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar CHECK(format->findData(kKeyHVCC, &type, &data, &size)); 30353b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar 30363b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar const uint8_t *ptr = (const uint8_t *)data; 30373b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar 30383b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar CHECK(size >= 7); 30393b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 30403b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar 30413b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar mNALLengthSize = 1 + (ptr[14 + 7] & 3); 30426064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber } 304305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 304405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(format->findInt32(kKeyTrackID, &mTrackId)); 304505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 304605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mFirstMoofOffset != 0) { 304705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t offset = mFirstMoofOffset; 304805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(&offset); 304905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 305020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 305120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 305220111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() { 305320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mStarted) { 305420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 305520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 3056ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen free(mCurrentSampleInfoSizes); 3057ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen free(mCurrentSampleInfoOffsets); 305820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 305920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 306020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) { 30617b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 30627b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 3063dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(!mStarted); 306420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 306520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t val; 3066dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (params && params->findInt32(kKeyWantsNALFragments, &val) 306720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && val != 0) { 3068dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments = true; 306920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 3070dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments = false; 307120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 307220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 307320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup = new MediaBufferGroup; 307420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3075738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber int32_t max_size; 3076738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size)); 307720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3078738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber mGroup->add_buffer(new MediaBuffer(max_size)); 30790024245e134467d120b40099da16c467dc365e76Andreas Huber 30808da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen mSrcBuffer = new (std::nothrow) uint8_t[max_size]; 30818da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen if (mSrcBuffer == NULL) { 30828da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen // file probably specified a bad max size 30838da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen return ERROR_MALFORMED; 30848da8b2e80ccdb10ff2445f503829f803d3a6ab9fMarco Nelissen } 308520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 308620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = true; 308720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 308820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 308920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 309020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 309120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() { 30927b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 30937b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 3094dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(mStarted); 309520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 309620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mBuffer != NULL) { 309720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 309820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 309920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 310020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31010024245e134467d120b40099da16c467dc365e76Andreas Huber delete[] mSrcBuffer; 31020024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer = NULL; 31030024245e134467d120b40099da16c467dc365e76Andreas Huber 310420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete mGroup; 310520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup = NULL; 310620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 310720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = false; 310820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCurrentSampleIndex = 0; 310920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 311020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 311120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 311220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 311305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseChunk(off64_t *offset) { 311405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t hdr[2]; 311505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mDataSource->readAt(*offset, hdr, 8) < 8) { 311605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 311705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 311805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t chunk_size = ntohl(hdr[0]); 311905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t chunk_type = ntohl(hdr[1]); 312005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t data_offset = *offset + 8; 312105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 312205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_size == 1) { 312305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { 312405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 312505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 312605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen chunk_size = ntoh64(chunk_size); 312705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen data_offset += 8; 312805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 312905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_size < 16) { 313005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // The smallest valid chunk is 16 bytes long in this case. 313105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 313205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 313305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (chunk_size < 8) { 313405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // The smallest valid chunk is 8 bytes long. 313505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 313605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 313705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 313805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen char chunk[5]; 313905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MakeFourCCString(chunk_type, chunk); 314005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Source chunk %s @ %llx", chunk, *offset); 314105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 314205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t chunk_data_size = *offset + chunk_size - data_offset; 314305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 314405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen switch(chunk_type) { 314505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 314605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('t', 'r', 'a', 'f'): 314705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('m', 'o', 'o', 'f'): { 314805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t stop_offset = *offset + chunk_size; 314905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset = data_offset; 315005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen while (*offset < stop_offset) { 315105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err = parseChunk(offset); 315205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (err != OK) { 315305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 315405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 315505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 315605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (chunk_type == FOURCC('m', 'o', 'o', 'f')) { 31573f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen // *offset points to the box following this moof. Find the next moof from there. 31583f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen 31593f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen while (true) { 31603f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen if (mDataSource->readAt(*offset, hdr, 8) < 8) { 31613f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen return ERROR_END_OF_STREAM; 31623f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen } 31633f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen chunk_size = ntohl(hdr[0]); 31643f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen chunk_type = ntohl(hdr[1]); 31653f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen if (chunk_type == FOURCC('m', 'o', 'o', 'f')) { 31663f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen mNextMoofOffset = *offset; 31673f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen break; 31683f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen } 31693f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen *offset += chunk_size; 31703f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen } 317105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 317205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 317305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 317405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 317505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('t', 'f', 'h', 'd'): { 317605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err; 317705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((err = parseTrackFragmentHeader(data_offset, chunk_data_size)) != OK) { 317805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 317905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 318005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 318105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 318205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 318305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 318405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen case FOURCC('t', 'r', 'u', 'n'): { 318505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err; 318605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mLastParsedTrackId == mTrackId) { 318705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((err = parseTrackFragmentRun(data_offset, chunk_data_size)) != OK) { 318805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 318905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 319005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 319105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 319205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 319305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 319405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 319505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 3196ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'a', 'i', 'z'): { 3197ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t err; 3198ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if ((err = parseSampleAuxiliaryInformationSizes(data_offset, chunk_data_size)) != OK) { 3199ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return err; 3200ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3201ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 3202ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 3203ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3204ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('s', 'a', 'i', 'o'): { 3205ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen status_t err; 3206ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if ((err = parseSampleAuxiliaryInformationOffsets(data_offset, chunk_data_size)) != OK) { 3207ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return err; 3208ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3209ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 3210ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 3211ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3212ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3213ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen case FOURCC('m', 'd', 'a', 't'): { 3214ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // parse DRM info if present 3215ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("MPEG4Source::parseChunk mdat"); 3216ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // if saiz/saoi was previously observed, do something with the sampleinfos 3217ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen *offset += chunk_size; 3218ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen break; 3219ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3220ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 322105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen default: { 322205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *offset += chunk_size; 322305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 322405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 322505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 322605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 322705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 322805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 322984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationSizes( 323084333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber off64_t offset, off64_t /* size */) { 3231ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("parseSampleAuxiliaryInformationSizes"); 3232ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // 14496-12 8.7.12 3233ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t version; 3234ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt( 3235ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset, &version, sizeof(version)) 3236ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen < (ssize_t)sizeof(version)) { 3237ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 3238ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3239ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3240ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (version != 0) { 3241ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_UNSUPPORTED; 3242ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3243ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset++; 3244ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3245ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t flags; 3246ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt24(offset, &flags)) { 3247ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 3248ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3249ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 3; 3250ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3251ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (flags & 1) { 3252ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t tmp; 3253ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 3254ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 3255ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3256ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentAuxInfoType = tmp; 3257ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 3258ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 3259ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 3260ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3261ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentAuxInfoTypeParameter = tmp; 3262ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 3263ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3264ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3265ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t defsize; 3266ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(offset, &defsize, 1) != 1) { 3267ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 3268ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3269ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentDefaultSampleInfoSize = defsize; 3270ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset++; 3271ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3272ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t smplcnt; 3273ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &smplcnt)) { 3274ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_MALFORMED; 3275ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 327648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen mCurrentSampleInfoCount = smplcnt; 3277ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 3278ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 327948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (mCurrentDefaultSampleInfoSize != 0) { 328048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen ALOGV("@@@@ using default sample info size of %d", mCurrentDefaultSampleInfoSize); 328148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return OK; 328248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 3283ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (smplcnt > mCurrentSampleInfoAllocSize) { 3284ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoSizes = (uint8_t*) realloc(mCurrentSampleInfoSizes, smplcnt); 3285ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoAllocSize = smplcnt; 3286ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3287ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3288ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mDataSource->readAt(offset, mCurrentSampleInfoSizes, smplcnt); 3289ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return OK; 3290ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen} 3291ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 329284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t MPEG4Source::parseSampleAuxiliaryInformationOffsets( 329384333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber off64_t offset, off64_t /* size */) { 3294ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen ALOGV("parseSampleAuxiliaryInformationOffsets"); 3295ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // 14496-12 8.7.13 3296ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint8_t version; 3297ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(offset, &version, sizeof(version)) != 1) { 3298ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 3299ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3300ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset++; 3301ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3302ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t flags; 3303ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt24(offset, &flags)) { 3304ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 3305ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3306ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 3; 3307ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3308ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t entrycount; 3309ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &entrycount)) { 3310ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 3311ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3312ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 3313ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3314ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (entrycount > mCurrentSampleInfoOffsetsAllocSize) { 3315ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets = (uint64_t*) realloc(mCurrentSampleInfoOffsets, entrycount * 8); 3316ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsetsAllocSize = entrycount; 3317ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3318ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsetCount = entrycount; 3319ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3320ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < entrycount; i++) { 3321ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (version == 0) { 3322ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint32_t tmp; 3323ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &tmp)) { 3324ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 3325ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3326ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets[i] = tmp; 3327ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 4; 3328ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } else { 3329ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen uint64_t tmp; 3330ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt64(offset, &tmp)) { 3331ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 3332ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3333ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen mCurrentSampleInfoOffsets[i] = tmp; 3334ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen offset += 8; 3335ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3336ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3337ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3338ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen // parse clear/encrypted data 3339ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3340ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen off64_t drmoffset = mCurrentSampleInfoOffsets[0]; // from moof 3341ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3342ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen drmoffset += mCurrentMoofOffset; 3343ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen int ivlength; 3344ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen CHECK(mFormat->findInt32(kKeyCryptoDefaultIVSize, &ivlength)); 334548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 334648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // read CencSampleAuxiliaryDataFormats 3347ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen for (size_t i = 0; i < mCurrentSampleInfoCount; i++) { 3348ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen Sample *smpl = &mCurrentSamples.editItemAt(i); 3349ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3350ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen memset(smpl->iv, 0, 16); 3351ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (mDataSource->readAt(drmoffset, smpl->iv, ivlength) != ivlength) { 3352ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 3353ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3354ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3355ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen drmoffset += ivlength; 3356ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 335748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen int32_t smplinfosize = mCurrentDefaultSampleInfoSize; 335848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (smplinfosize == 0) { 335948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smplinfosize = mCurrentSampleInfoSizes[i]; 3360ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 336148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (smplinfosize > ivlength) { 336248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint16_t numsubsamples; 336348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!mDataSource->getUInt16(drmoffset, &numsubsamples)) { 3364ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return ERROR_IO; 3365ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3366ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen drmoffset += 2; 336748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen for (size_t j = 0; j < numsubsamples; j++) { 336848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint16_t numclear; 336948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen uint32_t numencrypted; 337048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!mDataSource->getUInt16(drmoffset, &numclear)) { 337148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return ERROR_IO; 337248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 337348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen drmoffset += 2; 337448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (!mDataSource->getUInt32(drmoffset, &numencrypted)) { 337548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen return ERROR_IO; 337648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 337748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen drmoffset += 4; 337848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->clearsizes.add(numclear); 337948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->encryptedsizes.add(numencrypted); 3380ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 338148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } else { 338248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->clearsizes.add(0); 338348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->encryptedsizes.add(smpl->size); 3384ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3385ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen } 3386ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3387ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 3388ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen return OK; 3389ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen} 3390ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen 339105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) { 339205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 339305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 339405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 339505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 339605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 339705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t flags; 3398ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags 339905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 340005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 340105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 340205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & 0xff000000) { 340305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 340405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 340505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 340605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, (uint32_t*)&mLastParsedTrackId)) { 340705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 340805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 340905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 341005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mLastParsedTrackId != mTrackId) { 341105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // this is not the right track, skip it 341205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 341305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 341405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 341505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mFlags = flags; 341605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mTrackID = mLastParsedTrackId; 341705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 341805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 341905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 342005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("fragment header: %08x %08x", flags, mTrackFragmentHeaderInfo.mTrackID); 342105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 342205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent) { 342305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 342405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 342505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 342605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 342705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt64(offset, &mTrackFragmentHeaderInfo.mBaseDataOffset)) { 342805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 342905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 343005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 343105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 343205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 343305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 343405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kSampleDescriptionIndexPresent) { 343505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 343605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 343705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 343805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 343905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mSampleDescriptionIndex)) { 344005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 344105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 344205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 344305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 344405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 344505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 344605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) { 344705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 344805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 344905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 345005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 345105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleDuration)) { 345205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 345305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 345405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 345505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 345605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 345705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 345805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) { 345905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 346005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 346105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 346205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 346305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleSize)) { 346405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 346505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 346605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 346705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 346805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 346905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 347005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) { 347105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 347205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 347305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 347405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 347505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &mTrackFragmentHeaderInfo.mDefaultSampleFlags)) { 347605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 347705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 347805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 347905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 348005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 348105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 348205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!(flags & TrackFragmentHeaderInfo::kBaseDataOffsetPresent)) { 348305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mBaseDataOffset = mCurrentMoofOffset; 348405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 348505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 348605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mDataOffset = 0; 348705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 348805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 348905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 349005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::parseTrackFragmentRun(off64_t offset, off64_t size) { 349105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 349205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Extractor::parseTrackFragmentRun"); 349305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 8) { 349405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 349505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 349605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 349705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen enum { 349805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kDataOffsetPresent = 0x01, 349905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kFirstSampleFlagsPresent = 0x04, 350005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleDurationPresent = 0x100, 350105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleSizePresent = 0x200, 350205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleFlagsPresent = 0x400, 350305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kSampleCompositionTimeOffsetPresent = 0x800, 350405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen }; 350505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 350605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t flags; 350705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &flags)) { 350805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 350905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 351005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("fragment run flags: %08x", flags); 351105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 351205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & 0xff000000) { 351305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 351405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 351505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 351605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if ((flags & kFirstSampleFlagsPresent) && (flags & kSampleFlagsPresent)) { 351705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // These two shall not be used together. 351805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 351905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 352005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 352105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleCount; 352205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset + 4, &sampleCount)) { 352305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 352405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 352505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 8; 352605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 8; 352705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 352805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint64_t dataOffset = mTrackFragmentHeaderInfo.mDataOffset; 352905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 353005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t firstSampleFlags = 0; 353105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 353205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kDataOffsetPresent) { 353305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 353405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 353505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 353605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 353705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t dataOffsetDelta; 353805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, (uint32_t*)&dataOffsetDelta)) { 353905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 354005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 354105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 354205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dataOffset = mTrackFragmentHeaderInfo.mBaseDataOffset + dataOffsetDelta; 354305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 354405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 354505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 354605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 354705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 354805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kFirstSampleFlagsPresent) { 354905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (size < 4) { 355005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 355105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 355205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 355305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &firstSampleFlags)) { 355405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 355505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 355605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 355705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size -= 4; 355805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 355905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 356005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t sampleDuration = 0, sampleSize = 0, sampleFlags = 0, 356105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleCtsOffset = 0; 356205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 356305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t bytesPerSample = 0; 356405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleDurationPresent) { 356505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 356605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (mTrackFragmentHeaderInfo.mFlags 356705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen & TrackFragmentHeaderInfo::kDefaultSampleDurationPresent) { 356805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleDuration = mTrackFragmentHeaderInfo.mDefaultSampleDuration; 3569c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen } else if (mTrex) { 3570c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen sampleDuration = mTrex->default_sample_duration; 357105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 357205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 357305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleSizePresent) { 357405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 357505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (mTrackFragmentHeaderInfo.mFlags 357605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen & TrackFragmentHeaderInfo::kDefaultSampleSizePresent) { 357705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize; 357805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 357905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleSize = mTrackFragmentHeaderInfo.mDefaultSampleSize; 358005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 358105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 358205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleFlagsPresent) { 358305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 358405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else if (mTrackFragmentHeaderInfo.mFlags 358505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen & TrackFragmentHeaderInfo::kDefaultSampleFlagsPresent) { 358605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags; 358705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 358805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleFlags = mTrackFragmentHeaderInfo.mDefaultSampleFlags; 358905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 359005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 359105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleCompositionTimeOffsetPresent) { 359205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bytesPerSample += 4; 359305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 359405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen sampleCtsOffset = 0; 359505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 359605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 3597a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn if (size < (off64_t)sampleCount * bytesPerSample) { 359805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return -EINVAL; 359905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 360005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 360105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen Sample tmp; 360205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen for (uint32_t i = 0; i < sampleCount; ++i) { 360305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleDurationPresent) { 360405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleDuration)) { 360505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 360605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 360705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 360805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 360905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 361005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleSizePresent) { 361105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleSize)) { 361205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 361305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 361405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 361505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 361605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 361705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleFlagsPresent) { 361805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleFlags)) { 361905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 362005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 362105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 362205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 362305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 362405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (flags & kSampleCompositionTimeOffsetPresent) { 362505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!mDataSource->getUInt32(offset, &sampleCtsOffset)) { 362605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 362705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 362805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset += 4; 362905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 363005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 3631a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("adding sample %d at offset 0x%08" PRIx64 ", size %u, duration %u, " 3632ec77122351b4e78c1fe5b60a208f76baf8c67591Marco Nelissen " flags 0x%08x", i + 1, 363305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dataOffset, sampleSize, sampleDuration, 363405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (flags & kFirstSampleFlagsPresent) && i == 0 363505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ? firstSampleFlags : sampleFlags); 363605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen tmp.offset = dataOffset; 363705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen tmp.size = sampleSize; 363805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen tmp.duration = sampleDuration; 3639c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen tmp.compositionOffset = sampleCtsOffset; 364005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSamples.add(tmp); 364105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 364205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dataOffset += sampleSize; 364305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 364405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 364505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mTrackFragmentHeaderInfo.mDataOffset = dataOffset; 364605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 364705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 364805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 364905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 365020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() { 36517b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 36527b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 365320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return mFormat; 365420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 365520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 36566064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const { 36576064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber switch (mNALLengthSize) { 36586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 1: 36596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return *data; 36606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 2: 36616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return U16_AT(data); 36626064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 3: 36636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return ((size_t)data[0] << 16) | U16_AT(&data[1]); 36646064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 4: 36656064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return U32_AT(data); 36666064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber } 36676064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 36686064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // This cannot happen, mNALLengthSize springs to life by adding 1 to 36696064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // a 2-bit integer. 36706064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(!"Should not be here."); 36716064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 36726064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return 0; 36736064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber} 36746064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 367520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read( 367620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer **out, const ReadOptions *options) { 36777b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 36787b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 3679dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(mStarted); 368020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 368105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mFirstMoofOffset > 0) { 368205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return fragmentedRead(out, options); 368305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 368405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 368520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *out = NULL; 368620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3687abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber int64_t targetSampleTimeUs = -1; 3688abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 368920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t seekTimeUs; 3690abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 3691abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 3692abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t findFlags = 0; 3693abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber switch (mode) { 3694abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_PREVIOUS_SYNC: 3695abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagBefore; 3696abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3697abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_NEXT_SYNC: 3698abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagAfter; 3699abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3700abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_CLOSEST_SYNC: 3701abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber case ReadOptions::SEEK_CLOSEST: 3702abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagClosest; 3703abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3704abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber default: 3705abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber CHECK(!"Should not be here."); 3706abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber break; 3707abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3708abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 370920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t sampleIndex; 3710abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber status_t err = mSampleTable->findSampleAtTime( 3711599950efbb03b1672561d4cf2272504b879525e8Lajos Molnar seekTimeUs, 1000000, mTimescale, 3712abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber &sampleIndex, findFlags); 3713abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3714abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 3715abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber // We found the closest sample already, now we want the sync 3716abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber // sample preceding it (or the sample itself of course), even 3717abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber // if the subsequent sync sample is closer. 3718abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber findFlags = SampleTable::kFlagBefore; 3719abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3720abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3721abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t syncSampleIndex; 3722abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (err == OK) { 3723abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber err = mSampleTable->findSyncSampleNear( 3724abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber sampleIndex, &syncSampleIndex, findFlags); 3725abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 372620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3727788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber uint32_t sampleTime; 3728788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber if (err == OK) { 3729788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber err = mSampleTable->getMetaDataForSample( 3730788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber sampleIndex, NULL, NULL, &sampleTime); 3731788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber } 3732788a07fc61bad7ea2f0e3cca3f126b52a9bab376Andreas Huber 373320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 37345295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber if (err == ERROR_OUT_OF_RANGE) { 37355295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // An attempt to seek past the end of the stream would 37365295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // normally cause this ERROR_OUT_OF_RANGE error. Propagating 37375295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // this all the way to the MediaPlayer would cause abnormal 37385295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // termination. Legacy behaviour appears to be to behave as if 37395295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // we had seeked to the end of stream, ending normally. 37405295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber err = ERROR_END_OF_STREAM; 37415295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber } 374205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("end of stream"); 374320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 374420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 374520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3746abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 3747abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale; 3748abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3749abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3750abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#if 0 3751abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber uint32_t syncSampleTime; 3752abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber CHECK_EQ(OK, mSampleTable->getMetaDataForSample( 3753abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber syncSampleIndex, NULL, NULL, &syncSampleTime)); 3754abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3755df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("seek to time %lld us => sample at time %lld us, " 3756abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber "sync sample at time %lld us", 3757abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber seekTimeUs, 3758abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber sampleTime * 1000000ll / mTimescale, 3759abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber syncSampleTime * 1000000ll / mTimescale); 3760abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber#endif 3761abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3762abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mCurrentSampleIndex = syncSampleIndex; 376320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mBuffer != NULL) { 376420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 376520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 376620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 376720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 376820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // fall through 376920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 377020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3771c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t offset; 37720024245e134467d120b40099da16c467dc365e76Andreas Huber size_t size; 3773170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih uint32_t cts, stts; 37748bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber bool isSyncSample; 3775dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber bool newBuffer = false; 3776dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (mBuffer == NULL) { 3777dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber newBuffer = true; 377820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3779c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber status_t err = 3780c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber mSampleTable->getMetaDataForSample( 3781170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample, &stts); 378220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3783dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (err != OK) { 3784dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return err; 3785dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3786dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3787dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber err = mGroup->acquire_buffer(&mBuffer); 3788c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 3789dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (err != OK) { 3790ba529e486dde15fe75ea1b48570f9d60a4cf3c48Andreas Huber CHECK(mBuffer == NULL); 3791dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return err; 3792dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 37930024245e134467d120b40099da16c467dc365e76Andreas Huber } 379420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37953b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar if ((!mIsAVC && !mIsHEVC) || mWantsNALFragments) { 3796dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (newBuffer) { 3797dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber ssize_t num_bytes_read = 379834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 3799dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3800dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (num_bytes_read < (ssize_t)size) { 3801dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->release(); 3802dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 3803dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3804dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return ERROR_IO; 3805dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3806dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 38077b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(mBuffer != NULL); 3808dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->set_range(0, size); 3809dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->meta_data()->clear(); 381048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mBuffer->meta_data()->setInt64( 38114678a6dc5f09008481524949a9667af5a6190374Andreas Huber kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 3812170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih mBuffer->meta_data()->setInt64( 3813170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih kKeyDuration, ((int64_t)stts * 1000000) / mTimescale); 3814abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3815abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (targetSampleTimeUs >= 0) { 3816abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mBuffer->meta_data()->setInt64( 3817abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber kKeyTargetTime, targetSampleTimeUs); 3818abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3819abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 38208bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber if (isSyncSample) { 38218bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 38228bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 38238bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 3824dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber ++mCurrentSampleIndex; 3825dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3826dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 38273b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar if (!mIsAVC && !mIsHEVC) { 3828dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber *out = mBuffer; 3829dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 3830dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3831dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return OK; 3832dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3833dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3834dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // Each NAL unit is split up into its constituent fragments and 3835dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // each one of them returned in its own buffer. 3836dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 38376064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(mBuffer->range_length() >= mNALLengthSize); 3838dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3839dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber const uint8_t *src = 3840dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 3841dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 38426064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t nal_size = parseNALSize(src); 3843e8a084958c27327b0aca749f69095605d2a21309Andreas Huber if (mBuffer->range_length() < mNALLengthSize + nal_size) { 384429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("incomplete NAL unit."); 3845e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 3846e8a084958c27327b0aca749f69095605d2a21309Andreas Huber mBuffer->release(); 3847e8a084958c27327b0aca749f69095605d2a21309Andreas Huber mBuffer = NULL; 3848e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 3849e8a084958c27327b0aca749f69095605d2a21309Andreas Huber return ERROR_MALFORMED; 3850e8a084958c27327b0aca749f69095605d2a21309Andreas Huber } 3851dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3852dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber MediaBuffer *clone = mBuffer->clone(); 38537b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(clone != NULL); 38546064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 3855dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 38567b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(mBuffer != NULL); 3857dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->set_range( 38586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mBuffer->range_offset() + mNALLengthSize + nal_size, 38596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mBuffer->range_length() - mNALLengthSize - nal_size); 3860dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3861dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (mBuffer->range_length() == 0) { 3862dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->release(); 3863dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 3864dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3865dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3866dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber *out = clone; 3867dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3868dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return OK; 3869dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } else { 3870dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // Whole NAL units are returned but each fragment is prefixed by 3871dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // the start code (0x00 00 00 01). 3872dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang ssize_t num_bytes_read = 0; 3873dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang int32_t drm = 0; 3874dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0); 3875dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (usesDRM) { 3876dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang num_bytes_read = 3877dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size); 3878dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else { 3879dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size); 3880dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 388120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 388220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (num_bytes_read < (ssize_t)size) { 388320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 388420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 388520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3886dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return ERROR_IO; 388720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 388820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3889dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (usesDRM) { 3890dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK(mBuffer != NULL); 3891dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer->set_range(0, size); 38926064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 3893dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } else { 3894dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang uint8_t *dstData = (uint8_t *)mBuffer->data(); 3895dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size_t srcOffset = 0; 3896dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang size_t dstOffset = 0; 3897e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 3898dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang while (srcOffset < size) { 3899bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize); 390034fe252c89e33572d01fea981b58d7b115e76164James Dong size_t nalLength = 0; 390134fe252c89e33572d01fea981b58d7b115e76164James Dong if (!isMalFormed) { 390234fe252c89e33572d01fea981b58d7b115e76164James Dong nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 390334fe252c89e33572d01fea981b58d7b115e76164James Dong srcOffset += mNALLengthSize; 3904bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength); 390534fe252c89e33572d01fea981b58d7b115e76164James Dong } 3906e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 390734fe252c89e33572d01fea981b58d7b115e76164James Dong if (isMalFormed) { 390829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("Video is malformed"); 3909dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer->release(); 3910dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer = NULL; 3911dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang return ERROR_MALFORMED; 3912dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 3913dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang 3914dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang if (nalLength == 0) { 3915dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang continue; 3916dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 3917dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3918dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK(dstOffset + 4 <= mBuffer->size()); 3919dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 3920dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 0; 3921dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 0; 3922dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 0; 3923dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstData[dstOffset++] = 1; 3924dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 3925dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang srcOffset += nalLength; 3926dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang dstOffset += nalLength; 3927dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang } 3928dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK_EQ(srcOffset, size); 3929dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang CHECK(mBuffer != NULL); 3930dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang mBuffer->set_range(0, dstOffset); 3931dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 3932dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 393320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->meta_data()->clear(); 393448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mBuffer->meta_data()->setInt64( 39354678a6dc5f09008481524949a9667af5a6190374Andreas Huber kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 3936170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih mBuffer->meta_data()->setInt64( 3937170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih kKeyDuration, ((int64_t)stts * 1000000) / mTimescale); 3938abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 3939abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (targetSampleTimeUs >= 0) { 3940abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber mBuffer->meta_data()->setInt64( 3941abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber kKeyTargetTime, targetSampleTimeUs); 3942abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber } 3943abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber 39448bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber if (isSyncSample) { 39458bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 39468bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber } 39478bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 394820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++mCurrentSampleIndex; 394920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 395020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *out = mBuffer; 395120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 395220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 395320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 395420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 395520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 395620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 395705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissenstatus_t MPEG4Source::fragmentedRead( 395805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MediaBuffer **out, const ReadOptions *options) { 395905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 396005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("MPEG4Source::fragmentedRead"); 396105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 396205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mStarted); 396305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 396405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = NULL; 396505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 396605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t targetSampleTimeUs = -1; 396705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 396805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t seekTimeUs; 396905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ReadOptions::SeekMode mode; 397005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (options && options->getSeekTo(&seekTimeUs, &mode)) { 397105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 397205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int numSidxEntries = mSegments.size(); 397305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (numSidxEntries != 0) { 397405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int64_t totalTime = 0; 397505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t totalOffset = mFirstMoofOffset; 397605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen for (int i = 0; i < numSidxEntries; i++) { 397705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const SidxEntry *se = &mSegments[i]; 397805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (totalTime + se->mDurationUs > seekTimeUs) { 397905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // The requested time is somewhere in this segment 39803f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen if ((mode == ReadOptions::SEEK_NEXT_SYNC && seekTimeUs > totalTime) || 398105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (mode == ReadOptions::SEEK_CLOSEST_SYNC && 398205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (seekTimeUs - totalTime) > (totalTime + se->mDurationUs - seekTimeUs))) { 398305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // requested next sync, or closest sync and it was closer to the end of 398405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // this segment 398505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalTime += se->mDurationUs; 398605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalOffset += se->mSize; 398705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 398805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen break; 398905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 399005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalTime += se->mDurationUs; 399105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen totalOffset += se->mSize; 399205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 3993ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen mCurrentMoofOffset = totalOffset; 3994ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen mCurrentSamples.clear(); 3995ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen mCurrentSampleIndex = 0; 3996ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen parseChunk(&totalOffset); 3997ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen mCurrentTime = totalTime * mTimescale / 1000000ll; 3998ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen } else { 3999ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen // without sidx boxes, we can only seek to 0 4000ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen mCurrentMoofOffset = mFirstMoofOffset; 4001ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen mCurrentSamples.clear(); 4002ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen mCurrentSampleIndex = 0; 4003ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen off64_t tmp = mCurrentMoofOffset; 4004ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen parseChunk(&tmp); 4005ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen mCurrentTime = 0; 400605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 400705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 400805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer != NULL) { 400905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 401005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 401105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 401205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 401305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // fall through 401405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 401505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 401605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen off64_t offset = 0; 4017442cc6dc48f8188e097617f7f804c314a9dacd0eAndreas Huber size_t size = 0; 401805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint32_t cts = 0; 401905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool isSyncSample = false; 402005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool newBuffer = false; 402105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer == NULL) { 402205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen newBuffer = true; 402305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 402405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mCurrentSampleIndex >= mCurrentSamples.size()) { 40253f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen // move to next fragment if there is one 40263f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen if (mNextMoofOffset <= mCurrentMoofOffset) { 40273f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen return ERROR_END_OF_STREAM; 40283f80319d5bddfaf11a1513777561096fc1447172Marco Nelissen } 4029ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen off64_t nextMoof = mNextMoofOffset; 403005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentMoofOffset = nextMoof; 403105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSamples.clear(); 403205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentSampleIndex = 0; 403305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen parseChunk(&nextMoof); 4034ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen if (mCurrentSampleIndex >= mCurrentSamples.size()) { 4035ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen return ERROR_END_OF_STREAM; 4036ebfd32300605d67e4c45a97f4972d4b6ea268a37Marco Nelissen } 403705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 403805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 403905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex]; 404005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen offset = smpl->offset; 404105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size = smpl->size; 4042c1f4b2b73fe9432cb75ce1dd368475a2867e70edMarco Nelissen cts = mCurrentTime + smpl->compositionOffset; 404305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mCurrentTime += smpl->duration; 404405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen isSyncSample = (mCurrentSampleIndex == 0); // XXX 404505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 404605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen status_t err = mGroup->acquire_buffer(&mBuffer); 404705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 404805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (err != OK) { 404905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer == NULL); 405005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("acquire_buffer returned %d", err); 405105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return err; 405205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 405305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 405405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 405548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen const Sample *smpl = &mCurrentSamples[mCurrentSampleIndex]; 405648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen const sp<MetaData> bufmeta = mBuffer->meta_data(); 405748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->clear(); 405848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen if (smpl->encryptedsizes.size()) { 405948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen // store clear/encrypted lengths in metadata 406048186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyPlainSizes, 0, 406148186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->clearsizes.array(), smpl->clearsizes.size() * 4); 406248186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyEncryptedSizes, 0, 406348186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen smpl->encryptedsizes.array(), smpl->encryptedsizes.size() * 4); 406448186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyCryptoIV, 0, smpl->iv, 16); // use 16 or the actual size? 406548186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize); 406648186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setInt32(kKeyCryptoMode, mCryptoMode); 406748186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen bufmeta->setData(kKeyCryptoKey, 0, mCryptoKey, 16); 406848186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen } 406948186b6ec99aa71ec48338a55f2a2d8291681fe4Marco Nelissen 40703b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar if ((!mIsAVC && !mIsHEVC)|| mWantsNALFragments) { 407105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (newBuffer) { 407205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ssize_t num_bytes_read = 407305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 407405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 407505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (num_bytes_read < (ssize_t)size) { 407605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 407705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 407805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 407905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("i/o error"); 408005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 408105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 408205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 408305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 408405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range(0, size); 408505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 408605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 4087170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih mBuffer->meta_data()->setInt64( 4088170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale); 408905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 409005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (targetSampleTimeUs >= 0) { 409105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 409205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTargetTime, targetSampleTimeUs); 409305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 409405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 409505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (isSyncSample) { 409605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 409705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 409805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 409905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ++mCurrentSampleIndex; 410005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 410105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 41023b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar if (!mIsAVC && !mIsHEVC) { 410305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = mBuffer; 410405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 410505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 410605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 410705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 410805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 410905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // Each NAL unit is split up into its constituent fragments and 411005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // each one of them returned in its own buffer. 411105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 411205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer->range_length() >= mNALLengthSize); 411305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 411405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen const uint8_t *src = 411505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 411605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 411705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t nal_size = parseNALSize(src); 411805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer->range_length() < mNALLengthSize + nal_size) { 411905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGE("incomplete NAL unit."); 412005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 412105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 412205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 412305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 412405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 412505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 412605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 412705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MediaBuffer *clone = mBuffer->clone(); 412805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(clone != NULL); 412905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 413005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 413105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 413205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range( 413305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->range_offset() + mNALLengthSize + nal_size, 413405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->range_length() - mNALLengthSize - nal_size); 413505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 413605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (mBuffer->range_length() == 0) { 413705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 413805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 413905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 414005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 414105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = clone; 414205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 414305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 414405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 414505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("whole NAL"); 414605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // Whole NAL units are returned but each fragment is prefixed by 414705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen // the start code (0x00 00 00 01). 414805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ssize_t num_bytes_read = 0; 414905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen int32_t drm = 0; 415005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0); 415105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (usesDRM) { 415205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen num_bytes_read = 415305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size); 415405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 415505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size); 415605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 415705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 415805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (num_bytes_read < (ssize_t)size) { 415905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 416005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 416105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 416205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGV("i/o error"); 416305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_IO; 416405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 416505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 416605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (usesDRM) { 416705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 416805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range(0, size); 416905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 417005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } else { 417105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen uint8_t *dstData = (uint8_t *)mBuffer->data(); 417205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t srcOffset = 0; 417305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t dstOffset = 0; 417405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 417505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen while (srcOffset < size) { 4176bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize); 417705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen size_t nalLength = 0; 417805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (!isMalFormed) { 417905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 418005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen srcOffset += mNALLengthSize; 4181bfed843041b6aaec13ee19996748a7a1476db9c8Lajos Molnar isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength); 418205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 418305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 418405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (isMalFormed) { 418505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ALOGE("Video is malformed"); 418605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->release(); 418705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 418805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return ERROR_MALFORMED; 418905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 419005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 419105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (nalLength == 0) { 419205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen continue; 419305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 419405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 419505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(dstOffset + 4 <= mBuffer->size()); 419605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 419705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 0; 419805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 0; 419905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 0; 420005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstData[dstOffset++] = 1; 420105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 420205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen srcOffset += nalLength; 420305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen dstOffset += nalLength; 420405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 420505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK_EQ(srcOffset, size); 420605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen CHECK(mBuffer != NULL); 420705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->set_range(0, dstOffset); 420805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 420905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 421005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 421105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 4212170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih mBuffer->meta_data()->setInt64( 4213170056540e9ce65261b45efd15f67e72e2df1bedRobert Shih kKeyDuration, ((int64_t)smpl->duration * 1000000) / mTimescale); 421405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 421505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (targetSampleTimeUs >= 0) { 421605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt64( 421705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen kKeyTargetTime, targetSampleTimeUs); 421805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 421905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 422005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen if (isSyncSample) { 422105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 422205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 422305f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 422405f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen ++mCurrentSampleIndex; 422505f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 422605f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen *out = mBuffer; 422705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen mBuffer = NULL; 422805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 422905f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen return OK; 423005f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen } 423105f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen} 423205f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen 4233bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix( 4234bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber const char *mimePrefix) { 4235bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber for (Track *track = mFirstTrack; track != NULL; track = track->next) { 4236bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber const char *mime; 4237bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber if (track->meta != NULL 4238bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber && track->meta->findCString(kKeyMIMEType, &mime) 4239bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) { 4240bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return track; 4241bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber } 4242bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber } 4243bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber 4244bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber return NULL; 4245bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber} 4246bdba1f2a3813e4c8e690d71cfc2b82d5dee85c73Andreas Huber 42471b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4( 4248693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 424920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t header[8]; 425020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 425134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber ssize_t n = source->readAt(4, header, sizeof(header)); 425220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (n < (ssize_t)sizeof(header)) { 425320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return false; 425420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 425520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 425620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8) 4257b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8) 4258b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8) 42590dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8) 4260ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8) 4261983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) { 426218291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 42635a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber *confidence = 0.4; 426420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 426520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return true; 426620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 426720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 426820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return false; 426920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 427020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 42711b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) { 42721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber static const uint32_t kCompatibleBrands[] = { 42731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('i', 's', 'o', 'm'), 42741b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('i', 's', 'o', '2'), 42751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('a', 'v', 'c', '1'), 42763b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar FOURCC('h', 'v', 'c', '1'), 42773b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar FOURCC('h', 'e', 'v', '1'), 42781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('3', 'g', 'p', '4'), 42791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('m', 'p', '4', '1'), 42801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('m', 'p', '4', '2'), 42814cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong 42824cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong // Won't promise that the following file types can be played. 42834cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong // Just give these file types a chance. 42844cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong FOURCC('q', 't', ' ', ' '), // Apple's QuickTime 42854cb2c4dc7af70684e81cfbce46cbcbb9e44f4dc4James Dong FOURCC('M', 'S', 'N', 'V'), // Sony's PSP 428658fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber 428758fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber FOURCC('3', 'g', '2', 'a'), // 3GPP2 428858fb39120c633e3b8aa31b8f0a78e8efc193d59dAndreas Huber FOURCC('3', 'g', '2', 'b'), 42891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber }; 42901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 42911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber for (size_t i = 0; 42921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]); 42931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber ++i) { 42941b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (kCompatibleBrands[i] == fourcc) { 42951b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 42961b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 42971b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 42981b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 42991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 43001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 43011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 43021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable 43031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present. 4304a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// Also try to identify where this file's metadata ends 4305a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of 4306a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber// the metadata. 43071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4( 4308a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 4309a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber sp<AMessage> *meta) { 4310a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // We scan up to 128 bytes to identify this file as an MP4. 4311a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber static const off64_t kMaxScanOffset = 128ll; 43121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 4313a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t offset = 0ll; 4314a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber bool foundGoodFileType = false; 4315a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t moovAtomEndOffset = -1ll; 4316a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber bool done = false; 43171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 4318a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber while (!done && offset < kMaxScanOffset) { 4319a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t hdr[2]; 4320a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (source->readAt(offset, hdr, 8) < 8) { 4321a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 4322a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 4323a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4324a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint64_t chunkSize = ntohl(hdr[0]); 4325a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t chunkType = ntohl(hdr[1]); 4326a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t chunkDataOffset = offset + 8; 4327a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4328a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (chunkSize == 1) { 4329a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (source->readAt(offset + 8, &chunkSize, 8) < 8) { 43301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 43311b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 43321b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 4333a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber chunkSize = ntoh64(chunkSize); 4334a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber chunkDataOffset += 8; 4335a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4336a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (chunkSize < 16) { 4337a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // The smallest valid chunk is 16 bytes long in this case. 4338a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 4339a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 4340a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } else if (chunkSize < 8) { 4341a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // The smallest valid chunk is 8 bytes long. 4342a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 4343a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 4344a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4345a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber off64_t chunkDataSize = offset + chunkSize - chunkDataOffset; 4346a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 434705f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen char chunkstring[5]; 434805f625c46b992ab66b8d1527a366fe2746b4e3c7Marco Nelissen MakeFourCCString(chunkType, chunkstring); 4349a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("saw chunk type %s, size %" PRIu64 " @ %lld", chunkstring, chunkSize, offset); 4350a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber switch (chunkType) { 4351a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber case FOURCC('f', 't', 'y', 'p'): 4352a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber { 4353a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (chunkDataSize < 8) { 4354a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 4355a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 4356a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4357a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4; 4358a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber for (size_t i = 0; i < numCompatibleBrands + 2; ++i) { 4359a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (i == 1) { 4360a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // Skip this index, it refers to the minorVersion, 4361a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber // not a brand. 4362a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber continue; 4363a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 4364a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4365a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber uint32_t brand; 4366a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (source->readAt( 4367a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber chunkDataOffset + 4 * i, &brand, 4) < 4) { 4368a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 4369a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 4370a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4371a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber brand = ntohl(brand); 4372a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4373a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (isCompatibleBrand(brand)) { 4374a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber foundGoodFileType = true; 4375a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber break; 4376a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 4377a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 4378a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4379a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (!foundGoodFileType) { 4380a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber return false; 4381a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 4382a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 43831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber break; 43841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 4385a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4386a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber case FOURCC('m', 'o', 'o', 'v'): 4387a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber { 4388a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber moovAtomEndOffset = offset + chunkSize; 4389a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4390a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber done = true; 4391a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber break; 4392a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 4393a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4394a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber default: 4395a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber break; 43961b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 4397a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4398a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber offset += chunkSize; 43991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 44001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 4401a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (!foundGoodFileType) { 44021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 44031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 44041b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 44051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 44065a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber *confidence = 0.4f; 44071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 4408a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (moovAtomEndOffset >= 0) { 4409a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber *meta = new AMessage; 4410a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber (*meta)->setInt64("meta-data-size", moovAtomEndOffset); 4411a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 4412456caf3f5f0af673dc120c17c23635f40d8f5ac2Andreas Huber ALOGV("found metadata size: %lld", moovAtomEndOffset); 4413a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber } 4414a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber 44151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 44161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 44171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 44181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4( 44195a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 4420a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber sp<AMessage> *meta) { 4421a0f2bf56e30f580535229fa6a58e7d48b762727cAndreas Huber if (BetterSniffMPEG4(source, mimeType, confidence, meta)) { 44221b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 44231b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 44241b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 44251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (LegacySniffMPEG4(source, mimeType, confidence)) { 44265ff1dd576bb93c45b44088a51544a18fc43ebf58Steve Block ALOGW("Identified supported mpeg4 through LegacySniffMPEG4."); 44271b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 44281b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 44291b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 44301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 44311b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 44321b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 443320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 4434