1e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber/* 2e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Copyright (C) 2009 The Android Open Source Project 3e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * 4e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * you may not use this file except in compliance with the License. 6e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * You may obtain a copy of the License at 7e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * 8e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * 10e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * Unless required by applicable law or agreed to in writing, software 11e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * See the License for the specific language governing permissions and 14e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber * limitations under the License. 15e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber */ 16e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 17e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#define LOG_TAG "MPEG4Extractor" 18e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/Log.h> 19e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2057515f334bcc1f66f95e342bfcaa13bf9ca802adAndreas Huber#include "include/MPEG4Extractor.h" 21bd7b43bb02852e51b3000185fa66e10c56b120e0Andreas Huber#include "include/SampleTable.h" 22c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang#include "include/ESDS.h" 2313bc8cde1c842bea1fa3000a48739a6e22f25a9cGloria Wang#include "timedtext/TimedTextPlayer.h" 24bd7b43bb02852e51b3000185fa66e10c56b120e0Andreas Huber 25e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <arpa/inet.h> 26e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 27e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <ctype.h> 28e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <stdint.h> 29e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <stdlib.h> 30e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <string.h> 31e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 32940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber#include <media/stagefright/foundation/ADebug.h> 33b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber#include <media/stagefright/foundation/AMessage.h> 34e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/DataSource.h> 35e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBuffer.h> 36e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBufferGroup.h> 37e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber#include <media/stagefright/MediaDefs.h> 38e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaSource.h> 39e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MetaData.h> 40e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/Utils.h> 41e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/String8.h> 42e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 43e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubernamespace android { 44e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 45e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberclass MPEG4Source : public MediaSource { 46e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberpublic: 47e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Caller retains ownership of both "dataSource" and "sampleTable". 48be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber MPEG4Source(const sp<MetaData> &format, 49be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<DataSource> &dataSource, 50fa8de752507feaca695123911915070c1ce463b2Andreas Huber int32_t timeScale, 51be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<SampleTable> &sampleTable); 52e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 53e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual status_t start(MetaData *params = NULL); 54e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual status_t stop(); 55e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 56e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual sp<MetaData> getFormat(); 57e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 58e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual status_t read( 59e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 60e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 61be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberprotected: 62be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber virtual ~MPEG4Source(); 63be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber 64e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberprivate: 65ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex mLock; 66ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 67e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber sp<MetaData> mFormat; 68be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber sp<DataSource> mDataSource; 69e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t mTimescale; 70be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber sp<SampleTable> mSampleTable; 71e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t mCurrentSampleIndex; 72e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 73e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bool mIsAVC; 74db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t mNALLengthSize; 75db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 76e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bool mStarted; 77e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 78e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBufferGroup *mGroup; 79e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 80e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer *mBuffer; 81e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 824f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber bool mWantsNALFragments; 83e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 848a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber uint8_t *mSrcBuffer; 858a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber 86db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t parseNALSize(const uint8_t *data) const; 87db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 88e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MPEG4Source(const MPEG4Source &); 89e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MPEG4Source &operator=(const MPEG4Source &); 90e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}; 91e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 92affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// This custom data source wraps an existing one and satisfies requests 93affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// falling entirely within a cached range from the cache while forwarding 94affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// all remaining requests to the wrapped datasource. 95affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// This is used to cache the full sampletable metadata for a single track, 96affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// possibly wrapping multiple times to cover all tracks, i.e. 97affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track. 98affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 99affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstruct MPEG4DataSource : public DataSource { 100affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber MPEG4DataSource(const sp<DataSource> &source); 101affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 102affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual status_t initCheck() const; 103b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong virtual ssize_t readAt(off64_t offset, void *data, size_t size); 104b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong virtual status_t getSize(off64_t *size); 105affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual uint32_t flags(); 106affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 107b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong status_t setCachedRange(off64_t offset, size_t size); 108affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 109affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberprotected: 110affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual ~MPEG4DataSource(); 111affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 112affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberprivate: 113affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber Mutex mLock; 114affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 115affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber sp<DataSource> mSource; 116b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t mCachedOffset; 117affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber size_t mCachedSize; 118affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber uint8_t *mCache; 119affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 120affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber void clearCache(); 121affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 122affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber MPEG4DataSource(const MPEG4DataSource &); 123affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber MPEG4DataSource &operator=(const MPEG4DataSource &); 124affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}; 125affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 126affa99c52957685f5a5652ab5254b92e729651c7Andreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source) 127affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber : mSource(source), 128affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedOffset(0), 129affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedSize(0), 130affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCache(NULL) { 131affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 132affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 133affa99c52957685f5a5652ab5254b92e729651c7Andreas HuberMPEG4DataSource::~MPEG4DataSource() { 134affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber clearCache(); 135affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 136affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 137affa99c52957685f5a5652ab5254b92e729651c7Andreas Hubervoid MPEG4DataSource::clearCache() { 138affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (mCache) { 139affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber free(mCache); 140affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCache = NULL; 141affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 142affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 143affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedOffset = 0; 144affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedSize = 0; 145affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 146affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 147affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstatus_t MPEG4DataSource::initCheck() const { 148affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return mSource->initCheck(); 149affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 150affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 151b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) { 152affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber Mutex::Autolock autoLock(mLock); 153affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 154affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (offset >= mCachedOffset 155affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber && offset + size <= mCachedOffset + mCachedSize) { 156affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber memcpy(data, &mCache[offset - mCachedOffset], size); 157affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return size; 158affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 159affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 160affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return mSource->readAt(offset, data, size); 161affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 162affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 163b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongstatus_t MPEG4DataSource::getSize(off64_t *size) { 164affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return mSource->getSize(size); 165affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 166affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 167affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberuint32_t MPEG4DataSource::flags() { 168affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return mSource->flags(); 169affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 170affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 171b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongstatus_t MPEG4DataSource::setCachedRange(off64_t offset, size_t size) { 172affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber Mutex::Autolock autoLock(mLock); 173affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 174affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber clearCache(); 175affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 176affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCache = (uint8_t *)malloc(size); 177affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 178affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (mCache == NULL) { 179affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return -ENOMEM; 180affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 181affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 182affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedOffset = offset; 183affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedSize = size; 184affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 185affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize); 186affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 187affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (err < (ssize_t)size) { 188affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber clearCache(); 189affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 190affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return ERROR_IO; 191affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 192affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 193affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return OK; 194affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 195affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 196affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber//////////////////////////////////////////////////////////////////////////////// 197affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 198e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic void hexdump(const void *_data, size_t size) { 199e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const uint8_t *data = (const uint8_t *)_data; 200e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber size_t offset = 0; 201e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (offset < size) { 202e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("0x%04x ", offset); 203e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 204e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber size_t n = size - offset; 205e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (n > 16) { 206e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber n = 16; 207e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 208e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 209e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber for (size_t i = 0; i < 16; ++i) { 210e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (i == 8) { 211e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf(" "); 212e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 213e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 214e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (offset + i < size) { 215e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("%02x ", data[offset + i]); 216e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 217e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf(" "); 218e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 219e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 220e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 221e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf(" "); 222e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 223e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber for (size_t i = 0; i < n; ++i) { 224e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (isprint(data[offset + i])) { 225e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("%c", data[offset + i]); 226e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 227e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("."); 228e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 229e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 230e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 231e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("\n"); 232e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 233e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber offset += 16; 234e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 235e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 236e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 237e6c409632f773e41f33188272a0072be9fcb783fAndreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) { 238e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber switch (fourcc) { 239e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'a'): 240e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_AUDIO_AAC; 241e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 242e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 243e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_AUDIO_AMR_NB; 244e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2452a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber case FOURCC('s', 'a', 'w', 'b'): 246e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_AUDIO_AMR_WB; 2472a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber 248e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'v'): 249e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_VIDEO_MPEG4; 250e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 251e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', '2', '6', '3'): 2520efdc95d59a51a130ce9d2515bcc9e2c01b52f14James Dong case FOURCC('h', '2', '6', '3'): 2530efdc95d59a51a130ce9d2515bcc9e2c01b52f14James Dong case FOURCC('H', '2', '6', '3'): 254e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_VIDEO_H263; 255e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 256e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('a', 'v', 'c', '1'): 257e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_VIDEO_AVC; 258e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 259e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber default: 2604f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(!"should not be here."); 261e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return NULL; 262e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 263e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 264e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 265be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source) 266e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber : mDataSource(source), 267f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber mInitCheck(NO_INIT), 2681cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber mHasVideo(false), 269e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mFirstTrack(NULL), 270c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mLastTrack(NULL), 271d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang mFileMetaData(new MetaData), 272d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang mFirstSINF(NULL), 273d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang mIsDrm(false) { 274e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 275e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 276e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Extractor::~MPEG4Extractor() { 277e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 278e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (track) { 279e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *next = track->next; 280e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 281e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber delete track; 282e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = next; 283e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 284e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mFirstTrack = mLastTrack = NULL; 285d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 286d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang SINF *sinf = mFirstSINF; 287d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang while (sinf) { 288d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang SINF *next = sinf->next; 289d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang delete sinf->IPMPData; 290d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang delete sinf; 291d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang sinf = next; 292d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 293d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang mFirstSINF = NULL; 294e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 295e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2961cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() { 2971cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber status_t err; 2981cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber if ((err = readMetaData()) != OK) { 299c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return new MetaData; 3001cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber } 3011cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 302c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return mFileMetaData; 3031cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber} 3041cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 305be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersize_t MPEG4Extractor::countTracks() { 306e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 307e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if ((err = readMetaData()) != OK) { 308be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return 0; 309e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 310e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 311be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber size_t n = 0; 312e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 313e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (track) { 314be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber ++n; 315e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = track->next; 316e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 317e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 318be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return n; 319e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 320e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 321e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData( 322e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber size_t index, uint32_t flags) { 323e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 324e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if ((err = readMetaData()) != OK) { 325e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return NULL; 326e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 327e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 328e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 329e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (index > 0) { 330e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (track == NULL) { 331e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return NULL; 332e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 333e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 334e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = track->next; 335e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber --index; 336e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 337e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 3382a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber if (track == NULL) { 3392a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber return NULL; 3402a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber } 3412a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber 342e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber if ((flags & kIncludeExtensiveMetaData) 343e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber && !track->includes_expensive_metadata) { 344e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber track->includes_expensive_metadata = true; 345e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber 346e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber const char *mime; 347e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 348e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber if (!strncasecmp("video/", mime, 6)) { 349e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber uint32_t sampleIndex; 350e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber uint32_t sampleTime; 351e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK 3521faa92a1e93f311e86dca483ed7702091137de66Andreas Huber && track->sampleTable->getMetaDataForSample( 3531faa92a1e93f311e86dca483ed7702091137de66Andreas Huber sampleIndex, NULL /* offset */, NULL /* size */, 3541faa92a1e93f311e86dca483ed7702091137de66Andreas Huber &sampleTime) == OK) { 355e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber track->meta->setInt64( 356e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber kKeyThumbnailTime, 357e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber ((int64_t)sampleTime * 1000000) / track->timescale); 358e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber } 359e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber } 360e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber } 361e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber 362e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return track->meta; 363e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 364e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 365e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Extractor::readMetaData() { 366f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber if (mInitCheck != NO_INIT) { 367f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber return mInitCheck; 368e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 369e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 370b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t offset = 0; 371e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 372e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while ((err = parseChunk(&offset, 0)) == OK) { 373e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 3741cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 375f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber if (mInitCheck == OK) { 376c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mHasVideo) { 377c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyMIMEType, "video/mp4"); 378c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else { 379c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyMIMEType, "audio/mp4"); 380c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 381c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 38244fdac0c62916ddcfac1fe887d867e7ff0cf446fAndreas Huber mInitCheck = OK; 383f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber } else { 384f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber mInitCheck = err; 385e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 386e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 387f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber CHECK_NE(err, (status_t)NO_INIT); 388f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber return mInitCheck; 389e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 390e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 391d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wangchar* MPEG4Extractor::getDrmTrackInfo(size_t trackID, int *len) { 392d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (mFirstSINF == NULL) { 393d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return NULL; 394d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 395d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 396d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang SINF *sinf = mFirstSINF; 397d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang while (sinf && (trackID != sinf->trackID)) { 398d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang sinf = sinf->next; 399d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 400d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 401d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (sinf == NULL) { 402d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return NULL; 403d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 404d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 405d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang *len = sinf->len; 406d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return sinf->IPMPData; 407d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang} 408d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 409d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang// Reads an encoded integer 7 bits at a time until it encounters the high bit clear. 410b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongint32_t readSize(off64_t offset, 411d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang const sp<DataSource> DataSource, uint8_t *numOfBytes) { 412d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang uint32_t size = 0; 413d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang uint8_t data; 414d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang bool moreData = true; 415d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang *numOfBytes = 0; 416d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 417d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang while (moreData) { 418d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (DataSource->readAt(offset, &data, 1) < 1) { 419d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return -1; 420d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 421d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang offset ++; 422d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang moreData = (data >= 128) ? true : false; 423d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang size = (size << 7) | (data & 0x7f); // Take last 7 bits 424d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang (*numOfBytes) ++; 425d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 426d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 427d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return size; 428d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang} 429d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 430b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongstatus_t MPEG4Extractor::parseDrmSINF(off64_t *offset, off64_t data_offset) { 431d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang uint8_t updateIdTag; 432d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) { 433d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_IO; 434d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 435d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang data_offset ++; 436d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 437d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (0x01/*OBJECT_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) { 438d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_MALFORMED; 439d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 440d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 441d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang uint8_t numOfBytes; 442d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang int32_t size = readSize(data_offset, mDataSource, &numOfBytes); 443d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (size < 0) { 444d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_IO; 445d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 446d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang int32_t classSize = size; 447d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang data_offset += numOfBytes; 448d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 449d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang while(size >= 11 ) { 450d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang uint8_t descriptorTag; 451d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (mDataSource->readAt(data_offset, &descriptorTag, 1) < 1) { 452d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_IO; 453d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 454d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang data_offset ++; 455d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 456d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (0x11/*OBJECT_DESCRIPTOR_ID_TAG*/ != descriptorTag) { 457d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_MALFORMED; 458d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 459d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 460d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang uint8_t buffer[8]; 461d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang //ObjectDescriptorID and ObjectDescriptor url flag 462d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (mDataSource->readAt(data_offset, buffer, 2) < 2) { 463d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_IO; 464d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 465d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang data_offset += 2; 466d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 467d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if ((buffer[1] >> 5) & 0x0001) { //url flag is set 468d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_MALFORMED; 469d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 470d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 471d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (mDataSource->readAt(data_offset, buffer, 8) < 8) { 472d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_IO; 473d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 474d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang data_offset += 8; 475d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 476d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if ((0x0F/*ES_ID_REF_TAG*/ != buffer[1]) 477d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang || ( 0x0A/*IPMP_DESCRIPTOR_POINTER_ID_TAG*/ != buffer[5])) { 478d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_MALFORMED; 479d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 480d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 481d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang SINF *sinf = new SINF; 482d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang sinf->trackID = U16_AT(&buffer[3]); 483d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang sinf->IPMPDescriptorID = buffer[7]; 484d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang sinf->next = mFirstSINF; 485d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang mFirstSINF = sinf; 486d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 487d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang size -= (8 + 2 + 1); 488d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 489d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 490d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (size != 0) { 491d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_MALFORMED; 492d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 493d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 494d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (mDataSource->readAt(data_offset, &updateIdTag, 1) < 1) { 495d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_IO; 496d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 497d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang data_offset ++; 498d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 499d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if(0x05/*IPMP_DESCRIPTOR_UPDATE_ID_TAG*/ != updateIdTag) { 500d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_MALFORMED; 501d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 502d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 503d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang size = readSize(data_offset, mDataSource, &numOfBytes); 504d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (size < 0) { 505d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_IO; 506d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 507d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang classSize = size; 508d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang data_offset += numOfBytes; 509d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 510d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang while (size > 0) { 511d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang uint8_t tag; 512d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang int32_t dataLen; 513d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (mDataSource->readAt(data_offset, &tag, 1) < 1) { 514d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_IO; 515d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 516d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang data_offset ++; 517d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 518d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (0x0B/*IPMP_DESCRIPTOR_ID_TAG*/ == tag) { 519d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang uint8_t id; 520d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang dataLen = readSize(data_offset, mDataSource, &numOfBytes); 521d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (dataLen < 0) { 522d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_IO; 523d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } else if (dataLen < 4) { 524d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_MALFORMED; 525d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 526d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang data_offset += numOfBytes; 527d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 528d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (mDataSource->readAt(data_offset, &id, 1) < 1) { 529d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_IO; 530d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 531d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang data_offset ++; 532d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 533d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang SINF *sinf = mFirstSINF; 534d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang while (sinf && (sinf->IPMPDescriptorID != id)) { 535d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang sinf = sinf->next; 536d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 537d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (sinf == NULL) { 538d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_MALFORMED; 539d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 540d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang sinf->len = dataLen - 3; 541d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang sinf->IPMPData = new char[sinf->len]; 542d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 543d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (mDataSource->readAt(data_offset + 2, sinf->IPMPData, sinf->len) < sinf->len) { 544d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_IO; 545d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 546d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang data_offset += sinf->len; 547d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 548d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang size -= (dataLen + numOfBytes + 1); 549d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 550d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 551d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 552d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (size != 0) { 553d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_MALFORMED; 554d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 555d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 556d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return UNKNOWN_ERROR; // Return a dummy error. 557d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang} 558d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 559e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic void MakeFourCCString(uint32_t x, char *s) { 560e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[0] = x >> 24; 561e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[1] = (x >> 16) & 0xff; 562e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[2] = (x >> 8) & 0xff; 563e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[3] = x & 0xff; 564e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[4] = '\0'; 565e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 566e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 567c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstruct PathAdder { 568c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder(Vector<uint32_t> *path, uint32_t chunkType) 569c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber : mPath(path) { 570c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mPath->push(chunkType); 571c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 572c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 573c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber ~PathAdder() { 574c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mPath->pop(); 575c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 576c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 577c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberprivate: 578c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber Vector<uint32_t> *mPath; 579c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 580c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder(const PathAdder &); 581c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder &operator=(const PathAdder &); 582c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber}; 583c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 584c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) { 585c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return path.size() >= 5 586c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && path[0] == FOURCC('m', 'o', 'o', 'v') 587c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && path[1] == FOURCC('u', 'd', 't', 'a') 588c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && path[2] == FOURCC('m', 'e', 't', 'a') 589c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && path[3] == FOURCC('i', 'l', 's', 't'); 590c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber} 591c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 592c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string. 593c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) { 594c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600); 595c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 596c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber char tmp[32]; 597c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970)); 598c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 599c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber s->setTo(tmp); 600c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber} 601c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 602b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongstatus_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { 603e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t hdr[2]; 6049a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt(*offset, hdr, 8) < 8) { 605e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 606e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 607e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint64_t chunk_size = ntohl(hdr[0]); 608e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t chunk_type = ntohl(hdr[1]); 609b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t data_offset = *offset + 8; 610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 611e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_size == 1) { 6129a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { 613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 615e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber chunk_size = ntoh64(chunk_size); 616e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset += 8; 617736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber 618736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber if (chunk_size < 16) { 619736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber // The smallest valid chunk is 16 bytes long in this case. 620736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber return ERROR_MALFORMED; 621736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber } 622736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber } else if (chunk_size < 8) { 623736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber // The smallest valid chunk is 8 bytes long. 624736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber return ERROR_MALFORMED; 625e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 626e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber char chunk[5]; 628e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MakeFourCCString(chunk_type, chunk); 629e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 630e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#if 0 631e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber static const char kWhitespace[] = " "; 632e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth]; 633e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size); 634e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber char buffer[256]; 636dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber size_t n = chunk_size; 637dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber if (n > sizeof(buffer)) { 638dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber n = sizeof(buffer); 639dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber } 640dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber if (mDataSource->readAt(*offset, buffer, n) 641dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber < (ssize_t)n) { 642dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber return ERROR_IO; 643e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 644dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber 645dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber hexdump(buffer, n); 646e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#endif 647e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 648c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder autoAdder(&mPath, chunk_type); 649c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 650b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t chunk_data_size = *offset + chunk_size - data_offset; 651e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 652c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (chunk_type != FOURCC('c', 'p', 'r', 't') 653e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong && chunk_type != FOURCC('c', 'o', 'v', 'r') 654c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && mPath.size() == 5 && underMetaDataPath(mPath)) { 655b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t stop_offset = *offset + chunk_size; 656c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset = data_offset; 657c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber while (*offset < stop_offset) { 658c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber status_t err = parseChunk(offset, depth + 1); 659c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (err != OK) { 660c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return err; 661c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 662c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 6635ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 6645ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 6655ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 6665ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 667c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 668c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return OK; 669c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 670c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 671e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber switch(chunk_type) { 672e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'o', 'o', 'v'): 673e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('t', 'r', 'a', 'k'): 674e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'd', 'i', 'a'): 675e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'i', 'n', 'f'): 676e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('d', 'i', 'n', 'f'): 677e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 'b', 'l'): 678e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'v', 'e', 'x'): 679e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'o', 'o', 'f'): 680e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('t', 'r', 'a', 'f'): 681e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'f', 'r', 'a'): 682c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('u', 'd', 't', 'a'): 683c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('i', 'l', 's', 't'): 684e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 685affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (chunk_type == FOURCC('s', 't', 'b', 'l')) { 686affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size); 687affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 6886da2ae11b62f155ee83c3e31fdd9cc53b2058586Andreas Huber if (mDataSource->flags() 6896da2ae11b62f155ee83c3e31fdd9cc53b2058586Andreas Huber & (DataSource::kWantsPrefetching 6906da2ae11b62f155ee83c3e31fdd9cc53b2058586Andreas Huber | DataSource::kIsCachingDataSource)) { 691affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber sp<MPEG4DataSource> cachedSource = 692affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber new MPEG4DataSource(mDataSource); 693affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 694affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (cachedSource->setCachedRange(*offset, chunk_size) == OK) { 695affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mDataSource = cachedSource; 696affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 697affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 698eb9128f9b0ee660504621381fd96f82d5bf8a3fdAndreas Huber 699eb9128f9b0ee660504621381fd96f82d5bf8a3fdAndreas Huber mLastTrack->sampleTable = new SampleTable(mDataSource); 700affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 701affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 7024d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber bool isTrack = false; 7035ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_type == FOURCC('t', 'r', 'a', 'k')) { 7044d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber isTrack = true; 7054d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 7065ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber Track *track = new Track; 7075ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->next = NULL; 7085ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (mLastTrack) { 7095ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber mLastTrack->next = track; 7105ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else { 7115ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber mFirstTrack = track; 7125ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 7135ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber mLastTrack = track; 7145ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 7155ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->meta = new MetaData; 7165ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->includes_expensive_metadata = false; 7174d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber track->skipTrack = false; 7185ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->timescale = 0; 7195ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->meta->setCString(kKeyMIMEType, "application/octet-stream"); 7205ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 7215ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 722b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t stop_offset = *offset + chunk_size; 723e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset; 724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (*offset < stop_offset) { 725e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 726e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 727e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 728e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 729e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 730e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 7315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 7325ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 7335ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 7345ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 7354d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber if (isTrack) { 7364d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber if (mLastTrack->skipTrack) { 7374d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber Track *cur = mFirstTrack; 7384d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 7394d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber if (cur == mLastTrack) { 7404d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber delete cur; 7414d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber mFirstTrack = mLastTrack = NULL; 7424d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber } else { 7434d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber while (cur && cur->next != mLastTrack) { 7444d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber cur = cur->next; 7454d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber } 7464d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber cur->next = NULL; 7474d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber delete mLastTrack; 7484d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber mLastTrack = cur; 7494d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber } 7504d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 7514d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber return OK; 7524d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber } 7534d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 7545ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber status_t err = verifyTrack(mLastTrack); 7555ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 7565ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (err != OK) { 7575ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return err; 7585ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 7595ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { 760f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber mInitCheck = OK; 761e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 762d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (!mIsDrm) { 763d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return UNKNOWN_ERROR; // Return a dummy error. 764d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } else { 765d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return OK; 766d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 767e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 768e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 769e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 770e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 771e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('t', 'k', 'h', 'd'): 772e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 773940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber status_t err; 774940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) { 775940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber return err; 776e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 777e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 778e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 779e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 780e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 781e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 782e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'd', 'h', 'd'): 783e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 784e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 4) { 785e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 786e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 787e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 788e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t version; 7899a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 790e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, &version, sizeof(version)) 791e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(version)) { 792e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 793e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 794e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 795b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t timescale_offset; 796e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 797e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 1) { 798e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset = data_offset + 4 + 16; 799e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else if (version == 0) { 800e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset = data_offset + 4 + 8; 801e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 802e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 803e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 804e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 805e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t timescale; 8069a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 807e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset, ×cale, sizeof(timescale)) 808e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(timescale)) { 809e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 810e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 811e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 812e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->timescale = ntohl(timescale); 813e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 814e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int64_t duration; 815e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 1) { 8169a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 817e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset + 4, &duration, sizeof(duration)) 818e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(duration)) { 819e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 820e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 821e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber duration = ntoh64(duration); 822e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 823e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t duration32; 8249a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 825e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset + 4, &duration32, sizeof(duration32)) 826e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(duration32)) { 827e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 828e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 829e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber duration = ntohl(duration32); 830e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 831fa8de752507feaca695123911915070c1ce463b2Andreas Huber mLastTrack->meta->setInt64( 832fa8de752507feaca695123911915070c1ce463b2Andreas Huber kKeyDuration, (duration * 1000000) / mLastTrack->timescale); 833e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 834c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang uint8_t lang[2]; 835c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang off64_t lang_offset; 836c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang if (version == 1) { 837c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang lang_offset = timescale_offset + 4 + 8; 838c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang } else if (version == 0) { 839c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang lang_offset = timescale_offset + 4 + 4; 840c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang } else { 841c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang return ERROR_IO; 842c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang } 843c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang 844c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang if (mDataSource->readAt(lang_offset, &lang, sizeof(lang)) 845c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang < (ssize_t)sizeof(lang)) { 846c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang return ERROR_IO; 847c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang } 848c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang 849c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang // To get the ISO-639-2/T three character language code 850c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang // 1 bit pad followed by 3 5-bits characters. Each character 851c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang // is packed as the difference between its ASCII value and 0x60. 852c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang char lang_code[4]; 853c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang lang_code[0] = ((lang[0] >> 2) & 0x1f) + 0x60; 854c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang lang_code[1] = ((lang[0] & 0x3) << 3 | (lang[1] >> 5)) + 0x60; 855c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang lang_code[2] = (lang[1] & 0x1f) + 0x60; 856c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang lang_code[3] = '\0'; 857c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang 858c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang mLastTrack->meta->setCString( 859c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang kKeyMediaLanguage, lang_code); 860c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang 861e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 862e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 863e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 864e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 865e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 'd'): 866e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 867e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 8) { 868e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 869e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 870e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 871e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[8]; 872b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong if (chunk_data_size < (off64_t)sizeof(buffer)) { 8735ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 8745ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 8755ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 8769a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 877e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, 8) < 8) { 878e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 879e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 880e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 881e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (U32_AT(buffer) != 0) { 882e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Should be version 0, flags 0. 883e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 884e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 885e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 886e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t entry_count = U32_AT(&buffer[4]); 887e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 888e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (entry_count > 1) { 889eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang // For 3GPP timed text, there could be multiple tx3g boxes contain 890eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang // multiple text display formats. These formats will be used to 891eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang // display the timed text. 892eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang const char *mime; 893eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 894eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang if (strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) { 895eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang // For now we only support a single type of media per track. 896eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang mLastTrack->skipTrack = true; 897eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang *offset += chunk_size; 898eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang break; 899eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang } 900e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 901e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 902b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t stop_offset = *offset + chunk_size; 903e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset + 8; 904e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber for (uint32_t i = 0; i < entry_count; ++i) { 905e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 906e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 907e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 908e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 909e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 9105ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 9115ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 9125ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 9135ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 914e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 915e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 916e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 917e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'a'): 918e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 9192a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber case FOURCC('s', 'a', 'w', 'b'): 920e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 921e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[8 + 20]; 922e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 923e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Basic AudioSampleEntry size. 924e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 925e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 926e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 9279a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 928e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 929e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 930e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 931e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 932e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 933e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t num_channels = U16_AT(&buffer[16]); 934e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 935d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber uint16_t sample_size = U16_AT(&buffer[18]); 936d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber uint32_t sample_rate = U32_AT(&buffer[24]) >> 16; 937d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber 938e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, 939d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber FourCC2MIME(chunk_type))) { 940d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber // AMR NB audio is always mono, 8kHz 941d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber num_channels = 1; 942d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber sample_rate = 8000; 943d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, 944e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber FourCC2MIME(chunk_type))) { 945d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber // AMR WB audio is always mono, 16kHz 946e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber num_channels = 1; 947d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber sample_rate = 16000; 948e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 949e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 950d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber#if 0 951d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber printf("*** coding='%s' %d channels, size %d, rate %d\n", 952d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber chunk, num_channels, sample_size, sample_rate); 953d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber#endif 954e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 955e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 956e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 957e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 958e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 959b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t stop_offset = *offset + chunk_size; 960e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset + sizeof(buffer); 961e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (*offset < stop_offset) { 962e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 963e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 964e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 965e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 966e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 9675ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 9685ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 9695ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 9705ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 971e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 972e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 973e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 974e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'v'): 975e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', '2', '6', '3'): 9760efdc95d59a51a130ce9d2515bcc9e2c01b52f14James Dong case FOURCC('H', '2', '6', '3'): 9770efdc95d59a51a130ce9d2515bcc9e2c01b52f14James Dong case FOURCC('h', '2', '6', '3'): 978e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('a', 'v', 'c', '1'): 979e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 9801cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber mHasVideo = true; 9811cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 982e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[78]; 983e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 984e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Basic VideoSampleEntry size. 985e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 986e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 987e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 9889a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 989e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 990e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 991e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 992e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 993e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 994e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t width = U16_AT(&buffer[6 + 18]); 995e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t height = U16_AT(&buffer[6 + 20]); 996e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 997c9e1c80f786667e264748bf2843dabdc2029c006James Dong // The video sample is not stand-compliant if it has invalid dimension. 998c9e1c80f786667e264748bf2843dabdc2029c006James Dong // Use some default width and height value, and 999c9e1c80f786667e264748bf2843dabdc2029c006James Dong // let the decoder figure out the actual width and height (and thus 1000c9e1c80f786667e264748bf2843dabdc2029c006James Dong // be prepared for INFO_FOMRAT_CHANGED event). 1001c9e1c80f786667e264748bf2843dabdc2029c006James Dong if (width == 0) width = 352; 1002c9e1c80f786667e264748bf2843dabdc2029c006James Dong if (height == 0) height = 288; 1003c9e1c80f786667e264748bf2843dabdc2029c006James Dong 10042ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber // printf("*** coding='%s' width=%d height=%d\n", 10052ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber // chunk, width, height); 1006e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1007e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 1008e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeyWidth, width); 1009e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeyHeight, height); 1010e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1011b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t stop_offset = *offset + chunk_size; 1012e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset + sizeof(buffer); 1013e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (*offset < stop_offset) { 1014e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 1015e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 1016e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 1017e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1018e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 10195ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 10205ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 10215ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 10225ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 1023e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 1024e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1025e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1026e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 'c', 'o'): 1027e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('c', 'o', '6', '4'): 1028e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 1029e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 1030e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setChunkOffsetParams( 1031e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber chunk_type, data_offset, chunk_data_size); 1032e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1033e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 1034e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 1035e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1036e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1037e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 1038e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 1039e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1040e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1041e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 'c'): 1042e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 1043e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 1044e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setSampleToChunkParams( 1045e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, chunk_data_size); 1046e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1047e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 1048e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 1049e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1050e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1051e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 1052e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 1053e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1054e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1055e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 'z'): 1056e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 'z', '2'): 1057e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 1058e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 1059e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setSampleSizeParams( 1060e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber chunk_type, data_offset, chunk_data_size); 1061e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1062e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 1063e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 1064e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1065e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 10661bceff916a72246fa208605d50615823d7f1688bAndreas Huber size_t max_size; 1067d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber err = mLastTrack->sampleTable->getMaxSampleSize(&max_size); 1068d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber 1069d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber if (err != OK) { 1070d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber return err; 1071d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber } 10721bceff916a72246fa208605d50615823d7f1688bAndreas Huber 10731bceff916a72246fa208605d50615823d7f1688bAndreas Huber // Assume that a given buffer only contains at most 10 fragments, 10741bceff916a72246fa208605d50615823d7f1688bAndreas Huber // each fragment originally prefixed with a 2 byte length will 10751bceff916a72246fa208605d50615823d7f1688bAndreas Huber // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion, 10761bceff916a72246fa208605d50615823d7f1688bAndreas Huber // and thus will grow by 2 bytes per fragment. 10771bceff916a72246fa208605d50615823d7f1688bAndreas Huber mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2); 1078e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 1079cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong 1080cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong // Calculate average frame rate. 1081cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong const char *mime; 1082cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong CHECK(mLastTrack->meta->findCString(kKeyMIMEType, &mime)); 1083cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong if (!strncasecmp("video/", mime, 6)) { 1084cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong size_t nSamples = mLastTrack->sampleTable->countSamples(); 1085cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong int64_t durationUs; 1086cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong if (mLastTrack->meta->findInt64(kKeyDuration, &durationUs)) { 1087cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong if (durationUs > 0) { 1088cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong int32_t frameRate = (nSamples * 1000000LL + 1089cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong (durationUs >> 1)) / durationUs; 1090cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong mLastTrack->meta->setInt32(kKeyFrameRate, frameRate); 1091cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong } 1092cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong } 1093cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong } 1094cbb488d67826dd38f665bc8626b55dfe2f0e135fJames Dong 1095e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 1096e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1097e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1098e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 't', 's'): 1099e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 1100e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 1101e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setTimeToSampleParams( 1102e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, chunk_data_size); 1103e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1104e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 1105e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 1106e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1107e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1108e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 1109e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 1110e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1111e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1112bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber case FOURCC('c', 't', 't', 's'): 1113bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber { 1114bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber status_t err = 1115bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber mLastTrack->sampleTable->setCompositionTimeToSampleParams( 1116bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber data_offset, chunk_data_size); 1117bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber 1118bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber if (err != OK) { 1119bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber return err; 1120bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber } 1121bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber 1122bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber *offset += chunk_size; 1123bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber break; 1124bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber } 1125bd352c3cdc6a8682dae58a5108c82a303be05274Andreas Huber 1126e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 's'): 1127e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 1128e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 1129e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setSyncSampleParams( 1130e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, chunk_data_size); 1131e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1132e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 1133e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 1134e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1135e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1136e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 1137e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 1138e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1139e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 114077c500c9a1f763b31fb5a03c803b3523fcb72310James Dong // @xyz 114177c500c9a1f763b31fb5a03c803b3523fcb72310James Dong case FOURCC('\xA9', 'x', 'y', 'z'): 114277c500c9a1f763b31fb5a03c803b3523fcb72310James Dong { 114377c500c9a1f763b31fb5a03c803b3523fcb72310James Dong // Best case the total data length inside "@xyz" box 114477c500c9a1f763b31fb5a03c803b3523fcb72310James Dong // would be 8, for instance "@xyz" + "\x00\x04\x15\xc7" + "0+0/", 114577c500c9a1f763b31fb5a03c803b3523fcb72310James Dong // where "\x00\x04" is the text string length with value = 4, 114677c500c9a1f763b31fb5a03c803b3523fcb72310James Dong // "\0x15\xc7" is the language code = en, and "0+0" is a 114777c500c9a1f763b31fb5a03c803b3523fcb72310James Dong // location (string) value with longitude = 0 and latitude = 0. 114877c500c9a1f763b31fb5a03c803b3523fcb72310James Dong if (chunk_data_size < 8) { 114977c500c9a1f763b31fb5a03c803b3523fcb72310James Dong return ERROR_MALFORMED; 115077c500c9a1f763b31fb5a03c803b3523fcb72310James Dong } 115177c500c9a1f763b31fb5a03c803b3523fcb72310James Dong 115277c500c9a1f763b31fb5a03c803b3523fcb72310James Dong // Worst case the location string length would be 18, 115377c500c9a1f763b31fb5a03c803b3523fcb72310James Dong // for instance +90.0000-180.0000, without the trailing "/" and 115477c500c9a1f763b31fb5a03c803b3523fcb72310James Dong // the string length + language code. 115577c500c9a1f763b31fb5a03c803b3523fcb72310James Dong char buffer[18]; 115677c500c9a1f763b31fb5a03c803b3523fcb72310James Dong 115777c500c9a1f763b31fb5a03c803b3523fcb72310James Dong // Substracting 5 from the data size is because the text string length + 115877c500c9a1f763b31fb5a03c803b3523fcb72310James Dong // language code takes 4 bytes, and the trailing slash "/" takes 1 byte. 115977c500c9a1f763b31fb5a03c803b3523fcb72310James Dong off64_t location_length = chunk_data_size - 5; 116077c500c9a1f763b31fb5a03c803b3523fcb72310James Dong if (location_length >= (off64_t) sizeof(buffer)) { 116177c500c9a1f763b31fb5a03c803b3523fcb72310James Dong return ERROR_MALFORMED; 116277c500c9a1f763b31fb5a03c803b3523fcb72310James Dong } 116377c500c9a1f763b31fb5a03c803b3523fcb72310James Dong 116477c500c9a1f763b31fb5a03c803b3523fcb72310James Dong if (mDataSource->readAt( 116577c500c9a1f763b31fb5a03c803b3523fcb72310James Dong data_offset + 4, buffer, location_length) < location_length) { 116677c500c9a1f763b31fb5a03c803b3523fcb72310James Dong return ERROR_IO; 116777c500c9a1f763b31fb5a03c803b3523fcb72310James Dong } 116877c500c9a1f763b31fb5a03c803b3523fcb72310James Dong 116977c500c9a1f763b31fb5a03c803b3523fcb72310James Dong buffer[location_length] = '\0'; 117077c500c9a1f763b31fb5a03c803b3523fcb72310James Dong mFileMetaData->setCString(kKeyLocation, buffer); 117177c500c9a1f763b31fb5a03c803b3523fcb72310James Dong *offset += chunk_size; 117277c500c9a1f763b31fb5a03c803b3523fcb72310James Dong break; 117377c500c9a1f763b31fb5a03c803b3523fcb72310James Dong } 117477c500c9a1f763b31fb5a03c803b3523fcb72310James Dong 1175e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('e', 's', 'd', 's'): 1176e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 1177e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 4) { 1178e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 1179e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1180e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1181e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[256]; 1182b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong if (chunk_data_size > (off64_t)sizeof(buffer)) { 1183e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_BUFFER_TOO_SMALL; 1184e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1185e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 11869a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 1187e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 1188e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 1189e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1190e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1191e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (U32_AT(buffer) != 0) { 1192e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Should be version 0, flags 0. 1193e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 1194e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1195e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1196e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setData( 1197e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); 1198e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1199d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (mPath.size() >= 2 1200d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) { 1201d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // Information from the ESDS must be relied on for proper 1202d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // setup of sample rate and channel count for MPEG4 Audio. 1203d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // The generic header appears to only contain generic 1204d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // information... 1205d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1206d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio( 1207d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber &buffer[4], chunk_data_size - 4); 1208d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1209d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (err != OK) { 1210d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return err; 1211d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1212d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1213d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1214e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 1215e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 1216e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1217e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1218e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('a', 'v', 'c', 'C'): 1219e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 1220e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber char buffer[256]; 1221b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong if (chunk_data_size > (off64_t)sizeof(buffer)) { 1222e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_BUFFER_TOO_SMALL; 1223e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1224e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 12259a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 1226e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 1227e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 1228e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1229e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1230e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setData( 1231e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber kKeyAVCC, kTypeAVCC, buffer, chunk_data_size); 1232e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1233e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 1234e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 1235e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1236e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1237fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong case FOURCC('d', '2', '6', '3'): 1238fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong { 1239bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong /* 1240bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong * d263 contains a fixed 7 bytes part: 1241bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong * vendor - 4 bytes 1242bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong * version - 1 byte 1243bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong * level - 1 byte 1244bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong * profile - 1 byte 1245bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong * optionally, "d263" box itself may contain a 16-byte 1246bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong * bit rate box (bitr) 1247bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong * average bit rate - 4 bytes 1248bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong * max bit rate - 4 bytes 1249bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong */ 1250bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong char buffer[23]; 1251bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong if (chunk_data_size != 7 && 1252bc5f1f5c815e6a158859c031fa7bb0fd68d973b9James Dong chunk_data_size != 23) { 1253fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong LOGE("Incorrect D263 box size %lld", chunk_data_size); 1254fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong return ERROR_MALFORMED; 1255fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong } 1256fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong 1257fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong if (mDataSource->readAt( 1258fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong data_offset, buffer, chunk_data_size) < chunk_data_size) { 1259fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong return ERROR_IO; 1260fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong } 1261fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong 1262fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong mLastTrack->meta->setData(kKeyD263, kTypeD263, buffer, chunk_data_size); 1263fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong 1264fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong *offset += chunk_size; 1265fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong break; 1266fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong } 1267fe84cf13cdbccec4a499caca05f0dc309df9d318James Dong 1268c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('m', 'e', 't', 'a'): 1269c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1270c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint8_t buffer[4]; 1271b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong if (chunk_data_size < (off64_t)sizeof(buffer)) { 12725ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 12735ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 12745ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 1275c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt( 1276c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber data_offset, buffer, 4) < 4) { 1277c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_IO; 1278c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1279c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1280c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (U32_AT(buffer) != 0) { 1281c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber // Should be version 0, flags 0. 1282dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber 1283dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber // If it's not, let's assume this is one of those 1284dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber // apparently malformed chunks that don't have flags 1285dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber // and completely different semantics than what's 1286dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber // in the MPEG4 specs and skip it. 1287dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber *offset += chunk_size; 1288dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber return OK; 1289c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1290c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1291b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t stop_offset = *offset + chunk_size; 1292c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset = data_offset + sizeof(buffer); 1293c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber while (*offset < stop_offset) { 1294c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber status_t err = parseChunk(offset, depth + 1); 1295c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (err != OK) { 1296c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return err; 1297c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1298c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 12995ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 13005ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 13015ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 13025ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 1303c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1304c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1305c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1306c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('d', 'a', 't', 'a'): 1307c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1308c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mPath.size() == 6 && underMetaDataPath(mPath)) { 1309c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber status_t err = parseMetaData(data_offset, chunk_data_size); 1310c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1311c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (err != OK) { 1312c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return err; 1313c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1314c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1315c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1316c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset += chunk_size; 1317c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1318c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1319c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1320c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('m', 'v', 'h', 'd'): 1321c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1322c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (chunk_data_size < 12) { 1323c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_MALFORMED; 1324c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1325c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1326c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint8_t header[12]; 1327c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt( 1328c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber data_offset, header, sizeof(header)) 1329c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber < (ssize_t)sizeof(header)) { 1330c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_IO; 1331c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1332c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1333c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber int64_t creationTime; 1334c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (header[0] == 1) { 1335c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber creationTime = U64_AT(&header[4]); 13365ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else if (header[0] != 0) { 13375ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 1338c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else { 1339c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber creationTime = U32_AT(&header[4]); 1340c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1341c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1342c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber String8 s; 1343c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber convertTimeToDate(creationTime, &s); 1344c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1345c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyDate, s.string()); 1346c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1347c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset += chunk_size; 1348c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1349c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1350c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1351d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang case FOURCC('m', 'd', 'a', 't'): 1352d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang { 1353d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (!mIsDrm) { 1354d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang *offset += chunk_size; 1355d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang break; 1356d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 1357d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 1358d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (chunk_size < 8) { 1359d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_MALFORMED; 1360d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 1361d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 1362d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return parseDrmSINF(offset, data_offset); 1363d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 1364d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 1365eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang case FOURCC('h', 'd', 'l', 'r'): 1366eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang { 1367eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang uint32_t buffer; 1368eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang if (mDataSource->readAt( 1369eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang data_offset + 8, &buffer, 4) < 4) { 1370eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang return ERROR_IO; 1371eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang } 1372eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang 1373eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang uint32_t type = ntohl(buffer); 1374eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang // For the 3GPP file format, the handler-type within the 'hdlr' box 1375eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang // shall be 'text' 1376eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang if (type == FOURCC('t', 'e', 'x', 't')) { 1377eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_TEXT_3GPP); 1378eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang } 1379eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang 1380eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang *offset += chunk_size; 1381eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang break; 1382eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang } 1383eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang 1384c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang case FOURCC('t', 'x', '3', 'g'): 1385c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang { 1386eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang uint32_t type; 1387eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang const void *data; 1388eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang size_t size = 0; 1389eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang if (!mLastTrack->meta->findData( 1390eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang kKeyTextFormatData, &type, &data, &size)) { 1391eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang size = 0; 1392eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang } 1393eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang 1394eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang uint8_t *buffer = new uint8_t[size + chunk_size]; 1395eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang 1396eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang if (size > 0) { 1397eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang memcpy(buffer, data, size); 1398eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang } 1399eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang 1400eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang if ((size_t)(mDataSource->readAt(*offset, buffer + size, chunk_size)) 1401eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang < chunk_size) { 1402eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang delete[] buffer; 1403eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang buffer = NULL; 1404eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang 1405eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang return ERROR_IO; 1406eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang } 1407eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang 1408eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang mLastTrack->meta->setData( 1409eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang kKeyTextFormatData, 0, buffer, size + chunk_size); 1410eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang 1411eaa5d8f9c0117bdaa20fd0a57921156bb0c06345Gloria Wang delete[] buffer; 1412c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang 1413c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang *offset += chunk_size; 1414c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang break; 1415c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang } 1416c6091ddd3a22da98b5e83d4b5d864939b451b752Gloria Wang 1417e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong case FOURCC('c', 'o', 'v', 'r'): 1418e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong { 1419e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong if (mFileMetaData != NULL) { 1420e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong LOGV("chunk_data_size = %lld and data_offset = %lld", 1421e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong chunk_data_size, data_offset); 1422e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong uint8_t *buffer = new uint8_t[chunk_data_size + 1]; 1423e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong if (mDataSource->readAt( 1424e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong data_offset, buffer, chunk_data_size) != (ssize_t)chunk_data_size) { 1425e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong delete[] buffer; 1426e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong buffer = NULL; 1427e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong 1428e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong return ERROR_IO; 1429e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong } 1430e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong const int kSkipBytesOfDataBox = 16; 1431e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong mFileMetaData->setData( 1432e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong kKeyAlbumArt, MetaData::TYPE_NONE, 1433e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong buffer + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox); 1434e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong } 1435e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong 1436e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong *offset += chunk_size; 1437e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong break; 1438e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong } 1439e8b26dcec7765786bbf063b3ae6b967b8b547ab6James Dong 1440e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber default: 1441e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 1442e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 1443e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 1444e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1445e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1446e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1447e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1448e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1449e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1450940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huberstatus_t MPEG4Extractor::parseTrackHeader( 1451b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t data_offset, off64_t data_size) { 1452940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber if (data_size < 4) { 1453940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber return ERROR_MALFORMED; 1454940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber } 1455940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1456940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber uint8_t version; 1457940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber if (mDataSource->readAt(data_offset, &version, 1) < 1) { 1458940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber return ERROR_IO; 1459940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber } 1460940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1461940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber size_t dynSize = (version == 1) ? 36 : 24; 1462940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1463940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber uint8_t buffer[36 + 60]; 1464940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1465b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong if (data_size != (off64_t)dynSize + 60) { 1466940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber return ERROR_MALFORMED; 1467940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber } 1468940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1469940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber if (mDataSource->readAt( 1470940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber data_offset, buffer, data_size) < (ssize_t)data_size) { 1471940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber return ERROR_IO; 1472940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber } 1473940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1474940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber uint64_t ctime, mtime, duration; 1475940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber int32_t id; 1476940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1477940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber if (version == 1) { 1478940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber ctime = U64_AT(&buffer[4]); 1479940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber mtime = U64_AT(&buffer[12]); 1480940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber id = U32_AT(&buffer[20]); 1481940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber duration = U64_AT(&buffer[28]); 1482940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber } else { 1483940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber CHECK_EQ((unsigned)version, 0u); 1484940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1485940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber ctime = U32_AT(&buffer[4]); 1486940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber mtime = U32_AT(&buffer[8]); 1487940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber id = U32_AT(&buffer[12]); 1488940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber duration = U32_AT(&buffer[20]); 1489940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber } 1490940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1491940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber mLastTrack->meta->setInt32(kKeyTrackID, id); 1492940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1493940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber size_t matrixOffset = dynSize + 16; 1494940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber int32_t a00 = U32_AT(&buffer[matrixOffset]); 1495940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber int32_t a01 = U32_AT(&buffer[matrixOffset + 4]); 1496940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber int32_t dx = U32_AT(&buffer[matrixOffset + 8]); 1497940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber int32_t a10 = U32_AT(&buffer[matrixOffset + 12]); 1498940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber int32_t a11 = U32_AT(&buffer[matrixOffset + 16]); 1499940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber int32_t dy = U32_AT(&buffer[matrixOffset + 20]); 1500940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1501940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber#if 0 1502940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber LOGI("x' = %.2f * x + %.2f * y + %.2f", 1503940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f); 1504940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber LOGI("y' = %.2f * x + %.2f * y + %.2f", 1505940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f); 1506940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber#endif 1507940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1508940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber uint32_t rotationDegrees; 1509940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1510940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber static const int32_t kFixedOne = 0x10000; 1511940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) { 1512940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber // Identity, no rotation 1513940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber rotationDegrees = 0; 1514940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) { 1515940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber rotationDegrees = 90; 1516940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) { 1517940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber rotationDegrees = 270; 1518940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) { 1519940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber rotationDegrees = 180; 1520940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber } else { 1521940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber LOGW("We only support 0,90,180,270 degree rotation matrices"); 1522940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber rotationDegrees = 0; 1523940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber } 1524940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1525940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber if (rotationDegrees != 0) { 1526940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees); 1527940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber } 1528940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 152908adfd29ae3634b554cfe184ab82f112ef934d7bJames Dong // Handle presentation display size, which could be different 153008adfd29ae3634b554cfe184ab82f112ef934d7bJames Dong // from the image size indicated by kKeyWidth and kKeyHeight. 1531940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber uint32_t width = U32_AT(&buffer[dynSize + 52]); 1532940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber uint32_t height = U32_AT(&buffer[dynSize + 56]); 153308adfd29ae3634b554cfe184ab82f112ef934d7bJames Dong mLastTrack->meta->setInt32(kKeyDisplayWidth, width >> 16); 153408adfd29ae3634b554cfe184ab82f112ef934d7bJames Dong mLastTrack->meta->setInt32(kKeyDisplayHeight, height >> 16); 1535940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1536940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber return OK; 1537940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber} 1538940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber 1539b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dongstatus_t MPEG4Extractor::parseMetaData(off64_t offset, size_t size) { 1540c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (size < 4) { 1541c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_MALFORMED; 1542c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1543c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1544c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint8_t *buffer = new uint8_t[size + 1]; 1545c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt( 1546c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber offset, buffer, size) != (ssize_t)size) { 1547c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber delete[] buffer; 1548c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer = NULL; 1549c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1550c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_IO; 1551c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1552c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1553c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint32_t flags = U32_AT(buffer); 1554c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1555c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint32_t metadataKey = 0; 1556c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber switch (mPath[4]) { 1557c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'a', 'l', 'b'): 1558c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1559c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyAlbum; 1560c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1561c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1562c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'A', 'R', 'T'): 1563c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1564c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyArtist; 1565c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1566c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1567c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen case FOURCC('a', 'A', 'R', 'T'): 1568c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen { 1569c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen metadataKey = kKeyAlbumArtist; 1570c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen break; 1571c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen } 1572c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'd', 'a', 'y'): 1573c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1574c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyYear; 1575c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1576c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1577c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'n', 'a', 'm'): 1578c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1579c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyTitle; 1580c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1581c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1582c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'w', 'r', 't'): 1583c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1584c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyWriter; 1585c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1586c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1587c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('c', 'o', 'v', 'r'): 1588c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1589c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyAlbumArt; 1590c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1591c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1592c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('g', 'n', 'r', 'e'): 1593c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1594c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyGenre; 1595c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1596c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1597fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen case FOURCC(0xa9, 'g', 'e', 'n'): 1598fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen { 1599fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen metadataKey = kKeyGenre; 1600fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen break; 1601fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1602ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen case FOURCC('c', 'p', 'i', 'l'): 1603ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen { 1604ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen if (size == 9 && flags == 21) { 1605ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen char tmp[16]; 1606ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen sprintf(tmp, "%d", 1607ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen (int)buffer[size - 1]); 1608ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen 1609ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen mFileMetaData->setCString(kKeyCompilation, tmp); 1610ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen } 1611ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen break; 1612ee35aff74494e6c0b718e219427af6a6c573b928Marco Nelissen } 1613c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('t', 'r', 'k', 'n'): 1614c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1615c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (size == 16 && flags == 0) { 1616c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber char tmp[16]; 1617c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber sprintf(tmp, "%d/%d", 1618c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber (int)buffer[size - 5], (int)buffer[size - 3]); 1619c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1620c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyCDTrackNumber, tmp); 1621c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1622c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1623c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1624fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen case FOURCC('d', 'i', 's', 'k'): 1625fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen { 1626fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen if (size == 14 && flags == 0) { 1627fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen char tmp[16]; 1628fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen sprintf(tmp, "%d/%d", 1629fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen (int)buffer[size - 3], (int)buffer[size - 1]); 1630fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen 1631fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen mFileMetaData->setCString(kKeyDiscNumber, tmp); 1632fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1633fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen break; 1634fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1635fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen 1636c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber default: 1637c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1638c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1639c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1640c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (size >= 8 && metadataKey) { 1641c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (metadataKey == kKeyAlbumArt) { 1642c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setData( 1643c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber kKeyAlbumArt, MetaData::TYPE_NONE, 1644c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer + 8, size - 8); 1645c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else if (metadataKey == kKeyGenre) { 1646c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (flags == 0) { 1647fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // uint8_t genre code, iTunes genre codes are 1648fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // the standard id3 codes, except they start 1649fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // at 1 instead of 0 (e.g. Pop is 14, not 13) 1650fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // We use standard id3 numbering, so subtract 1. 1651fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen int genrecode = (int)buffer[size - 1]; 1652fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen genrecode--; 1653fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen if (genrecode < 0) { 1654fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen genrecode = 255; // reserved for 'unknown genre' 1655fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1656c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber char genre[10]; 1657fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen sprintf(genre, "%d", genrecode); 1658c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1659c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(metadataKey, genre); 1660fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } else if (flags == 1) { 1661fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // custom genre string 1662fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen buffer[size] = '\0'; 1663fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen 1664fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen mFileMetaData->setCString( 1665fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen metadataKey, (const char *)buffer + 8); 1666c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1667c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else { 1668c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer[size] = '\0'; 1669c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1670c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString( 1671c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey, (const char *)buffer + 8); 1672c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1673c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1674c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1675c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber delete[] buffer; 1676c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer = NULL; 1677c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1678c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return OK; 1679c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber} 1680c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1681be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) { 1682e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 1683e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if ((err = readMetaData()) != OK) { 1684be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return NULL; 1685e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1686e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1687e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 1688e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (index > 0) { 1689e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (track == NULL) { 1690be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return NULL; 1691e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1692e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1693e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = track->next; 1694e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber --index; 1695e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1696e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 16972a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber if (track == NULL) { 16982a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber return NULL; 16992a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber } 17002a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber 1701be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return new MPEG4Source( 1702fa8de752507feaca695123911915070c1ce463b2Andreas Huber track->meta, mDataSource, track->timescale, track->sampleTable); 1703e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1704e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 17055ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber// static 17065ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) { 17075ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber const char *mime; 17085ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 17095ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 17105ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber uint32_t type; 17115ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber const void *data; 17125ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber size_t size; 17135ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 17145ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (!track->meta->findData(kKeyAVCC, &type, &data, &size) 17155ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber || type != kTypeAVCC) { 17165ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 17175ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 17185ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 17195ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 17205ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (!track->meta->findData(kKeyESDS, &type, &data, &size) 17215ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber || type != kTypeESDS) { 17225ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 17235ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 17245ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 17255ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 1726987cb2ed4a3aebdb624088c38981b2409ab8f6b1Andreas Huber if (!track->sampleTable->isValid()) { 1727987cb2ed4a3aebdb624088c38981b2409ab8f6b1Andreas Huber // Make sure we have all the metadata we need. 1728987cb2ed4a3aebdb624088c38981b2409ab8f6b1Andreas Huber return ERROR_MALFORMED; 1729987cb2ed4a3aebdb624088c38981b2409ab8f6b1Andreas Huber } 1730987cb2ed4a3aebdb624088c38981b2409ab8f6b1Andreas Huber 17315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return OK; 17325ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber} 17335ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 1734d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( 1735d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber const void *esds_data, size_t esds_size) { 1736d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber ESDS esds(esds_data, esds_size); 1737d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber 1738d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber uint8_t objectTypeIndication; 1739d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) { 1740d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber return ERROR_MALFORMED; 1741d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber } 1742d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber 1743d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber if (objectTypeIndication == 0xe1) { 1744d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber // This isn't MPEG4 audio at all, it's QCELP 14k... 1745d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP); 1746d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber return OK; 1747d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber } 1748d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber 1749e883d317d51733145b880ce11c610f0287fba447James Dong if (objectTypeIndication == 0x6b) { 1750e883d317d51733145b880ce11c610f0287fba447James Dong // The media subtype is MP3 audio 1751e883d317d51733145b880ce11c610f0287fba447James Dong // Our software MP3 audio decoder may not be able to handle 1752e883d317d51733145b880ce11c610f0287fba447James Dong // packetized MP3 audio; for now, lets just return ERROR_UNSUPPORTED 1753e883d317d51733145b880ce11c610f0287fba447James Dong LOGE("MP3 track in MP4/3GPP file is not supported"); 1754e883d317d51733145b880ce11c610f0287fba447James Dong return ERROR_UNSUPPORTED; 1755e883d317d51733145b880ce11c610f0287fba447James Dong } 1756e883d317d51733145b880ce11c610f0287fba447James Dong 1757d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber const uint8_t *csd; 1758d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber size_t csd_size; 1759d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (esds.getCodecSpecificInfo( 1760d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber (const void **)&csd, &csd_size) != OK) { 1761d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1762d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1763d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1764d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#if 0 1765d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber printf("ESD of size %d\n", csd_size); 1766d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber hexdump(csd, csd_size); 1767d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#endif 1768d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 176908c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber if (csd_size == 0) { 177008c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber // There's no further information, i.e. no codec specific data 177108c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber // Let's assume that the information provided in the mpeg4 headers 177208c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber // is accurate and hope for the best. 177308c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber 177408c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber return OK; 177508c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber } 177608c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber 1777d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (csd_size < 2) { 1778d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1779d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1780d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1781d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber uint32_t objectType = csd[0] >> 3; 1782d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1783d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (objectType == 31) { 1784d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_UNSUPPORTED; 1785d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1786d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1787d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7); 1788d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t sampleRate = 0; 1789d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t numChannels = 0; 1790d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (freqIndex == 15) { 1791d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (csd_size < 5) { 1792d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1793d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1794d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1795d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber sampleRate = (csd[1] & 0x7f) << 17 1796d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber | csd[2] << 9 1797d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber | csd[3] << 1 1798d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber | (csd[4] >> 7); 1799d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1800d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber numChannels = (csd[4] >> 3) & 15; 1801d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } else { 1802cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber static uint32_t kSamplingRate[] = { 1803cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 1804cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber 16000, 12000, 11025, 8000, 7350 1805cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber }; 1806d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1807d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (freqIndex == 13 || freqIndex == 14) { 1808d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1809d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1810d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1811d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber sampleRate = kSamplingRate[freqIndex]; 1812d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber numChannels = (csd[1] >> 3) & 15; 1813d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1814d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1815d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (numChannels == 0) { 1816d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_UNSUPPORTED; 1817d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1818d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1819d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t prevSampleRate; 1820d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate)); 1821d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1822d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (prevSampleRate != sampleRate) { 18234a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber LOGV("mpeg4 audio sample rate different from previous setting. " 1824d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber "was: %d, now: %d", prevSampleRate, sampleRate); 1825d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1826d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1827d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sampleRate); 1828d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1829d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t prevChannelCount; 1830d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount)); 1831d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1832d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (prevChannelCount != numChannels) { 18334a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber LOGV("mpeg4 audio channel count different from previous setting. " 1834d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber "was: %d, now: %d", prevChannelCount, numChannels); 1835d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1836d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1837d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, numChannels); 1838d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1839d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return OK; 1840d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber} 1841d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1842e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber//////////////////////////////////////////////////////////////////////////////// 1843e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1844e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::MPEG4Source( 1845e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const sp<MetaData> &format, 1846be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<DataSource> &dataSource, 1847fa8de752507feaca695123911915070c1ce463b2Andreas Huber int32_t timeScale, 1848be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<SampleTable> &sampleTable) 1849e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber : mFormat(format), 1850e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mDataSource(dataSource), 1851fa8de752507feaca695123911915070c1ce463b2Andreas Huber mTimescale(timeScale), 1852e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mSampleTable(sampleTable), 1853e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentSampleIndex(0), 1854e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mIsAVC(false), 1855db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mNALLengthSize(0), 1856e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted(false), 1857e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup(NULL), 1858e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer(NULL), 18594f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mWantsNALFragments(false), 18608a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber mSrcBuffer(NULL) { 1861e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const char *mime; 1862e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bool success = mFormat->findCString(kKeyMIMEType, &mime); 18634f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(success); 1864e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1865e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 1866db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1867db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber if (mIsAVC) { 1868db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber uint32_t type; 1869db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber const void *data; 1870db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t size; 1871db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(format->findData(kKeyAVCC, &type, &data, &size)); 1872db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1873db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber const uint8_t *ptr = (const uint8_t *)data; 1874db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1875db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(size >= 7); 1876940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 1877db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1878db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber // The number of bytes used to encode the length of a NAL unit. 1879db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mNALLengthSize = 1 + (ptr[4] & 3); 1880db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber } 1881e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1882e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1883e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::~MPEG4Source() { 1884e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mStarted) { 1885e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber stop(); 1886e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1887e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1888e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1889e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::start(MetaData *params) { 1890ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1891ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 18924f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(!mStarted); 1893e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1894e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t val; 18954f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (params && params->findInt32(kKeyWantsNALFragments, &val) 1896e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber && val != 0) { 18974f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mWantsNALFragments = true; 1898e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 18994f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mWantsNALFragments = false; 1900e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1901e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1902e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup = new MediaBufferGroup; 1903e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 19041bceff916a72246fa208605d50615823d7f1688bAndreas Huber int32_t max_size; 19051bceff916a72246fa208605d50615823d7f1688bAndreas Huber CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size)); 1906e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 19071bceff916a72246fa208605d50615823d7f1688bAndreas Huber mGroup->add_buffer(new MediaBuffer(max_size)); 19088a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber 19098a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber mSrcBuffer = new uint8_t[max_size]; 1910e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1911e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted = true; 1912e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1913e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1914e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1915e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1916e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::stop() { 1917ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1918ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 19194f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(mStarted); 1920e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1921e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mBuffer != NULL) { 1922e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->release(); 1923e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1924e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1925e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 19268a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber delete[] mSrcBuffer; 19278a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber mSrcBuffer = NULL; 19288a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber 1929e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber delete mGroup; 1930e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup = NULL; 1931e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1932e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted = false; 1933e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentSampleIndex = 0; 1934e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1935e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1936e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1937e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1938e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> MPEG4Source::getFormat() { 1939ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1940ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 1941e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return mFormat; 1942e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1943e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1944db5d662254f2ed788d32e2466739adc8d655c732Andreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const { 1945db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber switch (mNALLengthSize) { 1946db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 1: 1947db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return *data; 1948db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 2: 1949db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return U16_AT(data); 1950db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 3: 1951db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return ((size_t)data[0] << 16) | U16_AT(&data[1]); 1952db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 4: 1953db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return U32_AT(data); 1954db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber } 1955db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1956db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber // This cannot happen, mNALLengthSize springs to life by adding 1 to 1957db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber // a 2-bit integer. 1958db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(!"Should not be here."); 1959db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1960db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return 0; 1961db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber} 1962db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1963e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::read( 1964e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer **out, const ReadOptions *options) { 1965ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1966ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 19674f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(mStarted); 1968e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1969e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out = NULL; 1970e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 19716624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber int64_t targetSampleTimeUs = -1; 19726624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 1973e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int64_t seekTimeUs; 19746624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber ReadOptions::SeekMode mode; 19756624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 19766624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber uint32_t findFlags = 0; 19776624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber switch (mode) { 19786624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber case ReadOptions::SEEK_PREVIOUS_SYNC: 19796624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber findFlags = SampleTable::kFlagBefore; 19806624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber break; 19816624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber case ReadOptions::SEEK_NEXT_SYNC: 19826624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber findFlags = SampleTable::kFlagAfter; 19836624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber break; 19846624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber case ReadOptions::SEEK_CLOSEST_SYNC: 19856624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber case ReadOptions::SEEK_CLOSEST: 19866624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber findFlags = SampleTable::kFlagClosest; 19876624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber break; 19886624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber default: 19896624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber CHECK(!"Should not be here."); 19906624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber break; 19916624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 19926624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 1993e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t sampleIndex; 19946624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber status_t err = mSampleTable->findSampleAtTime( 1995e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber seekTimeUs * mTimescale / 1000000, 19966624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber &sampleIndex, findFlags); 19976624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 19986624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 19996624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber // We found the closest sample already, now we want the sync 20006624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber // sample preceding it (or the sample itself of course), even 20016624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber // if the subsequent sync sample is closer. 20026624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber findFlags = SampleTable::kFlagBefore; 20036624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 20046624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 20056624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber uint32_t syncSampleIndex; 20066624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (err == OK) { 20076624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber err = mSampleTable->findSyncSampleNear( 20086624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber sampleIndex, &syncSampleIndex, findFlags); 20096624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 2010e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 201190ba107fcf36ce6df111a594b2cc27163b36793dAndreas Huber uint32_t sampleTime; 201290ba107fcf36ce6df111a594b2cc27163b36793dAndreas Huber if (err == OK) { 201390ba107fcf36ce6df111a594b2cc27163b36793dAndreas Huber err = mSampleTable->getMetaDataForSample( 201490ba107fcf36ce6df111a594b2cc27163b36793dAndreas Huber sampleIndex, NULL, NULL, &sampleTime); 201590ba107fcf36ce6df111a594b2cc27163b36793dAndreas Huber } 201690ba107fcf36ce6df111a594b2cc27163b36793dAndreas Huber 2017e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 2018d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber if (err == ERROR_OUT_OF_RANGE) { 2019d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // An attempt to seek past the end of the stream would 2020d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // normally cause this ERROR_OUT_OF_RANGE error. Propagating 2021d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // this all the way to the MediaPlayer would cause abnormal 2022d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // termination. Legacy behaviour appears to be to behave as if 2023d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // we had seeked to the end of stream, ending normally. 2024d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber err = ERROR_END_OF_STREAM; 2025d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber } 2026e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 2027e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 2028e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 20296624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 20306624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale; 20316624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 20326624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 20336624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber#if 0 20346624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber uint32_t syncSampleTime; 20356624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber CHECK_EQ(OK, mSampleTable->getMetaDataForSample( 20366624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber syncSampleIndex, NULL, NULL, &syncSampleTime)); 20376624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 20386624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber LOGI("seek to time %lld us => sample at time %lld us, " 20396624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber "sync sample at time %lld us", 20406624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber seekTimeUs, 20416624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber sampleTime * 1000000ll / mTimescale, 20426624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber syncSampleTime * 1000000ll / mTimescale); 20436624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber#endif 20446624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 20456624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber mCurrentSampleIndex = syncSampleIndex; 2046e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mBuffer != NULL) { 2047e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->release(); 2048e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 2049e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 2050e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2051e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // fall through 2052e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 2053e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2054b1262a8b1dd23abad64465f9ffd25c44facdf4d2James Dong off64_t offset; 20558a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber size_t size; 205644fdac0c62916ddcfac1fe887d867e7ff0cf446fAndreas Huber uint32_t cts; 2057ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber bool isSyncSample; 20584f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber bool newBuffer = false; 20594f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (mBuffer == NULL) { 20604f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber newBuffer = true; 2061e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 20621faa92a1e93f311e86dca483ed7702091137de66Andreas Huber status_t err = 20631faa92a1e93f311e86dca483ed7702091137de66Andreas Huber mSampleTable->getMetaDataForSample( 206444fdac0c62916ddcfac1fe887d867e7ff0cf446fAndreas Huber mCurrentSampleIndex, &offset, &size, &cts, &isSyncSample); 2065e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 20664f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (err != OK) { 20674f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return err; 20684f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 20694f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 20704f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber err = mGroup->acquire_buffer(&mBuffer); 20711faa92a1e93f311e86dca483ed7702091137de66Andreas Huber 20724f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (err != OK) { 2073940c866c992f122be7aeb92a1b314d7df437d4e2Andreas Huber CHECK(mBuffer == NULL); 20744f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return err; 20754f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 20768a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber } 2077e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 20784f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (!mIsAVC || mWantsNALFragments) { 20794f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (newBuffer) { 20804f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber ssize_t num_bytes_read = 20819a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 20824f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 20834f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (num_bytes_read < (ssize_t)size) { 20844f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->release(); 20854f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer = NULL; 20864f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 20874f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return ERROR_IO; 20884f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 20894f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 2090ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(mBuffer != NULL); 20914f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->set_range(0, size); 20924f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->meta_data()->clear(); 2093fa8de752507feaca695123911915070c1ce463b2Andreas Huber mBuffer->meta_data()->setInt64( 209444fdac0c62916ddcfac1fe887d867e7ff0cf446fAndreas Huber kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 20956624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 20966624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (targetSampleTimeUs >= 0) { 20976624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber mBuffer->meta_data()->setInt64( 20986624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber kKeyTargetTime, targetSampleTimeUs); 20996624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 21006624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 2101ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber if (isSyncSample) { 2102ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 2103ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber } 2104ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber 21054f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber ++mCurrentSampleIndex; 21064f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 21074f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 21084f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (!mIsAVC) { 21094f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber *out = mBuffer; 21104f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer = NULL; 21114f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 21124f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return OK; 21134f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 21144f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 21154f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // Each NAL unit is split up into its constituent fragments and 21164f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // each one of them returned in its own buffer. 21174f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 2118db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(mBuffer->range_length() >= mNALLengthSize); 21194f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 21204f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber const uint8_t *src = 21214f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 21224f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 2123db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t nal_size = parseNALSize(src); 2124909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber if (mBuffer->range_length() < mNALLengthSize + nal_size) { 2125909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber LOGE("incomplete NAL unit."); 2126909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 2127909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer->release(); 2128909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer = NULL; 2129909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 2130909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber return ERROR_MALFORMED; 2131909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber } 21324f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 21334f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber MediaBuffer *clone = mBuffer->clone(); 2134ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(clone != NULL); 2135db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 21364f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 2137ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(mBuffer != NULL); 21384f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->set_range( 2139db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mBuffer->range_offset() + mNALLengthSize + nal_size, 2140db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mBuffer->range_length() - mNALLengthSize - nal_size); 21414f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 21424f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (mBuffer->range_length() == 0) { 21434f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->release(); 21444f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer = NULL; 21454f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 21464f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 21474f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber *out = clone; 21484f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 21494f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return OK; 21504f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } else { 21514f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // Whole NAL units are returned but each fragment is prefixed by 21524f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // the start code (0x00 00 00 01). 2153d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang ssize_t num_bytes_read = 0; 2154d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang int32_t drm = 0; 2155d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang bool usesDRM = (mFormat->findInt32(kKeyIsDRM, &drm) && drm != 0); 2156d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (usesDRM) { 2157d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang num_bytes_read = 2158d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang mDataSource->readAt(offset, (uint8_t*)mBuffer->data(), size); 2159d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } else { 2160d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang num_bytes_read = mDataSource->readAt(offset, mSrcBuffer, size); 2161d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 2162e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2163e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (num_bytes_read < (ssize_t)size) { 2164e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->release(); 2165e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 2166e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 21674f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return ERROR_IO; 2168e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 2169e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2170d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (usesDRM) { 2171d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang CHECK(mBuffer != NULL); 2172d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang mBuffer->set_range(0, size); 2173db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 2174d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } else { 2175d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang uint8_t *dstData = (uint8_t *)mBuffer->data(); 2176d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang size_t srcOffset = 0; 2177d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang size_t dstOffset = 0; 2178909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 2179d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang while (srcOffset < size) { 218034d76acc4edb359a8639ddb6ce537b5156deb760James Dong bool isMalFormed = (srcOffset + mNALLengthSize > size); 218134d76acc4edb359a8639ddb6ce537b5156deb760James Dong size_t nalLength = 0; 218234d76acc4edb359a8639ddb6ce537b5156deb760James Dong if (!isMalFormed) { 218334d76acc4edb359a8639ddb6ce537b5156deb760James Dong nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 218434d76acc4edb359a8639ddb6ce537b5156deb760James Dong srcOffset += mNALLengthSize; 218534d76acc4edb359a8639ddb6ce537b5156deb760James Dong isMalFormed = srcOffset + nalLength > size; 218634d76acc4edb359a8639ddb6ce537b5156deb760James Dong } 2187909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 218834d76acc4edb359a8639ddb6ce537b5156deb760James Dong if (isMalFormed) { 218934d76acc4edb359a8639ddb6ce537b5156deb760James Dong LOGE("Video is malformed"); 2190d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang mBuffer->release(); 2191d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang mBuffer = NULL; 2192d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang return ERROR_MALFORMED; 2193d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 2194d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang 2195d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang if (nalLength == 0) { 2196d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang continue; 2197d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 21984f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 2199d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang CHECK(dstOffset + 4 <= mBuffer->size()); 22004f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 2201d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang dstData[dstOffset++] = 0; 2202d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang dstData[dstOffset++] = 0; 2203d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang dstData[dstOffset++] = 0; 2204d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang dstData[dstOffset++] = 1; 2205d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 2206d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang srcOffset += nalLength; 2207d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang dstOffset += nalLength; 2208d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang } 2209d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang CHECK_EQ(srcOffset, size); 2210d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang CHECK(mBuffer != NULL); 2211d5770917a50a828cb4337c2a392b3e4a375624b9Gloria Wang mBuffer->set_range(0, dstOffset); 22124f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 22134f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 2214e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->meta_data()->clear(); 2215fa8de752507feaca695123911915070c1ce463b2Andreas Huber mBuffer->meta_data()->setInt64( 221644fdac0c62916ddcfac1fe887d867e7ff0cf446fAndreas Huber kKeyTime, ((int64_t)cts * 1000000) / mTimescale); 22176624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 22186624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (targetSampleTimeUs >= 0) { 22196624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber mBuffer->meta_data()->setInt64( 22206624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber kKeyTargetTime, targetSampleTimeUs); 22216624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 22226624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 2223ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber if (isSyncSample) { 2224ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 2225ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber } 2226ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber 2227e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ++mCurrentSampleIndex; 2228e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2229e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out = mBuffer; 2230e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 2231e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2232e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 2233e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 2234e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 2235e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2236f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas HuberMPEG4Extractor::Track *MPEG4Extractor::findTrackByMimePrefix( 2237f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber const char *mimePrefix) { 2238f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber for (Track *track = mFirstTrack; track != NULL; track = track->next) { 2239f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber const char *mime; 2240f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber if (track->meta != NULL 2241f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber && track->meta->findCString(kKeyMIMEType, &mime) 2242f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber && !strncasecmp(mime, mimePrefix, strlen(mimePrefix))) { 2243f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber return track; 2244f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber } 2245f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber } 2246f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber 2247f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber return NULL; 2248f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber} 2249f80e45a60a93c7bd63a47f5cb23750b69567fc37Andreas Huber 2250261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool LegacySniffMPEG4( 2251be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 2252e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t header[8]; 2253e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 22549a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber ssize_t n = source->readAt(4, header, sizeof(header)); 2255e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (n < (ssize_t)sizeof(header)) { 2256e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 2257e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 2258e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2259e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8) 2260e1130662d0455231853e7d6880bb84d8547d7229James Dong || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8) 2261e1130662d0455231853e7d6880bb84d8547d7229James Dong || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8) 22626bce6d87b3fd98e68fb54328fb4dc8e40cd2c293Andreas Huber || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8) 2263dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8) 2264eea1eefeada90ec54488e1742e81e4226fc6ace5Andreas Huber || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) { 2265e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 2266efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber *confidence = 0.4; 2267e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2268e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return true; 2269e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 2270e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2271e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 2272e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 2273e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2274261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) { 2275261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber static const uint32_t kCompatibleBrands[] = { 2276261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('i', 's', 'o', 'm'), 2277261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('i', 's', 'o', '2'), 2278261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('a', 'v', 'c', '1'), 2279261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('3', 'g', 'p', '4'), 2280261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('m', 'p', '4', '1'), 2281261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('m', 'p', '4', '2'), 22825f3586e1ad21b011ff7d70ce26c2e0aa6d44a3ffJames Dong 22835f3586e1ad21b011ff7d70ce26c2e0aa6d44a3ffJames Dong // Won't promise that the following file types can be played. 22845f3586e1ad21b011ff7d70ce26c2e0aa6d44a3ffJames Dong // Just give these file types a chance. 22855f3586e1ad21b011ff7d70ce26c2e0aa6d44a3ffJames Dong FOURCC('q', 't', ' ', ' '), // Apple's QuickTime 22865f3586e1ad21b011ff7d70ce26c2e0aa6d44a3ffJames Dong FOURCC('M', 'S', 'N', 'V'), // Sony's PSP 2287708d908668b4c3d0ac2493dfc06385dfd8693dc9Andreas Huber 2288708d908668b4c3d0ac2493dfc06385dfd8693dc9Andreas Huber FOURCC('3', 'g', '2', 'a'), // 3GPP2 2289708d908668b4c3d0ac2493dfc06385dfd8693dc9Andreas Huber FOURCC('3', 'g', '2', 'b'), 2290261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber }; 2291261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2292261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber for (size_t i = 0; 2293261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]); 2294261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber ++i) { 2295261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (kCompatibleBrands[i] == fourcc) { 2296261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return true; 2297261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 2298261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 2299261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2300261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 2301261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber} 2302261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2303261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable 2304261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber// compatible brand is present. 2305b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber// Also try to identify where this file's metadata ends 2306b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber// (end of the 'moov' atom) and report it to the caller as part of 2307b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber// the metadata. 2308261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool BetterSniffMPEG4( 2309b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 2310b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber sp<AMessage> *meta) { 2311b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber // We scan up to 128 bytes to identify this file as an MP4. 2312b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber static const off64_t kMaxScanOffset = 128ll; 2313261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2314b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber off64_t offset = 0ll; 2315b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber bool foundGoodFileType = false; 2316b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber off64_t moovAtomEndOffset = -1ll; 2317b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber bool done = false; 2318261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2319b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber while (!done && offset < kMaxScanOffset) { 2320b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber uint32_t hdr[2]; 2321b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber if (source->readAt(offset, hdr, 8) < 8) { 2322b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber return false; 2323b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber } 2324b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2325b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber uint64_t chunkSize = ntohl(hdr[0]); 2326b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber uint32_t chunkType = ntohl(hdr[1]); 2327b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber off64_t chunkDataOffset = offset + 8; 2328b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2329b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber if (chunkSize == 1) { 2330b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber if (source->readAt(offset + 8, &chunkSize, 8) < 8) { 2331261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 2332261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 2333261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2334b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber chunkSize = ntoh64(chunkSize); 2335b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber chunkDataOffset += 8; 2336b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2337b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber if (chunkSize < 16) { 2338b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber // The smallest valid chunk is 16 bytes long in this case. 2339b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber return false; 2340b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber } 2341b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber } else if (chunkSize < 8) { 2342b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber // The smallest valid chunk is 8 bytes long. 2343b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber return false; 2344b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber } 2345b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2346b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber off64_t chunkDataSize = offset + chunkSize - chunkDataOffset; 2347b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2348b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber switch (chunkType) { 2349b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber case FOURCC('f', 't', 'y', 'p'): 2350b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber { 2351b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber if (chunkDataSize < 8) { 2352b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber return false; 2353b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber } 2354b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2355b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4; 2356b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber for (size_t i = 0; i < numCompatibleBrands + 2; ++i) { 2357b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber if (i == 1) { 2358b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber // Skip this index, it refers to the minorVersion, 2359b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber // not a brand. 2360b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber continue; 2361b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber } 2362b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2363b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber uint32_t brand; 2364b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber if (source->readAt( 2365b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber chunkDataOffset + 4 * i, &brand, 4) < 4) { 2366b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber return false; 2367b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber } 2368b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2369b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber brand = ntohl(brand); 2370b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2371b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber if (isCompatibleBrand(brand)) { 2372b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber foundGoodFileType = true; 2373b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber break; 2374b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber } 2375b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber } 2376b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2377b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber if (!foundGoodFileType) { 2378b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber return false; 2379b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber } 2380b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2381261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber break; 2382261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 2383b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2384b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber case FOURCC('m', 'o', 'o', 'v'): 2385b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber { 2386b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber moovAtomEndOffset = offset + chunkSize; 2387b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2388b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber done = true; 2389b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber break; 2390b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber } 2391b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2392b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber default: 2393b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber break; 2394261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 2395b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2396b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber offset += chunkSize; 2397261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 2398261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2399b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber if (!foundGoodFileType) { 2400261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 2401261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 2402261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2403261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 2404efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber *confidence = 0.4f; 2405261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2406b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber if (moovAtomEndOffset >= 0) { 2407b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber *meta = new AMessage; 2408b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber (*meta)->setInt64("meta-data-size", moovAtomEndOffset); 2409b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2410b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber LOGV("found metadata size: %lld", moovAtomEndOffset); 2411b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber } 2412b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber 2413261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return true; 2414261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber} 2415261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2416261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberbool SniffMPEG4( 2417efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 2418b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber sp<AMessage> *meta) { 2419b8e651a6757c8e55fc3d9e5e86a13ead7326e91dAndreas Huber if (BetterSniffMPEG4(source, mimeType, confidence, meta)) { 2420261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return true; 2421261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 2422261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2423261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (LegacySniffMPEG4(source, mimeType, confidence)) { 2424261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber LOGW("Identified supported mpeg4 through LegacySniffMPEG4."); 2425261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return true; 2426261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 2427261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2428261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 2429261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber} 2430261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 2431e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} // namespace android 2432e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2433