MPEG4Extractor.cpp revision 1b52bd2874aef6c9cbc141f1cff5205830515f7d
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 1720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#define LOG_TAG "MPEG4Extractor" 1820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/Log.h> 1920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2066326a5ee0869f1ee4d136a477e6effba428b3cbAndreas Huber#include "include/MPEG4Extractor.h" 2189e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber#include "include/SampleTable.h" 2289e69da4d86348409994c9dafbbb2634ccd7c196Andreas Huber 2320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <arpa/inet.h> 2420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <ctype.h> 2620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdint.h> 2720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <stdlib.h> 2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <string.h> 2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/DataSource.h> 31ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#include "include/ESDS.h" 3220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBuffer.h> 3320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaBufferGroup.h> 34dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber#include <media/stagefright/MediaDebug.h> 3518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber#include <media/stagefright/MediaDefs.h> 3620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MediaSource.h> 3720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/MetaData.h> 3820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/Utils.h> 3920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <utils/String8.h> 4020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4120111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android { 4220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 4320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberclass MPEG4Source : public MediaSource { 4420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberpublic: 4520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Caller retains ownership of both "dataSource" and "sampleTable". 46693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber MPEG4Source(const sp<MetaData> &format, 47693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &dataSource, 4848c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int32_t timeScale, 49693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<SampleTable> &sampleTable); 5020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual status_t start(MetaData *params = NULL); 5220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual status_t stop(); 5320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual sp<MetaData> getFormat(); 5520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 5620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber virtual status_t read( 5720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 5820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huberprotected: 60693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber virtual ~MPEG4Source(); 61693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber 6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberprivate: 637b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex mLock; 647b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 6520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber sp<MetaData> mFormat; 66693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<DataSource> mDataSource; 6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t mTimescale; 68693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber sp<SampleTable> mSampleTable; 6920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t mCurrentSampleIndex; 7020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool mIsAVC; 726064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t mNALLengthSize; 736064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 7420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool mStarted; 7520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBufferGroup *mGroup; 7720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 7820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer *mBuffer; 7920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 80dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber bool mWantsNALFragments; 8120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 820024245e134467d120b40099da16c467dc365e76Andreas Huber uint8_t *mSrcBuffer; 830024245e134467d120b40099da16c467dc365e76Andreas Huber 846064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t parseNALSize(const uint8_t *data) const; 856064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Source(const MPEG4Source &); 8720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MPEG4Source &operator=(const MPEG4Source &); 8820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}; 8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 9050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This custom data source wraps an existing one and satisfies requests 9150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// falling entirely within a cached range from the cache while forwarding 9250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// all remaining requests to the wrapped datasource. 9350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// This is used to cache the full sampletable metadata for a single track, 9450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// possibly wrapping multiple times to cover all tracks, i.e. 9550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track. 9650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 9750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstruct MPEG4DataSource : public DataSource { 9850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber MPEG4DataSource(const sp<DataSource> &source); 9950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 10050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual status_t initCheck() const; 10150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual ssize_t readAt(off_t offset, void *data, size_t size); 10250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual status_t getSize(off_t *size); 10350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual uint32_t flags(); 10450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 10550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber status_t setCachedRange(off_t offset, size_t size); 10650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 10750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprotected: 10850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber virtual ~MPEG4DataSource(); 10950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 11050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberprivate: 11150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber Mutex mLock; 11250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 11350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber sp<DataSource> mSource; 11450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber off_t mCachedOffset; 11550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber size_t mCachedSize; 11650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber uint8_t *mCache; 11750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 11850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber void clearCache(); 11950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 12050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber MPEG4DataSource(const MPEG4DataSource &); 12150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber MPEG4DataSource &operator=(const MPEG4DataSource &); 12250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber}; 12350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 12450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source) 12550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber : mSource(source), 12650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedOffset(0), 12750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedSize(0), 12850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCache(NULL) { 12950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 13050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 13150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas HuberMPEG4DataSource::~MPEG4DataSource() { 13250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber clearCache(); 13350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 13450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 13550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Hubervoid MPEG4DataSource::clearCache() { 13650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (mCache) { 13750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber free(mCache); 13850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCache = NULL; 13950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 14050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 14150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedOffset = 0; 14250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedSize = 0; 14350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 14450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 14550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::initCheck() const { 14650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->initCheck(); 14750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 14850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 14950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberssize_t MPEG4DataSource::readAt(off_t offset, void *data, size_t size) { 15050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber Mutex::Autolock autoLock(mLock); 15150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 15250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (offset >= mCachedOffset 15350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber && offset + size <= mCachedOffset + mCachedSize) { 15450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber memcpy(data, &mCache[offset - mCachedOffset], size); 15550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return size; 15650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 15750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 15850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->readAt(offset, data, size); 15950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 16050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 16150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::getSize(off_t *size) { 16250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->getSize(size); 16350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 16450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 16550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberuint32_t MPEG4DataSource::flags() { 16650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return mSource->flags(); 16750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 16850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 16950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huberstatus_t MPEG4DataSource::setCachedRange(off_t offset, size_t size) { 17050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber Mutex::Autolock autoLock(mLock); 17150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 17250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber clearCache(); 17350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 17450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCache = (uint8_t *)malloc(size); 17550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 17650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (mCache == NULL) { 17750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return -ENOMEM; 17850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 17950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 18050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedOffset = offset; 18150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mCachedSize = size; 18250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 18350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize); 18450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 18550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (err < (ssize_t)size) { 18650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber clearCache(); 18750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 18850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return ERROR_IO; 18950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 19050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 19150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber return OK; 19250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber} 19350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 19450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber//////////////////////////////////////////////////////////////////////////////// 19550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 19620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void hexdump(const void *_data, size_t size) { 19720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const uint8_t *data = (const uint8_t *)_data; 19820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t offset = 0; 19920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (offset < size) { 20020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("0x%04x ", offset); 20120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber size_t n = size - offset; 20320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (n > 16) { 20420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber n = 16; 20520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 20620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 20720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (size_t i = 0; i < 16; ++i) { 20820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (i == 8) { 20920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf(" "); 21020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (offset + i < size) { 21320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("%02x ", data[offset + i]); 21420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 21520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf(" "); 21620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 21820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 21920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf(" "); 22020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (size_t i = 0; i < n; ++i) { 22220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (isprint(data[offset + i])) { 22320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("%c", data[offset + i]); 22420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 22520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("."); 22620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 22720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 22820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 22920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("\n"); 23020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber offset += 16; 23220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 23320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 23420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 23518291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) { 23620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber switch (fourcc) { 23720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'a'): 23818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_AUDIO_AAC; 23920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 24118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_AUDIO_AMR_NB; 24220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 243371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber case FOURCC('s', 'a', 'w', 'b'): 24418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_AUDIO_AMR_WB; 245371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber 24620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'v'): 24718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_VIDEO_MPEG4; 24820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 24920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', '2', '6', '3'): 25018291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_VIDEO_H263; 25120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 25220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', '1'): 25318291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber return MEDIA_MIMETYPE_VIDEO_AVC; 25420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 25520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber default: 256dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(!"should not be here."); 25720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 25820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 25920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 26020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 261693d271e62a3726689ff68f4505ba49228eb94b2Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source) 26220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mDataSource(source), 26320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mHaveMetadata(false), 2647be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber mHasVideo(false), 26520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFirstTrack(NULL), 26672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mLastTrack(NULL), 26772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData(new MetaData) { 26820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 26920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27020111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Extractor::~MPEG4Extractor() { 27120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 27220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (track) { 27320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *next = track->next; 27420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 27520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete track; 27620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = next; 27720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 27820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mFirstTrack = mLastTrack = NULL; 27920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 28020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 2817be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() { 2827be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber status_t err; 2837be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber if ((err = readMetaData()) != OK) { 28472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return new MetaData; 2857be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber } 2867be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 28772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return mFileMetaData; 2887be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber} 2897be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 290693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersize_t MPEG4Extractor::countTracks() { 29120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 29220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 293693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return 0; 29420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 29520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 296693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber size_t n = 0; 29720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 29820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (track) { 299693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber ++n; 30020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 30120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 30220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 303693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return n; 30420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 30520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 3067e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData( 3077e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber size_t index, uint32_t flags) { 30820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 30920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 31020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 31120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 31220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 31420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (index > 0) { 31520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (track == NULL) { 31620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return NULL; 31720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 31820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 31920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 32020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber --index; 32120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 32220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 323371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber if (track == NULL) { 324371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber return NULL; 325371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber } 326371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber 3277e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber if ((flags & kIncludeExtensiveMetaData) 3287e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber && !track->includes_expensive_metadata) { 3297e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber track->includes_expensive_metadata = true; 3307e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 3317e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber const char *mime; 3327e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 3337e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber if (!strncasecmp("video/", mime, 6)) { 3347e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber uint32_t sampleIndex; 3357e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber uint32_t sampleTime; 3367e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK 337c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber && track->sampleTable->getMetaDataForSample( 338c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber sampleIndex, NULL /* offset */, NULL /* size */, 339c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber &sampleTime) == OK) { 3407e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber track->meta->setInt64( 3417e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber kKeyThumbnailTime, 3427e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber ((int64_t)sampleTime * 1000000) / track->timescale); 3437e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 3447e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 3457e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber } 3467e04dcf8d6784dd56f53aa90bf34431ab4f0710cAndreas Huber 34720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return track->meta; 34820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 34920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::readMetaData() { 35120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mHaveMetadata) { 35220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 35320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 35420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 35520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t offset = 0; 35620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 35720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while ((err = parseChunk(&offset, 0)) == OK) { 35820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 3597be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 36020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mHaveMetadata) { 36172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mHasVideo) { 36272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyMIMEType, "video/mp4"); 36372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 36472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyMIMEType, "audio/mp4"); 36572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 36672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 36720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 36820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 36920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 37120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 37220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 37320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatic void MakeFourCCString(uint32_t x, char *s) { 37420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber s[0] = x >> 24; 37520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber s[1] = (x >> 16) & 0xff; 37620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber s[2] = (x >> 8) & 0xff; 37720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber s[3] = x & 0xff; 37820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber s[4] = '\0'; 37920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 38020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 38172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstruct PathAdder { 38272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder(Vector<uint32_t> *path, uint32_t chunkType) 38372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber : mPath(path) { 38472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mPath->push(chunkType); 38572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 38672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 38772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber ~PathAdder() { 38872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mPath->pop(); 38972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 39072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 39172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberprivate: 39272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber Vector<uint32_t> *mPath; 39372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 39472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder(const PathAdder &); 39572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder &operator=(const PathAdder &); 39672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber}; 39772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 39872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) { 39972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return path.size() >= 5 40072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[0] == FOURCC('m', 'o', 'o', 'v') 40172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[1] == FOURCC('u', 'd', 't', 'a') 40272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[2] == FOURCC('m', 'e', 't', 'a') 40372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && path[3] == FOURCC('i', 'l', 's', 't'); 40472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 40572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 40672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string. 40772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) { 40872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600); 40972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 41072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char tmp[32]; 41172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970)); 41272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 41372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber s->setTo(tmp); 41472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 41572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 41620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { 41720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t hdr[2]; 41834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt(*offset, hdr, 8) < 8) { 41920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 42020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 42120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint64_t chunk_size = ntohl(hdr[0]); 42220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t chunk_type = ntohl(hdr[1]); 42320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t data_offset = *offset + 8; 42420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 42520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_size == 1) { 42634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { 42720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 42820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 42920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_size = ntoh64(chunk_size); 43020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset += 8; 43120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 43220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 43320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber char chunk[5]; 43420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MakeFourCCString(chunk_type, chunk); 43520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 43620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#if 0 43720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber static const char kWhitespace[] = " "; 43820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth]; 43920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size); 44020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 44120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber char buffer[256]; 442ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber size_t n = chunk_size; 443ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber if (n > sizeof(buffer)) { 444ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber n = sizeof(buffer); 445ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber } 446ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber if (mDataSource->readAt(*offset, buffer, n) 447ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber < (ssize_t)n) { 448ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber return ERROR_IO; 44920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 450ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber 451ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber hexdump(buffer, n); 45220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#endif 45320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber PathAdder autoAdder(&mPath, chunk_type); 45572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 45620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t chunk_data_size = *offset + chunk_size - data_offset; 45720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 45872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (chunk_type != FOURCC('c', 'p', 'r', 't') 45972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber && mPath.size() == 5 && underMetaDataPath(mPath)) { 46072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber off_t stop_offset = *offset + chunk_size; 46172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset = data_offset; 46272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber while (*offset < stop_offset) { 46372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseChunk(offset, depth + 1); 46472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 46572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 46672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 46772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 468bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 469bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 470bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 471bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 47272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 47372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return OK; 47472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 47572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 47620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber switch(chunk_type) { 47720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'o', 'o', 'v'): 47820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'r', 'a', 'k'): 47920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'd', 'i', 'a'): 48020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'i', 'n', 'f'): 48120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('d', 'i', 'n', 'f'): 48220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'b', 'l'): 48320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'v', 'e', 'x'): 48420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'o', 'o', 'f'): 48520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'r', 'a', 'f'): 48620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'f', 'r', 'a'): 48720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 'k', 'i' ,'p'): 48872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('u', 'd', 't', 'a'): 48972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('i', 'l', 's', 't'): 49020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 49150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (chunk_type == FOURCC('s', 't', 'b', 'l')) { 49250a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size); 49350a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 49450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (mDataSource->flags() & DataSource::kWantsPrefetching) { 49550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber sp<MPEG4DataSource> cachedSource = 49650a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber new MPEG4DataSource(mDataSource); 49750a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 49850a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber if (cachedSource->setCachedRange(*offset, chunk_size) == OK) { 49950a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber mDataSource = cachedSource; 50050a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 50150a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 5021edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber 5031edbcb2bb9988cc7cb54a865aaea4613bdd53a9dAndreas Huber mLastTrack->sampleTable = new SampleTable(mDataSource); 50450a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber } 50550a9976892316c033cd90d522ecbfcc8e3c0eb9bAndreas Huber 5066f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber bool isTrack = false; 507bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (chunk_type == FOURCC('t', 'r', 'a', 'k')) { 5086f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber isTrack = true; 5096f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 510bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber Track *track = new Track; 511bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->next = NULL; 512bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (mLastTrack) { 513bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber mLastTrack->next = track; 514bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else { 515bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber mFirstTrack = track; 516bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 517bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber mLastTrack = track; 518bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 519bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->meta = new MetaData; 520bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->includes_expensive_metadata = false; 5216f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber track->skipTrack = false; 522bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->timescale = 0; 523bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber track->meta->setCString(kKeyMIMEType, "application/octet-stream"); 524bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 525bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 52620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t stop_offset = *offset + chunk_size; 52720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset; 52820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 52920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 53020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 53120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 53220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 53320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 53420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 535bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 536bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 537bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 538bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 5396f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber if (isTrack) { 5406f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber if (mLastTrack->skipTrack) { 5416f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber Track *cur = mFirstTrack; 5426f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 5436f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber if (cur == mLastTrack) { 5446f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber delete cur; 5456f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber mFirstTrack = mLastTrack = NULL; 5466f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } else { 5476f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber while (cur && cur->next != mLastTrack) { 5486f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber cur = cur->next; 5496f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } 5506f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber cur->next = NULL; 5516f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber delete mLastTrack; 5526f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber mLastTrack = cur; 5536f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } 5546f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 5556f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber return OK; 5566f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber } 5576f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 558bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber status_t err = verifyTrack(mLastTrack); 559bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 560bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (err != OK) { 561bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return err; 562bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 563bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { 56420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mHaveMetadata = true; 56520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 56620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return UNKNOWN_ERROR; // Return a dummy error. 56720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 56820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 56920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 57020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('t', 'k', 'h', 'd'): 57220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 573bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (chunk_data_size < 4) { 574bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 575bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 57620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 57720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t version; 57834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt(data_offset, &version, 1) < 1) { 57920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 58020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 58120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint64_t ctime, mtime, duration; 58320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t id; 58420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t width, height; 58520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 58620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (version == 1) { 58720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size != 36 + 60) { 58820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 58920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 59020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[36 + 60]; 59234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 59320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 59420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 59520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 59620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 59720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ctime = U64_AT(&buffer[4]); 59820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mtime = U64_AT(&buffer[12]); 59920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber id = U32_AT(&buffer[20]); 60020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber duration = U64_AT(&buffer[28]); 60120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber width = U32_AT(&buffer[88]); 60220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber height = U32_AT(&buffer[92]); 60320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else if (version == 0) { 60420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size != 24 + 60) { 60520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 60620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 60720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 60820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[24 + 60]; 60934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 61020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 61120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 61220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 61320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ctime = U32_AT(&buffer[4]); 61420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mtime = U32_AT(&buffer[8]); 61520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber id = U32_AT(&buffer[12]); 61620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber duration = U32_AT(&buffer[20]); 61720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber width = U32_AT(&buffer[76]); 61820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber height = U32_AT(&buffer[80]); 61920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 62020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 62220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 62320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 62420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 62520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'd', 'h', 'd'): 62620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 62720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 4) { 62820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 62920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 63020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 63120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t version; 63234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 63320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, &version, sizeof(version)) 63420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(version)) { 63520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 63620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 63720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 63820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t timescale_offset; 63920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 64020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (version == 1) { 64120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset = data_offset + 4 + 16; 64220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else if (version == 0) { 64320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset = data_offset + 4 + 8; 64420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 64520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 64620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 64720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 64820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t timescale; 64934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 65020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset, ×cale, sizeof(timescale)) 65120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(timescale)) { 65220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 65320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 65420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 65520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->timescale = ntohl(timescale); 65620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 65720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t duration; 65820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (version == 1) { 65934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 66020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset + 4, &duration, sizeof(duration)) 66120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(duration)) { 66220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 66320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 66420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber duration = ntoh64(duration); 66520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 66620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t duration32; 66734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 66820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber timescale_offset + 4, &duration32, sizeof(duration32)) 66920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber < (ssize_t)sizeof(duration32)) { 67020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 67120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 67220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber duration = ntohl(duration32); 67320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 67448c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mLastTrack->meta->setInt64( 67548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber kKeyDuration, (duration * 1000000) / mLastTrack->timescale); 67620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 67720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 67820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 67920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 68020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 68120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'd'): 68220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 68320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 8) { 68420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 68520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 68620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 68720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[8]; 688bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (chunk_data_size < (off_t)sizeof(buffer)) { 689bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 690bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 691bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 69234769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 69320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, 8) < 8) { 69420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 69520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 69620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 69720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (U32_AT(buffer) != 0) { 69820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Should be version 0, flags 0. 69920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 70020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 70120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 70220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t entry_count = U32_AT(&buffer[4]); 70320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 70420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (entry_count > 1) { 70520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // For now we only support a single type of media per track. 7066f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber 7076f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber mLastTrack->skipTrack = true; 7086f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber *offset += chunk_size; 7096f3a0c2dcb8d37d34e29e6a02acf1e3f8596088cAndreas Huber break; 71020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 71120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 71220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t stop_offset = *offset + chunk_size; 71320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + 8; 71420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber for (uint32_t i = 0; i < entry_count; ++i) { 71520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 71620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 71720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 71820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 71920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 720bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 721bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 722bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 723bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 72420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 72520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 72620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 72720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'a'): 72820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 729371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber case FOURCC('s', 'a', 'w', 'b'): 73020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 73120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[8 + 20]; 73220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 73320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Basic AudioSampleEntry size. 73420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 73520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 73620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 73734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 73820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 73920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 74020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 74120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 74320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t num_channels = U16_AT(&buffer[16]); 74420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 74581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint16_t sample_size = U16_AT(&buffer[18]); 74681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint32_t sample_rate = U32_AT(&buffer[24]) >> 16; 74781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 74818291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, 74981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber FourCC2MIME(chunk_type))) { 75081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber // AMR NB audio is always mono, 8kHz 75181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber num_channels = 1; 75281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber sample_rate = 8000; 75381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, 75418291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber FourCC2MIME(chunk_type))) { 75581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber // AMR WB audio is always mono, 16kHz 75620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber num_channels = 1; 75781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber sample_rate = 16000; 75820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 75920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber#if 0 76181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber printf("*** coding='%s' %d channels, size %d, rate %d\n", 76281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber chunk, num_channels, sample_size, sample_rate); 76381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber#endif 76420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 76620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 76720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 76820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 76920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t stop_offset = *offset + chunk_size; 77020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + sizeof(buffer); 77120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 77220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 77320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 77420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 77520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 77620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 777bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 778bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 779bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 780bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 78120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 78220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 78320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 78420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('m', 'p', '4', 'v'): 78520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', '2', '6', '3'): 78620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', '1'): 78720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 7887be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber mHasVideo = true; 7897be6407f2ad7f2b0782d195d9f792072c084d6f5Andreas Huber 79020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[78]; 79120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 79220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Basic VideoSampleEntry size. 79320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 79420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 79520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 79634769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 79720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 79820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 79920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 80020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 80120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 80220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t width = U16_AT(&buffer[6 + 18]); 80320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint16_t height = U16_AT(&buffer[6 + 20]); 80420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 805134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber // printf("*** coding='%s' width=%d height=%d\n", 806134ee6a324c35f39e3576172e4eae4c6de6eb9dcAndreas Huber // chunk, width, height); 80720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 80820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 80920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyWidth, width); 81020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setInt32(kKeyHeight, height); 81120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 81220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber off_t stop_offset = *offset + chunk_size; 81320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset = data_offset + sizeof(buffer); 81420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (*offset < stop_offset) { 81520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = parseChunk(offset, depth + 1); 81620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 81720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 81820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 81920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 820bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 821bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 822bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 823bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 82420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 82520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 82620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 82720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'c', 'o'): 82820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('c', 'o', '6', '4'): 82920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 83020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 83120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setChunkOffsetParams( 83220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_type, data_offset, chunk_data_size); 83320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 83420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 83520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 83620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 83720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 83820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 83920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 84020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 84120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 84220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'c'): 84320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 84420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 84520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSampleToChunkParams( 84620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 84720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 84820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 84920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 85020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 85120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 85220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 85320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 85420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 85520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 85620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 'z'): 85720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 'z', '2'): 85820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 85920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 86020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSampleSizeParams( 86120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber chunk_type, data_offset, chunk_data_size); 86220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 86320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 86420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 86520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 86620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 867738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber size_t max_size; 868738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber CHECK_EQ(mLastTrack->sampleTable->getMaxSampleSize(&max_size), OK); 869738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber 870738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber // Assume that a given buffer only contains at most 10 fragments, 871738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber // each fragment originally prefixed with a 2 byte length will 872738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion, 873738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber // and thus will grow by 2 bytes per fragment. 874738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2); 875738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber 87620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 87720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 87820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 87920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 88020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 't', 's'): 88120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 88220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 88320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setTimeToSampleParams( 88420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 88520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 88620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 88720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 88820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 88920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 89020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 89120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 89220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 89320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 89420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('s', 't', 's', 's'): 89520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 89620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = 89720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->sampleTable->setSyncSampleParams( 89820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, chunk_data_size); 89920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 90020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 90120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 90220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 90320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 90420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 90520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 90620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 90720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 90820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('e', 's', 'd', 's'): 90920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 91020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size < 4) { 91120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 91220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 91320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 91420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t buffer[256]; 91520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size > (off_t)sizeof(buffer)) { 91620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_BUFFER_TOO_SMALL; 91720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 91820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 91934769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 92020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 92120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 92220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 92320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 92420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (U32_AT(buffer) != 0) { 92520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // Should be version 0, flags 0. 92620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_MALFORMED; 92720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 92820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 92920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setData( 93020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); 93120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 932ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (mPath.size() >= 2 933ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) { 934ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // Information from the ESDS must be relied on for proper 935ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // setup of sample rate and channel count for MPEG4 Audio. 936ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // The generic header appears to only contain generic 937ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber // information... 938ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 939ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio( 940ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber &buffer[4], chunk_data_size - 4); 941ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 942ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (err != OK) { 943ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return err; 944ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 945ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 946ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 94720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 94820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 94920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 95020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber case FOURCC('a', 'v', 'c', 'C'): 95220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 95320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber char buffer[256]; 95420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (chunk_data_size > (off_t)sizeof(buffer)) { 95520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_BUFFER_TOO_SMALL; 95620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 95720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 95834769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber if (mDataSource->readAt( 95920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 96020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return ERROR_IO; 96120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 96220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 96320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mLastTrack->meta->setData( 96420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber kKeyAVCC, kTypeAVCC, buffer, chunk_data_size); 96520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 96620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 96720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 96820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 96920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 97072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('m', 'e', 't', 'a'): 97172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 97272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint8_t buffer[4]; 973bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (chunk_data_size < (off_t)sizeof(buffer)) { 974bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 975bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 976bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 97772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 97872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber data_offset, buffer, 4) < 4) { 97972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 98072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 98172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 98272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (U32_AT(buffer) != 0) { 98372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber // Should be version 0, flags 0. 984ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber 985ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // If it's not, let's assume this is one of those 986ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // apparently malformed chunks that don't have flags 987ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // and completely different semantics than what's 988ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber // in the MPEG4 specs and skip it. 989ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber *offset += chunk_size; 990ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber return OK; 99172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 99272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 99372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber off_t stop_offset = *offset + chunk_size; 99472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset = data_offset + sizeof(buffer); 99572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber while (*offset < stop_offset) { 99672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseChunk(offset, depth + 1); 99772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 99872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 99972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 100072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 1001bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1002bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (*offset != stop_offset) { 1003bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1004bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 100572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 100672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 100772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 100872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('d', 'a', 't', 'a'): 100972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 101072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mPath.size() == 6 && underMetaDataPath(mPath)) { 101172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber status_t err = parseMetaData(data_offset, chunk_data_size); 101272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 101372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (err != OK) { 101472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return err; 101572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 101672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 101772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 101872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset += chunk_size; 101972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 102072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 102172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 102272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('m', 'v', 'h', 'd'): 102372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 102472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (chunk_data_size < 12) { 102572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_MALFORMED; 102672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 102772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 102872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint8_t header[12]; 102972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 103072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber data_offset, header, sizeof(header)) 103172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber < (ssize_t)sizeof(header)) { 103272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 103372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 103472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 103572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber int64_t creationTime; 103672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (header[0] == 1) { 103772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber creationTime = U64_AT(&header[4]); 1038bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (header[0] != 0) { 1039bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 104072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 104172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber creationTime = U32_AT(&header[4]); 104272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 104372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 104472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber String8 s; 104572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber convertTimeToDate(creationTime, &s); 104672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 104772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyDate, s.string()); 104872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 104972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber *offset += chunk_size; 105072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 105172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 105272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 105320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber default: 105420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber { 105520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *offset += chunk_size; 105620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber break; 105720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 105820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 105920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 106020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 106120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 106220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 106372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huberstatus_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) { 106472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (size < 4) { 106572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_MALFORMED; 106672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 106772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 106872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint8_t *buffer = new uint8_t[size + 1]; 106972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (mDataSource->readAt( 107072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber offset, buffer, size) != (ssize_t)size) { 107172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber delete[] buffer; 107272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer = NULL; 107372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 107472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return ERROR_IO; 107572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 107672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 107772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint32_t flags = U32_AT(buffer); 107872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 107972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber uint32_t metadataKey = 0; 108072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber switch (mPath[4]) { 108172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'a', 'l', 'b'): 108272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 108372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyAlbum; 108472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 108572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 108672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'A', 'R', 'T'): 108772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 108872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyArtist; 108972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 109072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 109166ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen case FOURCC('a', 'A', 'R', 'T'): 109266ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen { 109366ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen metadataKey = kKeyAlbumArtist; 109466ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen break; 109566ac4df65516ebfd0e500bfca75dc4b5ef8d674eMarco Nelissen } 109672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'd', 'a', 'y'): 109772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 109872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyYear; 109972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 110072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 110172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'n', 'a', 'm'): 110272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 110372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyTitle; 110472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 110572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 110672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC(0xa9, 'w', 'r', 't'): 110772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 110872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyWriter; 110972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 111072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 111172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('c', 'o', 'v', 'r'): 111272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 111372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyAlbumArt; 111472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 111572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 111672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('g', 'n', 'r', 'e'): 111772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 111872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey = kKeyGenre; 111972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 112072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 112126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen case FOURCC(0xa9, 'g', 'e', 'n'): 112226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen { 112326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen metadataKey = kKeyGenre; 112426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen break; 112526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 112672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber case FOURCC('t', 'r', 'k', 'n'): 112772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber { 112872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (size == 16 && flags == 0) { 112972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char tmp[16]; 113072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber sprintf(tmp, "%d/%d", 113172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber (int)buffer[size - 5], (int)buffer[size - 3]); 113272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 113372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(kKeyCDTrackNumber, tmp); 113472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 113572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 113672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 113726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen case FOURCC('d', 'i', 's', 'k'): 113826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen { 113926bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen if (size == 14 && flags == 0) { 114026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen char tmp[16]; 114126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen sprintf(tmp, "%d/%d", 114226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen (int)buffer[size - 3], (int)buffer[size - 1]); 114326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 114426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen mFileMetaData->setCString(kKeyDiscNumber, tmp); 114526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 114626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen break; 114726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 114826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 114972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber default: 115072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber break; 115172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 115272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 115372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (size >= 8 && metadataKey) { 115472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (metadataKey == kKeyAlbumArt) { 115572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setData( 115672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber kKeyAlbumArt, MetaData::TYPE_NONE, 115772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer + 8, size - 8); 115872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else if (metadataKey == kKeyGenre) { 115972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber if (flags == 0) { 116026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // uint8_t genre code, iTunes genre codes are 116126bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // the standard id3 codes, except they start 116226bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // at 1 instead of 0 (e.g. Pop is 14, not 13) 116326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // We use standard id3 numbering, so subtract 1. 116426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen int genrecode = (int)buffer[size - 1]; 116526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen genrecode--; 116626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen if (genrecode < 0) { 116726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen genrecode = 255; // reserved for 'unknown genre' 116826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } 116972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber char genre[10]; 117026bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen sprintf(genre, "%d", genrecode); 117172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 117272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString(metadataKey, genre); 117326bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen } else if (flags == 1) { 117426bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen // custom genre string 117526bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen buffer[size] = '\0'; 117626bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen 117726bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen mFileMetaData->setCString( 117826bae54d7a3d04215eba34c62c349f1be6ab1493Marco Nelissen metadataKey, (const char *)buffer + 8); 117972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 118072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } else { 118172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer[size] = '\0'; 118272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 118372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber mFileMetaData->setCString( 118472b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber metadataKey, (const char *)buffer + 8); 118572b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 118672b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber } 118772b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 118872b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber delete[] buffer; 118972b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber buffer = NULL; 119072b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 119172b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber return OK; 119272b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber} 119372b8c5ae6a5f97a4fcfc6d23d33159d6ae50179cAndreas Huber 1194693d271e62a3726689ff68f4505ba49228eb94b2Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) { 119520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err; 119620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if ((err = readMetaData()) != OK) { 1197693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return NULL; 119820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 119920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber Track *track = mFirstTrack; 120120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber while (index > 0) { 120220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (track == NULL) { 1203693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return NULL; 120420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 120520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 120620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber track = track->next; 120720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber --index; 120820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 120920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1210371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber if (track == NULL) { 1211371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber return NULL; 1212371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber } 1213371e243b6638e74e577d56a24eee7d5a97e36d2bAndreas Huber 1214693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber return new MPEG4Source( 121548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber track->meta, mDataSource, track->timescale, track->sampleTable); 121620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 121720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1218bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber// static 1219bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) { 1220bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber const char *mime; 1221bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 1222bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1223bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber uint32_t type; 1224bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber const void *data; 1225bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber size_t size; 1226bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 1227bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!track->meta->findData(kKeyAVCC, &type, &data, &size) 1228bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || type != kTypeAVCC) { 1229bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1230bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 1231bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 1232bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 1233bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber if (!track->meta->findData(kKeyESDS, &type, &data, &size) 1234bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber || type != kTypeESDS) { 1235bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return ERROR_MALFORMED; 1236bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 1237bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber } 1238bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1239bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber return OK; 1240bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber} 1241bd5d93f21e6f79c6d9ebe9d77542c3090d4a7ff4Andreas Huber 1242ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( 1243ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber const void *esds_data, size_t esds_size) { 1244ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber ESDS esds(esds_data, esds_size); 124581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 124681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber uint8_t objectTypeIndication; 124781f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) { 124881f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber return ERROR_MALFORMED; 124981f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber } 125081f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 125181f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber if (objectTypeIndication == 0xe1) { 125281f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber // This isn't MPEG4 audio at all, it's QCELP 14k... 125381f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP); 125481f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber return OK; 125581f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber } 125681f82c32459029bf0744e28c73f95a7f18cab5acAndreas Huber 1257ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber const uint8_t *csd; 1258ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber size_t csd_size; 1259ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (esds.getCodecSpecificInfo( 1260ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber (const void **)&csd, &csd_size) != OK) { 1261ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 1262ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1263ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1264ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#if 0 1265ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber printf("ESD of size %d\n", csd_size); 1266ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber hexdump(csd, csd_size); 1267ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber#endif 1268ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1269ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (csd_size < 2) { 1270ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 1271ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1272ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1273ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber uint32_t objectType = csd[0] >> 3; 1274ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1275ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (objectType == 31) { 1276ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_UNSUPPORTED; 1277ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1278ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1279ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7); 1280ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t sampleRate = 0; 1281ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t numChannels = 0; 1282ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (freqIndex == 15) { 1283ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (csd_size < 5) { 1284ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 1285ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1286ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1287ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber sampleRate = (csd[1] & 0x7f) << 17 1288ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber | csd[2] << 9 1289ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber | csd[3] << 1 1290ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber | (csd[4] >> 7); 1291ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1292ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber numChannels = (csd[4] >> 3) & 15; 1293ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } else { 1294ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber static uint32_t kSamplingRate[] = { 1295ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 1296ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 16000, 12000, 11025, 8000, 7350 1297ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber }; 1298ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1299ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (freqIndex == 13 || freqIndex == 14) { 1300ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_MALFORMED; 1301ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1302ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1303ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber sampleRate = kSamplingRate[freqIndex]; 1304ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber numChannels = (csd[1] >> 3) & 15; 1305ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1306ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1307ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (numChannels == 0) { 1308ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return ERROR_UNSUPPORTED; 1309ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1310ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1311ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t prevSampleRate; 1312ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate)); 1313ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1314ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (prevSampleRate != sampleRate) { 1315ec9dd59902c8beea4ba6a842f3a843d46150d949Andreas Huber LOGV("mpeg4 audio sample rate different from previous setting. " 1316ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber "was: %d, now: %d", prevSampleRate, sampleRate); 1317ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1318ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1319ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sampleRate); 1320ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1321ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber int32_t prevChannelCount; 1322ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount)); 1323ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1324ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber if (prevChannelCount != numChannels) { 1325ec9dd59902c8beea4ba6a842f3a843d46150d949Andreas Huber LOGV("mpeg4 audio channel count different from previous setting. " 1326ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber "was: %d, now: %d", prevChannelCount, numChannels); 1327ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber } 1328ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1329ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, numChannels); 1330ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 1331ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber return OK; 1332ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber} 1333ba7c7eeca462614251aec3d27f0f7ff3a83cefa1Andreas Huber 133420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber//////////////////////////////////////////////////////////////////////////////// 133520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 133620111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::MPEG4Source( 133720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const sp<MetaData> &format, 1338693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &dataSource, 133948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber int32_t timeScale, 1340693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<SampleTable> &sampleTable) 134120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber : mFormat(format), 134220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mDataSource(dataSource), 134348c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mTimescale(timeScale), 134420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mSampleTable(sampleTable), 134520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCurrentSampleIndex(0), 134620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mIsAVC(false), 13476064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mNALLengthSize(0), 134820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted(false), 134920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup(NULL), 135020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer(NULL), 1351dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments(false), 13520024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer(NULL) { 135320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber const char *mime; 135420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber bool success = mFormat->findCString(kKeyMIMEType, &mime); 1355dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(success); 135620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 135718291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 13586064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 13596064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber if (mIsAVC) { 13606064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber uint32_t type; 13616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber const void *data; 13626064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t size; 13636064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(format->findData(kKeyAVCC, &type, &data, &size)); 13646064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 13656064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber const uint8_t *ptr = (const uint8_t *)data; 13666064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 13676064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(size >= 7); 13686064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK_EQ(ptr[0], 1); // configurationVersion == 1 13696064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 13706064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // The number of bytes used to encode the length of a NAL unit. 13716064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mNALLengthSize = 1 + (ptr[4] & 3); 13726064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber } 137320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 137420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 137520111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberMPEG4Source::~MPEG4Source() { 137620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mStarted) { 137720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber stop(); 137820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 137920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 138020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 138120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::start(MetaData *params) { 13827b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 13837b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 1384dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(!mStarted); 138520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 138620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int32_t val; 1387dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (params && params->findInt32(kKeyWantsNALFragments, &val) 138820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber && val != 0) { 1389dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments = true; 139020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } else { 1391dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mWantsNALFragments = false; 139220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 139320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 139420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup = new MediaBufferGroup; 139520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1396738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber int32_t max_size; 1397738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size)); 139820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1399738c4315859395bfeeaae3d4c9d6fb9f414778f1Andreas Huber mGroup->add_buffer(new MediaBuffer(max_size)); 14000024245e134467d120b40099da16c467dc365e76Andreas Huber 14010024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer = new uint8_t[max_size]; 140220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 140320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = true; 140420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 140520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 140620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 140720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 140820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::stop() { 14097b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 14107b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 1411dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(mStarted); 141220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 141320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mBuffer != NULL) { 141420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 141520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 141620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 141720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14180024245e134467d120b40099da16c467dc365e76Andreas Huber delete[] mSrcBuffer; 14190024245e134467d120b40099da16c467dc365e76Andreas Huber mSrcBuffer = NULL; 14200024245e134467d120b40099da16c467dc365e76Andreas Huber 142120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber delete mGroup; 142220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mGroup = NULL; 142320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 142420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mStarted = false; 142520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCurrentSampleIndex = 0; 142620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 142720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 142820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 142920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 143020111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubersp<MetaData> MPEG4Source::getFormat() { 14317b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 14327b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 143320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return mFormat; 143420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 143520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14366064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const { 14376064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber switch (mNALLengthSize) { 14386064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 1: 14396064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return *data; 14406064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 2: 14416064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return U16_AT(data); 14426064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 3: 14436064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return ((size_t)data[0] << 16) | U16_AT(&data[1]); 14446064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber case 4: 14456064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return U32_AT(data); 14466064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber } 14476064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 14486064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // This cannot happen, mNALLengthSize springs to life by adding 1 to 14496064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber // a 2-bit integer. 14506064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(!"Should not be here."); 14516064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 14526064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber return 0; 14536064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber} 14546064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 145520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huberstatus_t MPEG4Source::read( 145620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber MediaBuffer **out, const ReadOptions *options) { 14577b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber Mutex::Autolock autoLock(mLock); 14587b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber 1459dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(mStarted); 146020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 146120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *out = NULL; 146220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 146320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber int64_t seekTimeUs; 146420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (options && options->getSeekTo(&seekTimeUs)) { 146520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint32_t sampleIndex; 146620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber status_t err = mSampleTable->findClosestSample( 146720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber seekTimeUs * mTimescale / 1000000, 146820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber &sampleIndex, SampleTable::kSyncSample_Flag); 146920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 147020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (err != OK) { 14715295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber if (err == ERROR_OUT_OF_RANGE) { 14725295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // An attempt to seek past the end of the stream would 14735295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // normally cause this ERROR_OUT_OF_RANGE error. Propagating 14745295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // this all the way to the MediaPlayer would cause abnormal 14755295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // termination. Legacy behaviour appears to be to behave as if 14765295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber // we had seeked to the end of stream, ending normally. 14775295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber err = ERROR_END_OF_STREAM; 14785295c0c55d41a2906ea7f65a3f22e6278cb17d4bAndreas Huber } 147920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return err; 148020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 148120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 148220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mCurrentSampleIndex = sampleIndex; 148320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (mBuffer != NULL) { 148420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 148520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 148620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 148720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 148820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber // fall through 148920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 149020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 14910024245e134467d120b40099da16c467dc365e76Andreas Huber off_t offset; 14920024245e134467d120b40099da16c467dc365e76Andreas Huber size_t size; 1493dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber uint32_t dts; 1494dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber bool newBuffer = false; 1495dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (mBuffer == NULL) { 1496dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber newBuffer = true; 149720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1498c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber status_t err = 1499c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber mSampleTable->getMetaDataForSample( 1500c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber mCurrentSampleIndex, &offset, &size, &dts); 150120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1502dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (err != OK) { 1503dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return err; 1504dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 1505dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1506dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber err = mGroup->acquire_buffer(&mBuffer); 1507c57b67905c2128ddadfeca96785ee1f593b6605aAndreas Huber 1508dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (err != OK) { 1509dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK_EQ(mBuffer, NULL); 1510dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return err; 1511dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 15120024245e134467d120b40099da16c467dc365e76Andreas Huber } 151320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1514dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (!mIsAVC || mWantsNALFragments) { 1515dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (newBuffer) { 1516dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber ssize_t num_bytes_read = 151734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 1518dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1519dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (num_bytes_read < (ssize_t)size) { 1520dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->release(); 1521dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 1522dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1523dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return ERROR_IO; 1524dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 1525dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 15267b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(mBuffer != NULL); 1527dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->set_range(0, size); 1528dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->meta_data()->clear(); 152948c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mBuffer->meta_data()->setInt64( 153048c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber kKeyTime, ((int64_t)dts * 1000000) / mTimescale); 1531dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber ++mCurrentSampleIndex; 1532dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 1533dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1534dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (!mIsAVC) { 1535dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber *out = mBuffer; 1536dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 1537dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1538dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return OK; 1539dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 1540dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1541dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // Each NAL unit is split up into its constituent fragments and 1542dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // each one of them returned in its own buffer. 1543dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 15446064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(mBuffer->range_length() >= mNALLengthSize); 1545dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1546dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber const uint8_t *src = 1547dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 1548dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 15496064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t nal_size = parseNALSize(src); 1550e8a084958c27327b0aca749f69095605d2a21309Andreas Huber if (mBuffer->range_length() < mNALLengthSize + nal_size) { 1551e8a084958c27327b0aca749f69095605d2a21309Andreas Huber LOGE("incomplete NAL unit."); 1552e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 1553e8a084958c27327b0aca749f69095605d2a21309Andreas Huber mBuffer->release(); 1554e8a084958c27327b0aca749f69095605d2a21309Andreas Huber mBuffer = NULL; 1555e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 1556e8a084958c27327b0aca749f69095605d2a21309Andreas Huber return ERROR_MALFORMED; 1557e8a084958c27327b0aca749f69095605d2a21309Andreas Huber } 1558dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1559dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber MediaBuffer *clone = mBuffer->clone(); 15607b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(clone != NULL); 15616064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 1562dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 15637b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(mBuffer != NULL); 1564dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->set_range( 15656064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mBuffer->range_offset() + mNALLengthSize + nal_size, 15666064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber mBuffer->range_length() - mNALLengthSize - nal_size); 1567dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1568dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (mBuffer->range_length() == 0) { 1569dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->release(); 1570dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer = NULL; 1571dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 1572dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1573dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber *out = clone; 1574dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1575dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return OK; 1576dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } else { 1577dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // Whole NAL units are returned but each fragment is prefixed by 1578dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber // the start code (0x00 00 00 01). 1579dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 158020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ssize_t num_bytes_read = 158134769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber mDataSource->readAt(offset, mSrcBuffer, size); 158220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 158320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (num_bytes_read < (ssize_t)size) { 158420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->release(); 158520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 158620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1587dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber return ERROR_IO; 158820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 158920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1590dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber uint8_t *dstData = (uint8_t *)mBuffer->data(); 1591dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber size_t srcOffset = 0; 1592dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber size_t dstOffset = 0; 15936064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber 1594dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber while (srcOffset < size) { 15956064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK(srcOffset + mNALLengthSize <= size); 15966064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 15976064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber srcOffset += mNALLengthSize; 1598e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 1599e8a084958c27327b0aca749f69095605d2a21309Andreas Huber if (srcOffset + nalLength > size) { 1600e8a084958c27327b0aca749f69095605d2a21309Andreas Huber mBuffer->release(); 1601e8a084958c27327b0aca749f69095605d2a21309Andreas Huber mBuffer = NULL; 1602e8a084958c27327b0aca749f69095605d2a21309Andreas Huber 1603e8a084958c27327b0aca749f69095605d2a21309Andreas Huber return ERROR_MALFORMED; 1604e8a084958c27327b0aca749f69095605d2a21309Andreas Huber } 1605dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1606dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber if (nalLength == 0) { 1607dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber continue; 1608dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 1609dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1610dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber CHECK(dstOffset + 4 <= mBuffer->size()); 1611dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 1612dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber dstData[dstOffset++] = 0; 1613dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber dstData[dstOffset++] = 0; 1614dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber dstData[dstOffset++] = 0; 1615dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber dstData[dstOffset++] = 1; 1616dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 1617dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber srcOffset += nalLength; 1618dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber dstOffset += nalLength; 1619dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber } 16206064017c61aa0bcadcff3119e176eab5fc3c001bAndreas Huber CHECK_EQ(srcOffset, size); 1621dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber 16227b3396acc702451be9bafb19d7fe26d55d43a316Andreas Huber CHECK(mBuffer != NULL); 1623dbc03445db2bbf83b64f0c0a5dc62e61408864d7Andreas Huber mBuffer->set_range(0, dstOffset); 162420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer->meta_data()->clear(); 162548c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber mBuffer->meta_data()->setInt64( 162648c948b1137e7bbdb161b51908657ab72ac5e2daAndreas Huber kKeyTime, ((int64_t)dts * 1000000) / mTimescale); 162720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber ++mCurrentSampleIndex; 162820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 162920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *out = mBuffer; 163020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber mBuffer = NULL; 163120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 163220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return OK; 163320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 163420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 163520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16361b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool LegacySniffMPEG4( 1637693d271e62a3726689ff68f4505ba49228eb94b2Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 163820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber uint8_t header[8]; 163920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 164034769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huber ssize_t n = source->readAt(4, header, sizeof(header)); 164120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (n < (ssize_t)sizeof(header)) { 164220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return false; 164320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 164420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 164520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8) 1646b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8) 1647b9dbba9285fb406bc6eb87779c8bfc405269b6f2James Dong || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8) 16480dba73763a04d39faf999dcc5ef12af3c99535a7Andreas Huber || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8) 1649ea5ea10a036f79c86bf5f204cb81804bf2bacdc7Andreas Huber || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8) 1650983b449a27b5fa91eca82ede5204b4341899be62Andreas Huber || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) { 165118291bc20e55e8f3fd5feb786771a8ed32c19c59Andreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 165220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *confidence = 0.1; 165320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 165420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return true; 165520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber } 165620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 165720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber return false; 165820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} 165920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 16601b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) { 16611b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber static const uint32_t kCompatibleBrands[] = { 16621b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('i', 's', 'o', 'm'), 16631b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('i', 's', 'o', '2'), 16641b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('a', 'v', 'c', '1'), 16651b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('3', 'g', 'p', '4'), 16661b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('m', 'p', '4', '1'), 16671b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber FOURCC('m', 'p', '4', '2'), 16681b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber }; 16691b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 16701b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber for (size_t i = 0; 16711b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]); 16721b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber ++i) { 16731b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (kCompatibleBrands[i] == fourcc) { 16741b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 16751b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 16761b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 16771b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 16781b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 16791b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 16801b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 16811b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable 16821b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber// compatible brand is present. 16831b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberstatic bool BetterSniffMPEG4( 16841b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 16851b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber uint8_t header[12]; 16861b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (source->readAt(0, header, 12) != 12 16871b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber || memcmp("ftyp", &header[4], 4)) { 16881b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 16891b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 16901b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 16911b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber size_t atomSize = U32_AT(&header[0]); 16921b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (atomSize < 16 || (atomSize % 4) != 0) { 16931b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 16941b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 16951b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 16961b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber bool success = false; 16971b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (isCompatibleBrand(U32_AT(&header[8]))) { 16981b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber success = true; 16991b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } else { 17001b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber size_t numCompatibleBrands = (atomSize - 16) / 4; 17011b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber for (size_t i = 0; i < numCompatibleBrands; ++i) { 17021b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber uint8_t tmp[4]; 17031b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (source->readAt(16 + i * 4, tmp, 4) != 4) { 17041b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 17051b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 17061b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 17071b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (isCompatibleBrand(U32_AT(&tmp[0]))) { 17081b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber success = true; 17091b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber break; 17101b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 17111b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 17121b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 17131b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 17141b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (!success) { 17151b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 17161b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 17171b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 17181b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 17191b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber *confidence = 0.3f; 17201b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 17211b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 17221b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 17231b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 17241b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huberbool SniffMPEG4( 17251b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 17261b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (BetterSniffMPEG4(source, mimeType, confidence)) { 17271b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 17281b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 17291b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 17301b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber if (LegacySniffMPEG4(source, mimeType, confidence)) { 17311b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber LOGW("Identified supported mpeg4 through LegacySniffMPEG4."); 17321b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return true; 17331b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber } 17341b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 17351b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber return false; 17361b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber} 17371b52bd2874aef6c9cbc141f1cff5205830515f7dAndreas Huber 173820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber} // namespace android 173920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber 1740