MPEG4Extractor.cpp revision 08c94b265c4bf7105b593afb119053a2e16865e9
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" 22bd7b43bb02852e51b3000185fa66e10c56b120e0Andreas Huber 23e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <arpa/inet.h> 24e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 25e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <ctype.h> 26e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <stdint.h> 27e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <stdlib.h> 28e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <string.h> 29e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 30e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/DataSource.h> 31d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#include "include/ESDS.h" 32e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBuffer.h> 33e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBufferGroup.h> 344f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber#include <media/stagefright/MediaDebug.h> 35e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber#include <media/stagefright/MediaDefs.h> 36e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaSource.h> 37e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MetaData.h> 38e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/Utils.h> 39e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/String8.h> 40e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 41e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubernamespace android { 42e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 43e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberclass MPEG4Source : public MediaSource { 44e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberpublic: 45e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Caller retains ownership of both "dataSource" and "sampleTable". 46be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber MPEG4Source(const sp<MetaData> &format, 47be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<DataSource> &dataSource, 48fa8de752507feaca695123911915070c1ce463b2Andreas Huber int32_t timeScale, 49be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<SampleTable> &sampleTable); 50e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 51e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual status_t start(MetaData *params = NULL); 52e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual status_t stop(); 53e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 54e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual sp<MetaData> getFormat(); 55e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 56e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual status_t read( 57e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 58e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 59be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberprotected: 60be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber virtual ~MPEG4Source(); 61be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber 62e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberprivate: 63ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex mLock; 64ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 65e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber sp<MetaData> mFormat; 66be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber sp<DataSource> mDataSource; 67e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t mTimescale; 68be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber sp<SampleTable> mSampleTable; 69e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t mCurrentSampleIndex; 70e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 71e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bool mIsAVC; 72db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t mNALLengthSize; 73db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 74e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bool mStarted; 75e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 76e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBufferGroup *mGroup; 77e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 78e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer *mBuffer; 79e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 804f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber bool mWantsNALFragments; 81e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 828a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber uint8_t *mSrcBuffer; 838a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber 84db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t parseNALSize(const uint8_t *data) const; 85db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 86e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MPEG4Source(const MPEG4Source &); 87e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MPEG4Source &operator=(const MPEG4Source &); 88e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}; 89e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 90affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// This custom data source wraps an existing one and satisfies requests 91affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// falling entirely within a cached range from the cache while forwarding 92affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// all remaining requests to the wrapped datasource. 93affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// This is used to cache the full sampletable metadata for a single track, 94affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// possibly wrapping multiple times to cover all tracks, i.e. 95affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track. 96affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 97affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstruct MPEG4DataSource : public DataSource { 98affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber MPEG4DataSource(const sp<DataSource> &source); 99affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 100affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual status_t initCheck() const; 101affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual ssize_t readAt(off_t offset, void *data, size_t size); 102affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual status_t getSize(off_t *size); 103affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual uint32_t flags(); 104affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 105affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber status_t setCachedRange(off_t offset, size_t size); 106affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 107affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberprotected: 108affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual ~MPEG4DataSource(); 109affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 110affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberprivate: 111affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber Mutex mLock; 112affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 113affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber sp<DataSource> mSource; 114affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber off_t mCachedOffset; 115affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber size_t mCachedSize; 116affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber uint8_t *mCache; 117affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 118affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber void clearCache(); 119affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 120affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber MPEG4DataSource(const MPEG4DataSource &); 121affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber MPEG4DataSource &operator=(const MPEG4DataSource &); 122affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}; 123affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 124affa99c52957685f5a5652ab5254b92e729651c7Andreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source) 125affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber : mSource(source), 126affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedOffset(0), 127affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedSize(0), 128affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCache(NULL) { 129affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 130affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 131affa99c52957685f5a5652ab5254b92e729651c7Andreas HuberMPEG4DataSource::~MPEG4DataSource() { 132affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber clearCache(); 133affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 134affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 135affa99c52957685f5a5652ab5254b92e729651c7Andreas Hubervoid MPEG4DataSource::clearCache() { 136affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (mCache) { 137affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber free(mCache); 138affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCache = NULL; 139affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 140affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 141affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedOffset = 0; 142affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedSize = 0; 143affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 144affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 145affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstatus_t MPEG4DataSource::initCheck() const { 146affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return mSource->initCheck(); 147affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 148affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 149affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberssize_t MPEG4DataSource::readAt(off_t offset, void *data, size_t size) { 150affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber Mutex::Autolock autoLock(mLock); 151affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 152affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (offset >= mCachedOffset 153affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber && offset + size <= mCachedOffset + mCachedSize) { 154affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber memcpy(data, &mCache[offset - mCachedOffset], size); 155affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return size; 156affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 157affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 158affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return mSource->readAt(offset, data, size); 159affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 160affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 161affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstatus_t MPEG4DataSource::getSize(off_t *size) { 162affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return mSource->getSize(size); 163affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 164affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 165affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberuint32_t MPEG4DataSource::flags() { 166affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return mSource->flags(); 167affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 168affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 169affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstatus_t MPEG4DataSource::setCachedRange(off_t offset, size_t size) { 170affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber Mutex::Autolock autoLock(mLock); 171affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 172affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber clearCache(); 173affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 174affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCache = (uint8_t *)malloc(size); 175affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 176affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (mCache == NULL) { 177affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return -ENOMEM; 178affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 179affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 180affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedOffset = offset; 181affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedSize = size; 182affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 183affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize); 184affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 185affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (err < (ssize_t)size) { 186affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber clearCache(); 187affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 188affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return ERROR_IO; 189affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 190affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 191affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return OK; 192affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 193affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 194affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber//////////////////////////////////////////////////////////////////////////////// 195affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 196e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic void hexdump(const void *_data, size_t size) { 197e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const uint8_t *data = (const uint8_t *)_data; 198e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber size_t offset = 0; 199e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (offset < size) { 200e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("0x%04x ", offset); 201e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 202e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber size_t n = size - offset; 203e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (n > 16) { 204e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber n = 16; 205e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 206e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 207e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber for (size_t i = 0; i < 16; ++i) { 208e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (i == 8) { 209e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf(" "); 210e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 211e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 212e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (offset + i < size) { 213e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("%02x ", data[offset + i]); 214e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 215e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf(" "); 216e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 217e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 218e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 219e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf(" "); 220e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 221e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber for (size_t i = 0; i < n; ++i) { 222e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (isprint(data[offset + i])) { 223e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("%c", data[offset + i]); 224e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 225e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("."); 226e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 227e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 228e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 229e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("\n"); 230e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 231e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber offset += 16; 232e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 233e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 234e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 235e6c409632f773e41f33188272a0072be9fcb783fAndreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) { 236e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber switch (fourcc) { 237e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'a'): 238e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_AUDIO_AAC; 239e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 240e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 241e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_AUDIO_AMR_NB; 242e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2432a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber case FOURCC('s', 'a', 'w', 'b'): 244e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_AUDIO_AMR_WB; 2452a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber 246e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'v'): 247e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_VIDEO_MPEG4; 248e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 249e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', '2', '6', '3'): 250e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_VIDEO_H263; 251e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 252e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('a', 'v', 'c', '1'): 253e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_VIDEO_AVC; 254e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 255e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber default: 2564f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(!"should not be here."); 257e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return NULL; 258e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 259e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 260e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 261be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source) 262e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber : mDataSource(source), 263e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mHaveMetadata(false), 2641cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber mHasVideo(false), 265e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mFirstTrack(NULL), 266c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mLastTrack(NULL), 267c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData(new MetaData) { 268e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 269e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 270e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Extractor::~MPEG4Extractor() { 271e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 272e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (track) { 273e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *next = track->next; 274e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 275e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber delete track; 276e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = next; 277e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 278e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mFirstTrack = mLastTrack = NULL; 279e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 280e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2811cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() { 2821cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber status_t err; 2831cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber if ((err = readMetaData()) != OK) { 284c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return new MetaData; 2851cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber } 2861cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 287c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return mFileMetaData; 2881cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber} 2891cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 290be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersize_t MPEG4Extractor::countTracks() { 291e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 292e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if ((err = readMetaData()) != OK) { 293be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return 0; 294e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 295e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 296be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber size_t n = 0; 297e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 298e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (track) { 299be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber ++n; 300e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = track->next; 301e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 302e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 303be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return n; 304e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 305e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 306e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData( 307e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber size_t index, uint32_t flags) { 308e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 309e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if ((err = readMetaData()) != OK) { 310e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return NULL; 311e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 312e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 313e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 314e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (index > 0) { 315e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (track == NULL) { 316e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return NULL; 317e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 318e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 319e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = track->next; 320e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber --index; 321e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 322e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 3232a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber if (track == NULL) { 3242a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber return NULL; 3252a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber } 3262a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber 327e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber if ((flags & kIncludeExtensiveMetaData) 328e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber && !track->includes_expensive_metadata) { 329e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber track->includes_expensive_metadata = true; 330e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber 331e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber const char *mime; 332e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 333e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber if (!strncasecmp("video/", mime, 6)) { 334e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber uint32_t sampleIndex; 335e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber uint32_t sampleTime; 336e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK 3371faa92a1e93f311e86dca483ed7702091137de66Andreas Huber && track->sampleTable->getMetaDataForSample( 3381faa92a1e93f311e86dca483ed7702091137de66Andreas Huber sampleIndex, NULL /* offset */, NULL /* size */, 3391faa92a1e93f311e86dca483ed7702091137de66Andreas Huber &sampleTime) == OK) { 340e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber track->meta->setInt64( 341e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber kKeyThumbnailTime, 342e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber ((int64_t)sampleTime * 1000000) / track->timescale); 343e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber } 344e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber } 345e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber } 346e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber 347e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return track->meta; 348e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 349e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 350e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Extractor::readMetaData() { 351e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mHaveMetadata) { 352e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 353e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 354e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 355e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t offset = 0; 356e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 357e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while ((err = parseChunk(&offset, 0)) == OK) { 358e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 3591cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 360e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mHaveMetadata) { 361c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mHasVideo) { 362c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyMIMEType, "video/mp4"); 363c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else { 364c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyMIMEType, "audio/mp4"); 365c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 366c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 367e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 368e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 369e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 370e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 371e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 372e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 373e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic void MakeFourCCString(uint32_t x, char *s) { 374e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[0] = x >> 24; 375e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[1] = (x >> 16) & 0xff; 376e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[2] = (x >> 8) & 0xff; 377e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[3] = x & 0xff; 378e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[4] = '\0'; 379e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 380e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 381c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstruct PathAdder { 382c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder(Vector<uint32_t> *path, uint32_t chunkType) 383c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber : mPath(path) { 384c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mPath->push(chunkType); 385c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 386c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 387c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber ~PathAdder() { 388c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mPath->pop(); 389c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 390c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 391c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberprivate: 392c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber Vector<uint32_t> *mPath; 393c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 394c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder(const PathAdder &); 395c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder &operator=(const PathAdder &); 396c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber}; 397c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 398c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) { 399c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return path.size() >= 5 400c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && path[0] == FOURCC('m', 'o', 'o', 'v') 401c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && path[1] == FOURCC('u', 'd', 't', 'a') 402c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && path[2] == FOURCC('m', 'e', 't', 'a') 403c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && path[3] == FOURCC('i', 'l', 's', 't'); 404c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber} 405c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 406c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string. 407c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) { 408c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600); 409c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 410c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber char tmp[32]; 411c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970)); 412c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 413c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber s->setTo(tmp); 414c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber} 415c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 416e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { 417e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t hdr[2]; 4189a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt(*offset, hdr, 8) < 8) { 419e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 420e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 421e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint64_t chunk_size = ntohl(hdr[0]); 422e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t chunk_type = ntohl(hdr[1]); 423e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t data_offset = *offset + 8; 424e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 425e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_size == 1) { 4269a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { 427e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 428e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 429e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber chunk_size = ntoh64(chunk_size); 430e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset += 8; 431736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber 432736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber if (chunk_size < 16) { 433736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber // The smallest valid chunk is 16 bytes long in this case. 434736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber return ERROR_MALFORMED; 435736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber } 436736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber } else if (chunk_size < 8) { 437736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber // The smallest valid chunk is 8 bytes long. 438736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber return ERROR_MALFORMED; 439e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 440e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 441e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber char chunk[5]; 442e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MakeFourCCString(chunk_type, chunk); 443e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 444e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#if 0 445e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber static const char kWhitespace[] = " "; 446e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth]; 447e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size); 448e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 449e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber char buffer[256]; 450dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber size_t n = chunk_size; 451dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber if (n > sizeof(buffer)) { 452dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber n = sizeof(buffer); 453dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber } 454dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber if (mDataSource->readAt(*offset, buffer, n) 455dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber < (ssize_t)n) { 456dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber return ERROR_IO; 457e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 458dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber 459dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber hexdump(buffer, n); 460e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#endif 461e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 462c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder autoAdder(&mPath, chunk_type); 463c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 464e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t chunk_data_size = *offset + chunk_size - data_offset; 465e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 466c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (chunk_type != FOURCC('c', 'p', 'r', 't') 467c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && mPath.size() == 5 && underMetaDataPath(mPath)) { 468c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber off_t stop_offset = *offset + chunk_size; 469c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset = data_offset; 470c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber while (*offset < stop_offset) { 471c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber status_t err = parseChunk(offset, depth + 1); 472c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (err != OK) { 473c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return err; 474c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 475c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 4765ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 4775ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 4785ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 4795ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 480c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 481c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return OK; 482c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 483c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 484e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber switch(chunk_type) { 485e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'o', 'o', 'v'): 486e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('t', 'r', 'a', 'k'): 487e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'd', 'i', 'a'): 488e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'i', 'n', 'f'): 489e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('d', 'i', 'n', 'f'): 490e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 'b', 'l'): 491e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'v', 'e', 'x'): 492e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'o', 'o', 'f'): 493e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('t', 'r', 'a', 'f'): 494e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'f', 'r', 'a'): 495c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('u', 'd', 't', 'a'): 496c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('i', 'l', 's', 't'): 497e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 498affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (chunk_type == FOURCC('s', 't', 'b', 'l')) { 499affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size); 500affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 501affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (mDataSource->flags() & DataSource::kWantsPrefetching) { 502affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber sp<MPEG4DataSource> cachedSource = 503affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber new MPEG4DataSource(mDataSource); 504affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 505affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (cachedSource->setCachedRange(*offset, chunk_size) == OK) { 506affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mDataSource = cachedSource; 507affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 508affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 509eb9128f9b0ee660504621381fd96f82d5bf8a3fdAndreas Huber 510eb9128f9b0ee660504621381fd96f82d5bf8a3fdAndreas Huber mLastTrack->sampleTable = new SampleTable(mDataSource); 511affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 512affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 5134d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber bool isTrack = false; 5145ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_type == FOURCC('t', 'r', 'a', 'k')) { 5154d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber isTrack = true; 5164d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 5175ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber Track *track = new Track; 5185ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->next = NULL; 5195ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (mLastTrack) { 5205ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber mLastTrack->next = track; 5215ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else { 5225ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber mFirstTrack = track; 5235ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 5245ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber mLastTrack = track; 5255ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 5265ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->meta = new MetaData; 5275ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->includes_expensive_metadata = false; 5284d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber track->skipTrack = false; 5295ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->timescale = 0; 5305ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->meta->setCString(kKeyMIMEType, "application/octet-stream"); 5315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 5325ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 533e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t stop_offset = *offset + chunk_size; 534e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset; 535e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (*offset < stop_offset) { 536e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 537e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 538e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 539e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 540e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 541e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 5425ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 5435ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 5445ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 5455ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 5464d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber if (isTrack) { 5474d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber if (mLastTrack->skipTrack) { 5484d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber Track *cur = mFirstTrack; 5494d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 5504d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber if (cur == mLastTrack) { 5514d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber delete cur; 5524d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber mFirstTrack = mLastTrack = NULL; 5534d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber } else { 5544d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber while (cur && cur->next != mLastTrack) { 5554d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber cur = cur->next; 5564d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber } 5574d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber cur->next = NULL; 5584d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber delete mLastTrack; 5594d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber mLastTrack = cur; 5604d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber } 5614d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 5624d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber return OK; 5634d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber } 5644d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 5655ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber status_t err = verifyTrack(mLastTrack); 5665ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 5675ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (err != OK) { 5685ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return err; 5695ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 5705ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { 571e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mHaveMetadata = true; 572e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 573e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return UNKNOWN_ERROR; // Return a dummy error. 574e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 575e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 576e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 577e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 578e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('t', 'k', 'h', 'd'): 579e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 5805ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_data_size < 4) { 5815ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 5825ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 583e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 584e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t version; 5859a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt(data_offset, &version, 1) < 1) { 586e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 587e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 588e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 589e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint64_t ctime, mtime, duration; 590e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t id; 591e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t width, height; 592e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 593e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 1) { 594e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size != 36 + 60) { 595e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 596e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 597e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 598e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[36 + 60]; 5999a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 600e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 601e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 602e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 603e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 604e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ctime = U64_AT(&buffer[4]); 605e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mtime = U64_AT(&buffer[12]); 606e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber id = U32_AT(&buffer[20]); 607e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber duration = U64_AT(&buffer[28]); 608e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber width = U32_AT(&buffer[88]); 609e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber height = U32_AT(&buffer[92]); 610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else if (version == 0) { 611e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size != 24 + 60) { 612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 615e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[24 + 60]; 6169a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 617e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 618e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 619e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 620e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ctime = U32_AT(&buffer[4]); 621e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mtime = U32_AT(&buffer[8]); 622e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber id = U32_AT(&buffer[12]); 623e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber duration = U32_AT(&buffer[20]); 624e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber width = U32_AT(&buffer[76]); 625e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber height = U32_AT(&buffer[80]); 626e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 628e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 629e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 630e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 631e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 632e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'd', 'h', 'd'): 633e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 634e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 4) { 635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 636e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 637e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 638e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t version; 6399a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 640e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, &version, sizeof(version)) 641e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(version)) { 642e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 643e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 644e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 645e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t timescale_offset; 646e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 647e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 1) { 648e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset = data_offset + 4 + 16; 649e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else if (version == 0) { 650e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset = data_offset + 4 + 8; 651e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 652e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 653e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 654e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 655e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t timescale; 6569a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 657e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset, ×cale, sizeof(timescale)) 658e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(timescale)) { 659e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 660e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 661e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 662e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->timescale = ntohl(timescale); 663e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 664e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int64_t duration; 665e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 1) { 6669a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 667e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset + 4, &duration, sizeof(duration)) 668e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(duration)) { 669e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 670e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 671e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber duration = ntoh64(duration); 672e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 673e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t duration32; 6749a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 675e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset + 4, &duration32, sizeof(duration32)) 676e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(duration32)) { 677e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 678e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 679e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber duration = ntohl(duration32); 680e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 681fa8de752507feaca695123911915070c1ce463b2Andreas Huber mLastTrack->meta->setInt64( 682fa8de752507feaca695123911915070c1ce463b2Andreas Huber kKeyDuration, (duration * 1000000) / mLastTrack->timescale); 683e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 684e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 685e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 686e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 687e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 688e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 'd'): 689e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 690e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 8) { 691e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 692e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 693e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 694e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[8]; 6955ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_data_size < (off_t)sizeof(buffer)) { 6965ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 6975ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 6985ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 6999a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 700e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, 8) < 8) { 701e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 702e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 703e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 704e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (U32_AT(buffer) != 0) { 705e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Should be version 0, flags 0. 706e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 707e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 708e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 709e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t entry_count = U32_AT(&buffer[4]); 710e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 711e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (entry_count > 1) { 712e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // For now we only support a single type of media per track. 7134d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 7144d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber mLastTrack->skipTrack = true; 7154d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber *offset += chunk_size; 7164d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber break; 717e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 718e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 719e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t stop_offset = *offset + chunk_size; 720e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset + 8; 721e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber for (uint32_t i = 0; i < entry_count; ++i) { 722e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 723e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 725e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 726e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 7275ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 7285ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 7295ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 7305ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 731e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 732e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 733e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 734e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'a'): 735e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 7362a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber case FOURCC('s', 'a', 'w', 'b'): 737e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 738e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[8 + 20]; 739e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 740e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Basic AudioSampleEntry size. 741e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 742e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 743e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 7449a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 745e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 746e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 747e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 748e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 749e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 750e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t num_channels = U16_AT(&buffer[16]); 751e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 752d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber uint16_t sample_size = U16_AT(&buffer[18]); 753d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber uint32_t sample_rate = U32_AT(&buffer[24]) >> 16; 754d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber 755e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, 756d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber FourCC2MIME(chunk_type))) { 757d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber // AMR NB audio is always mono, 8kHz 758d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber num_channels = 1; 759d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber sample_rate = 8000; 760d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, 761e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber FourCC2MIME(chunk_type))) { 762d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber // AMR WB audio is always mono, 16kHz 763e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber num_channels = 1; 764d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber sample_rate = 16000; 765e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 766e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 767d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber#if 0 768d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber printf("*** coding='%s' %d channels, size %d, rate %d\n", 769d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber chunk, num_channels, sample_size, sample_rate); 770d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber#endif 771e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 772e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 773e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 774e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 775e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 776e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t stop_offset = *offset + chunk_size; 777e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset + sizeof(buffer); 778e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (*offset < stop_offset) { 779e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 780e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 781e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 782e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 783e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 7845ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 7855ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 7865ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 7875ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 788e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 789e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 790e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 791e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'v'): 792e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', '2', '6', '3'): 793e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('a', 'v', 'c', '1'): 794e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 7951cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber mHasVideo = true; 7961cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 797e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[78]; 798e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 799e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Basic VideoSampleEntry size. 800e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 801e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 802e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 8039a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 804e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 805e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 806e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 807e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 808e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 809e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t width = U16_AT(&buffer[6 + 18]); 810e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t height = U16_AT(&buffer[6 + 20]); 811e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 8122ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber // printf("*** coding='%s' width=%d height=%d\n", 8132ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber // chunk, width, height); 814e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 815e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 816e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeyWidth, width); 817e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeyHeight, height); 818e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 819e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t stop_offset = *offset + chunk_size; 820e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset + sizeof(buffer); 821e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (*offset < stop_offset) { 822e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 823e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 824e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 825e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 826e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 8275ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 8285ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 8295ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 8305ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 831e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 832e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 833e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 834e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 'c', 'o'): 835e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('c', 'o', '6', '4'): 836e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 837e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 838e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setChunkOffsetParams( 839e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber chunk_type, data_offset, chunk_data_size); 840e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 841e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 842e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 843e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 844e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 845e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 846e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 847e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 848e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 849e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 'c'): 850e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 851e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 852e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setSampleToChunkParams( 853e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, chunk_data_size); 854e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 855e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 856e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 857e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 858e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 859e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 860e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 861e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 862e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 863e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 'z'): 864e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 'z', '2'): 865e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 866e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 867e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setSampleSizeParams( 868e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber chunk_type, data_offset, chunk_data_size); 869e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 870e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 871e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 872e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 873e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 8741bceff916a72246fa208605d50615823d7f1688bAndreas Huber size_t max_size; 8751bceff916a72246fa208605d50615823d7f1688bAndreas Huber CHECK_EQ(mLastTrack->sampleTable->getMaxSampleSize(&max_size), OK); 8761bceff916a72246fa208605d50615823d7f1688bAndreas Huber 8771bceff916a72246fa208605d50615823d7f1688bAndreas Huber // Assume that a given buffer only contains at most 10 fragments, 8781bceff916a72246fa208605d50615823d7f1688bAndreas Huber // each fragment originally prefixed with a 2 byte length will 8791bceff916a72246fa208605d50615823d7f1688bAndreas Huber // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion, 8801bceff916a72246fa208605d50615823d7f1688bAndreas Huber // and thus will grow by 2 bytes per fragment. 8811bceff916a72246fa208605d50615823d7f1688bAndreas Huber mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2); 8821bceff916a72246fa208605d50615823d7f1688bAndreas Huber 883e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 884e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 885e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 886e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 887e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 't', 's'): 888e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 889e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 890e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setTimeToSampleParams( 891e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, chunk_data_size); 892e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 893e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 894e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 895e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 896e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 897e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 898e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 899e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 900e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 901e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 's'): 902e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 903e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 904e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setSyncSampleParams( 905e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, chunk_data_size); 906e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 907e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 908e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 909e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 910e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 911e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 912e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 913e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 914e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 915e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('e', 's', 'd', 's'): 916e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 917e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 4) { 918e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 919e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 920e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 921e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[256]; 922e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size > (off_t)sizeof(buffer)) { 923e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_BUFFER_TOO_SMALL; 924e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 925e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 9269a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 927e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 928e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 929e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 930e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 931e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (U32_AT(buffer) != 0) { 932e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Should be version 0, flags 0. 933e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 934e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 935e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 936e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setData( 937e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); 938e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 939d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (mPath.size() >= 2 940d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) { 941d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // Information from the ESDS must be relied on for proper 942d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // setup of sample rate and channel count for MPEG4 Audio. 943d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // The generic header appears to only contain generic 944d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // information... 945d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 946d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio( 947d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber &buffer[4], chunk_data_size - 4); 948d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 949d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (err != OK) { 950d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return err; 951d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 952d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 953d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 954e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 955e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 956e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 957e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 958e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('a', 'v', 'c', 'C'): 959e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 960e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber char buffer[256]; 961e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size > (off_t)sizeof(buffer)) { 962e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_BUFFER_TOO_SMALL; 963e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 964e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 9659a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 966e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 967e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 968e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 969e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 970e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setData( 971e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber kKeyAVCC, kTypeAVCC, buffer, chunk_data_size); 972e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 973e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 974e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 975e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 976e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 977c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('m', 'e', 't', 'a'): 978c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 979c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint8_t buffer[4]; 9805ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_data_size < (off_t)sizeof(buffer)) { 9815ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 9825ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 9835ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 984c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt( 985c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber data_offset, buffer, 4) < 4) { 986c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_IO; 987c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 988c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 989c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (U32_AT(buffer) != 0) { 990c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber // Should be version 0, flags 0. 991dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber 992dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber // If it's not, let's assume this is one of those 993dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber // apparently malformed chunks that don't have flags 994dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber // and completely different semantics than what's 995dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber // in the MPEG4 specs and skip it. 996dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber *offset += chunk_size; 997dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber return OK; 998c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 999c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1000c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber off_t stop_offset = *offset + chunk_size; 1001c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset = data_offset + sizeof(buffer); 1002c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber while (*offset < stop_offset) { 1003c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber status_t err = parseChunk(offset, depth + 1); 1004c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (err != OK) { 1005c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return err; 1006c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1007c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 10085ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 10095ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 10105ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 10115ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 1012c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1013c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1014c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1015c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('d', 'a', 't', 'a'): 1016c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1017c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mPath.size() == 6 && underMetaDataPath(mPath)) { 1018c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber status_t err = parseMetaData(data_offset, chunk_data_size); 1019c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1020c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (err != OK) { 1021c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return err; 1022c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1023c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1024c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1025c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset += chunk_size; 1026c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1027c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1028c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1029c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('m', 'v', 'h', 'd'): 1030c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1031c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (chunk_data_size < 12) { 1032c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_MALFORMED; 1033c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1034c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1035c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint8_t header[12]; 1036c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt( 1037c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber data_offset, header, sizeof(header)) 1038c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber < (ssize_t)sizeof(header)) { 1039c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_IO; 1040c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1041c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1042c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber int64_t creationTime; 1043c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (header[0] == 1) { 1044c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber creationTime = U64_AT(&header[4]); 10455ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else if (header[0] != 0) { 10465ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 1047c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else { 1048c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber creationTime = U32_AT(&header[4]); 1049c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1050c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1051c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber String8 s; 1052c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber convertTimeToDate(creationTime, &s); 1053c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1054c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyDate, s.string()); 1055c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1056c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset += chunk_size; 1057c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1058c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1059c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1060e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber default: 1061e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 1062e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 1063e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 1064e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1065e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1066e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1067e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1068e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1069e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1070c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatus_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) { 1071c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (size < 4) { 1072c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_MALFORMED; 1073c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1074c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1075c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint8_t *buffer = new uint8_t[size + 1]; 1076c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt( 1077c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber offset, buffer, size) != (ssize_t)size) { 1078c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber delete[] buffer; 1079c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer = NULL; 1080c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1081c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_IO; 1082c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1083c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1084c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint32_t flags = U32_AT(buffer); 1085c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1086c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint32_t metadataKey = 0; 1087c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber switch (mPath[4]) { 1088c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'a', 'l', 'b'): 1089c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1090c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyAlbum; 1091c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1092c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1093c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'A', 'R', 'T'): 1094c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1095c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyArtist; 1096c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1097c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1098c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen case FOURCC('a', 'A', 'R', 'T'): 1099c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen { 1100c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen metadataKey = kKeyAlbumArtist; 1101c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen break; 1102c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen } 1103c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'd', 'a', 'y'): 1104c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1105c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyYear; 1106c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1107c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1108c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'n', 'a', 'm'): 1109c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1110c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyTitle; 1111c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1112c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1113c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'w', 'r', 't'): 1114c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1115c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyWriter; 1116c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1117c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1118c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('c', 'o', 'v', 'r'): 1119c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1120c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyAlbumArt; 1121c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1122c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1123c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('g', 'n', 'r', 'e'): 1124c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1125c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyGenre; 1126c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1127c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1128fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen case FOURCC(0xa9, 'g', 'e', 'n'): 1129fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen { 1130fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen metadataKey = kKeyGenre; 1131fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen break; 1132fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1133c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('t', 'r', 'k', 'n'): 1134c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1135c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (size == 16 && flags == 0) { 1136c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber char tmp[16]; 1137c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber sprintf(tmp, "%d/%d", 1138c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber (int)buffer[size - 5], (int)buffer[size - 3]); 1139c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1140c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyCDTrackNumber, tmp); 1141c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1142c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1143c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1144fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen case FOURCC('d', 'i', 's', 'k'): 1145fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen { 1146fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen if (size == 14 && flags == 0) { 1147fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen char tmp[16]; 1148fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen sprintf(tmp, "%d/%d", 1149fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen (int)buffer[size - 3], (int)buffer[size - 1]); 1150fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen 1151fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen mFileMetaData->setCString(kKeyDiscNumber, tmp); 1152fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1153fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen break; 1154fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1155fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen 1156c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber default: 1157c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1158c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1159c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1160c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (size >= 8 && metadataKey) { 1161c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (metadataKey == kKeyAlbumArt) { 1162c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setData( 1163c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber kKeyAlbumArt, MetaData::TYPE_NONE, 1164c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer + 8, size - 8); 1165c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else if (metadataKey == kKeyGenre) { 1166c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (flags == 0) { 1167fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // uint8_t genre code, iTunes genre codes are 1168fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // the standard id3 codes, except they start 1169fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // at 1 instead of 0 (e.g. Pop is 14, not 13) 1170fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // We use standard id3 numbering, so subtract 1. 1171fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen int genrecode = (int)buffer[size - 1]; 1172fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen genrecode--; 1173fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen if (genrecode < 0) { 1174fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen genrecode = 255; // reserved for 'unknown genre' 1175fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1176c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber char genre[10]; 1177fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen sprintf(genre, "%d", genrecode); 1178c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1179c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(metadataKey, genre); 1180fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } else if (flags == 1) { 1181fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // custom genre string 1182fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen buffer[size] = '\0'; 1183fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen 1184fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen mFileMetaData->setCString( 1185fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen metadataKey, (const char *)buffer + 8); 1186c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1187c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else { 1188c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer[size] = '\0'; 1189c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1190c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString( 1191c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey, (const char *)buffer + 8); 1192c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1193c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1194c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1195c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber delete[] buffer; 1196c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer = NULL; 1197c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1198c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return OK; 1199c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber} 1200c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1201be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) { 1202e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 1203e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if ((err = readMetaData()) != OK) { 1204be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return NULL; 1205e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1206e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1207e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 1208e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (index > 0) { 1209e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (track == NULL) { 1210be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return NULL; 1211e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1212e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1213e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = track->next; 1214e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber --index; 1215e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1216e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 12172a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber if (track == NULL) { 12182a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber return NULL; 12192a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber } 12202a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber 1221be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return new MPEG4Source( 1222fa8de752507feaca695123911915070c1ce463b2Andreas Huber track->meta, mDataSource, track->timescale, track->sampleTable); 1223e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1224e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 12255ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber// static 12265ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) { 12275ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber const char *mime; 12285ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 12295ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 12305ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber uint32_t type; 12315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber const void *data; 12325ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber size_t size; 12335ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 12345ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (!track->meta->findData(kKeyAVCC, &type, &data, &size) 12355ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber || type != kTypeAVCC) { 12365ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 12375ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 12385ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 12395ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 12405ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (!track->meta->findData(kKeyESDS, &type, &data, &size) 12415ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber || type != kTypeESDS) { 12425ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 12435ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 12445ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 12455ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 12465ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return OK; 12475ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber} 12485ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 1249d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( 1250d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber const void *esds_data, size_t esds_size) { 1251d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber ESDS esds(esds_data, esds_size); 1252d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber 1253d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber uint8_t objectTypeIndication; 1254d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) { 1255d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber return ERROR_MALFORMED; 1256d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber } 1257d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber 1258d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber if (objectTypeIndication == 0xe1) { 1259d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber // This isn't MPEG4 audio at all, it's QCELP 14k... 1260d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP); 1261d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber return OK; 1262d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber } 1263d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber 1264d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber const uint8_t *csd; 1265d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber size_t csd_size; 1266d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (esds.getCodecSpecificInfo( 1267d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber (const void **)&csd, &csd_size) != OK) { 1268d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1269d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1270d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1271d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#if 0 1272d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber printf("ESD of size %d\n", csd_size); 1273d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber hexdump(csd, csd_size); 1274d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#endif 1275d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 127608c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber if (csd_size == 0) { 127708c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber // There's no further information, i.e. no codec specific data 127808c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber // Let's assume that the information provided in the mpeg4 headers 127908c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber // is accurate and hope for the best. 128008c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber 128108c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber return OK; 128208c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber } 128308c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber 1284d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (csd_size < 2) { 1285d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1286d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1287d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1288d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber uint32_t objectType = csd[0] >> 3; 1289d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1290d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (objectType == 31) { 1291d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_UNSUPPORTED; 1292d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1293d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1294d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7); 1295d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t sampleRate = 0; 1296d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t numChannels = 0; 1297d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (freqIndex == 15) { 1298d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (csd_size < 5) { 1299d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1300d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1301d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1302d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber sampleRate = (csd[1] & 0x7f) << 17 1303d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber | csd[2] << 9 1304d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber | csd[3] << 1 1305d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber | (csd[4] >> 7); 1306d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1307d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber numChannels = (csd[4] >> 3) & 15; 1308d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } else { 1309cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber static uint32_t kSamplingRate[] = { 1310cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 1311cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber 16000, 12000, 11025, 8000, 7350 1312cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber }; 1313d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1314d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (freqIndex == 13 || freqIndex == 14) { 1315d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1316d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1317d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1318d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber sampleRate = kSamplingRate[freqIndex]; 1319d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber numChannels = (csd[1] >> 3) & 15; 1320d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1321d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1322d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (numChannels == 0) { 1323d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_UNSUPPORTED; 1324d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1325d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1326d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t prevSampleRate; 1327d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate)); 1328d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1329d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (prevSampleRate != sampleRate) { 13304a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber LOGV("mpeg4 audio sample rate different from previous setting. " 1331d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber "was: %d, now: %d", prevSampleRate, sampleRate); 1332d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1333d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1334d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sampleRate); 1335d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1336d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t prevChannelCount; 1337d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount)); 1338d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1339d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (prevChannelCount != numChannels) { 13404a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber LOGV("mpeg4 audio channel count different from previous setting. " 1341d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber "was: %d, now: %d", prevChannelCount, numChannels); 1342d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1343d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1344d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, numChannels); 1345d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1346d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return OK; 1347d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber} 1348d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1349e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber//////////////////////////////////////////////////////////////////////////////// 1350e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1351e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::MPEG4Source( 1352e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const sp<MetaData> &format, 1353be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<DataSource> &dataSource, 1354fa8de752507feaca695123911915070c1ce463b2Andreas Huber int32_t timeScale, 1355be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<SampleTable> &sampleTable) 1356e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber : mFormat(format), 1357e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mDataSource(dataSource), 1358fa8de752507feaca695123911915070c1ce463b2Andreas Huber mTimescale(timeScale), 1359e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mSampleTable(sampleTable), 1360e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentSampleIndex(0), 1361e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mIsAVC(false), 1362db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mNALLengthSize(0), 1363e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted(false), 1364e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup(NULL), 1365e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer(NULL), 13664f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mWantsNALFragments(false), 13678a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber mSrcBuffer(NULL) { 1368e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const char *mime; 1369e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bool success = mFormat->findCString(kKeyMIMEType, &mime); 13704f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(success); 1371e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1372e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 1373db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1374db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber if (mIsAVC) { 1375db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber uint32_t type; 1376db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber const void *data; 1377db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t size; 1378db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(format->findData(kKeyAVCC, &type, &data, &size)); 1379db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1380db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber const uint8_t *ptr = (const uint8_t *)data; 1381db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1382db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(size >= 7); 1383db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK_EQ(ptr[0], 1); // configurationVersion == 1 1384db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1385db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber // The number of bytes used to encode the length of a NAL unit. 1386db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mNALLengthSize = 1 + (ptr[4] & 3); 1387db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber } 1388e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1389e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1390e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::~MPEG4Source() { 1391e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mStarted) { 1392e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber stop(); 1393e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1394e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1395e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1396e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::start(MetaData *params) { 1397ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1398ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 13994f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(!mStarted); 1400e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1401e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t val; 14024f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (params && params->findInt32(kKeyWantsNALFragments, &val) 1403e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber && val != 0) { 14044f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mWantsNALFragments = true; 1405e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 14064f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mWantsNALFragments = false; 1407e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1408e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1409e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup = new MediaBufferGroup; 1410e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 14111bceff916a72246fa208605d50615823d7f1688bAndreas Huber int32_t max_size; 14121bceff916a72246fa208605d50615823d7f1688bAndreas Huber CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size)); 1413e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 14141bceff916a72246fa208605d50615823d7f1688bAndreas Huber mGroup->add_buffer(new MediaBuffer(max_size)); 14158a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber 14168a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber mSrcBuffer = new uint8_t[max_size]; 1417e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1418e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted = true; 1419e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1420e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1421e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1422e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1423e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::stop() { 1424ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1425ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 14264f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(mStarted); 1427e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1428e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mBuffer != NULL) { 1429e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->release(); 1430e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1431e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1432e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 14338a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber delete[] mSrcBuffer; 14348a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber mSrcBuffer = NULL; 14358a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber 1436e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber delete mGroup; 1437e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup = NULL; 1438e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1439e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted = false; 1440e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentSampleIndex = 0; 1441e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1442e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1443e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1444e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1445e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> MPEG4Source::getFormat() { 1446ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1447ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 1448e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return mFormat; 1449e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1450e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1451db5d662254f2ed788d32e2466739adc8d655c732Andreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const { 1452db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber switch (mNALLengthSize) { 1453db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 1: 1454db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return *data; 1455db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 2: 1456db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return U16_AT(data); 1457db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 3: 1458db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return ((size_t)data[0] << 16) | U16_AT(&data[1]); 1459db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 4: 1460db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return U32_AT(data); 1461db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber } 1462db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1463db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber // This cannot happen, mNALLengthSize springs to life by adding 1 to 1464db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber // a 2-bit integer. 1465db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(!"Should not be here."); 1466db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1467db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return 0; 1468db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber} 1469db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1470e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::read( 1471e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer **out, const ReadOptions *options) { 1472ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1473ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 14744f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(mStarted); 1475e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1476e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out = NULL; 1477e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 14786624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber int64_t targetSampleTimeUs = -1; 14796624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 1480e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int64_t seekTimeUs; 14816624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber ReadOptions::SeekMode mode; 14826624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 14836624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber uint32_t findFlags = 0; 14846624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber switch (mode) { 14856624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber case ReadOptions::SEEK_PREVIOUS_SYNC: 14866624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber findFlags = SampleTable::kFlagBefore; 14876624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber break; 14886624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber case ReadOptions::SEEK_NEXT_SYNC: 14896624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber findFlags = SampleTable::kFlagAfter; 14906624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber break; 14916624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber case ReadOptions::SEEK_CLOSEST_SYNC: 14926624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber case ReadOptions::SEEK_CLOSEST: 14936624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber findFlags = SampleTable::kFlagClosest; 14946624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber break; 14956624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber default: 14966624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber CHECK(!"Should not be here."); 14976624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber break; 14986624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 14996624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 1500e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t sampleIndex; 15016624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber status_t err = mSampleTable->findSampleAtTime( 1502e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber seekTimeUs * mTimescale / 1000000, 15036624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber &sampleIndex, findFlags); 15046624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 15056624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 15066624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber // We found the closest sample already, now we want the sync 15076624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber // sample preceding it (or the sample itself of course), even 15086624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber // if the subsequent sync sample is closer. 15096624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber findFlags = SampleTable::kFlagBefore; 15106624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 15116624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 15126624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber uint32_t syncSampleIndex; 15136624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (err == OK) { 15146624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber err = mSampleTable->findSyncSampleNear( 15156624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber sampleIndex, &syncSampleIndex, findFlags); 15166624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 1517e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1518e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 1519d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber if (err == ERROR_OUT_OF_RANGE) { 1520d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // An attempt to seek past the end of the stream would 1521d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // normally cause this ERROR_OUT_OF_RANGE error. Propagating 1522d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // this all the way to the MediaPlayer would cause abnormal 1523d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // termination. Legacy behaviour appears to be to behave as if 1524d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // we had seeked to the end of stream, ending normally. 1525d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber err = ERROR_END_OF_STREAM; 1526d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber } 1527e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 1528e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1529e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 15306624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber uint32_t sampleTime; 15316624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber CHECK_EQ(OK, mSampleTable->getMetaDataForSample( 15326624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber sampleIndex, NULL, NULL, &sampleTime)); 15336624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 15346624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 15356624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale; 15366624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 15376624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 15386624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber#if 0 15396624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber uint32_t syncSampleTime; 15406624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber CHECK_EQ(OK, mSampleTable->getMetaDataForSample( 15416624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber syncSampleIndex, NULL, NULL, &syncSampleTime)); 15426624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 15436624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber LOGI("seek to time %lld us => sample at time %lld us, " 15446624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber "sync sample at time %lld us", 15456624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber seekTimeUs, 15466624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber sampleTime * 1000000ll / mTimescale, 15476624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber syncSampleTime * 1000000ll / mTimescale); 15486624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber#endif 15496624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 15506624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber mCurrentSampleIndex = syncSampleIndex; 1551e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mBuffer != NULL) { 1552e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->release(); 1553e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1554e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1555e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1556e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // fall through 1557e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1558e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 15598a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber off_t offset; 15608a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber size_t size; 15614f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber uint32_t dts; 1562ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber bool isSyncSample; 15634f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber bool newBuffer = false; 15644f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (mBuffer == NULL) { 15654f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber newBuffer = true; 1566e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 15671faa92a1e93f311e86dca483ed7702091137de66Andreas Huber status_t err = 15681faa92a1e93f311e86dca483ed7702091137de66Andreas Huber mSampleTable->getMetaDataForSample( 1569ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber mCurrentSampleIndex, &offset, &size, &dts, &isSyncSample); 1570e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 15714f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (err != OK) { 15724f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return err; 15734f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 15744f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15754f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber err = mGroup->acquire_buffer(&mBuffer); 15761faa92a1e93f311e86dca483ed7702091137de66Andreas Huber 15774f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (err != OK) { 15784f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK_EQ(mBuffer, NULL); 15794f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return err; 15804f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 15818a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber } 1582e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 15834f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (!mIsAVC || mWantsNALFragments) { 15844f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (newBuffer) { 15854f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber ssize_t num_bytes_read = 15869a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 15874f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15884f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (num_bytes_read < (ssize_t)size) { 15894f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->release(); 15904f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer = NULL; 15914f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15924f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return ERROR_IO; 15934f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 15944f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1595ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(mBuffer != NULL); 15964f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->set_range(0, size); 15974f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->meta_data()->clear(); 1598fa8de752507feaca695123911915070c1ce463b2Andreas Huber mBuffer->meta_data()->setInt64( 1599fa8de752507feaca695123911915070c1ce463b2Andreas Huber kKeyTime, ((int64_t)dts * 1000000) / mTimescale); 16006624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 16016624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (targetSampleTimeUs >= 0) { 16026624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber mBuffer->meta_data()->setInt64( 16036624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber kKeyTargetTime, targetSampleTimeUs); 16046624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 16056624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 1606ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber if (isSyncSample) { 1607ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 1608ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber } 1609ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber 16104f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber ++mCurrentSampleIndex; 16114f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 16124f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16134f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (!mIsAVC) { 16144f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber *out = mBuffer; 16154f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer = NULL; 16164f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16174f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return OK; 16184f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 16194f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16204f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // Each NAL unit is split up into its constituent fragments and 16214f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // each one of them returned in its own buffer. 16224f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1623db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(mBuffer->range_length() >= mNALLengthSize); 16244f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16254f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber const uint8_t *src = 16264f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 16274f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1628db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t nal_size = parseNALSize(src); 1629909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber if (mBuffer->range_length() < mNALLengthSize + nal_size) { 1630909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber LOGE("incomplete NAL unit."); 1631909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 1632909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer->release(); 1633909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer = NULL; 1634909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 1635909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber return ERROR_MALFORMED; 1636909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber } 16374f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16384f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber MediaBuffer *clone = mBuffer->clone(); 1639ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(clone != NULL); 1640db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 16414f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1642ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(mBuffer != NULL); 16434f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->set_range( 1644db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mBuffer->range_offset() + mNALLengthSize + nal_size, 1645db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mBuffer->range_length() - mNALLengthSize - nal_size); 16464f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16474f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (mBuffer->range_length() == 0) { 16484f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->release(); 16494f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer = NULL; 16504f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 16514f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16524f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber *out = clone; 16534f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16544f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return OK; 16554f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } else { 16564f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // Whole NAL units are returned but each fragment is prefixed by 16574f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // the start code (0x00 00 00 01). 16584f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1659e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ssize_t num_bytes_read = 16609a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber mDataSource->readAt(offset, mSrcBuffer, size); 1661e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1662e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (num_bytes_read < (ssize_t)size) { 1663e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->release(); 1664e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1665e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 16664f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return ERROR_IO; 1667e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1668e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 16694f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber uint8_t *dstData = (uint8_t *)mBuffer->data(); 16704f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber size_t srcOffset = 0; 16714f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber size_t dstOffset = 0; 1672db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 16734f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber while (srcOffset < size) { 1674db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(srcOffset + mNALLengthSize <= size); 1675db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 1676db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber srcOffset += mNALLengthSize; 1677909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 1678909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber if (srcOffset + nalLength > size) { 1679909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer->release(); 1680909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer = NULL; 1681909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 1682909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber return ERROR_MALFORMED; 1683909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber } 16844f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16854f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (nalLength == 0) { 16864f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber continue; 16874f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 16884f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16894f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(dstOffset + 4 <= mBuffer->size()); 16904f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16914f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstData[dstOffset++] = 0; 16924f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstData[dstOffset++] = 0; 16934f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstData[dstOffset++] = 0; 16944f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstData[dstOffset++] = 1; 16954f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 16964f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber srcOffset += nalLength; 16974f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstOffset += nalLength; 16984f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 1699db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK_EQ(srcOffset, size); 17004f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1701ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(mBuffer != NULL); 17024f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->set_range(0, dstOffset); 1703e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->meta_data()->clear(); 1704fa8de752507feaca695123911915070c1ce463b2Andreas Huber mBuffer->meta_data()->setInt64( 1705fa8de752507feaca695123911915070c1ce463b2Andreas Huber kKeyTime, ((int64_t)dts * 1000000) / mTimescale); 17066624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 17076624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (targetSampleTimeUs >= 0) { 17086624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber mBuffer->meta_data()->setInt64( 17096624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber kKeyTargetTime, targetSampleTimeUs); 17106624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 17116624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 1712ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber if (isSyncSample) { 1713ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 1714ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber } 1715ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber 1716e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ++mCurrentSampleIndex; 1717e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1718e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out = mBuffer; 1719e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1720e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1721e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1722e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1723e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1725261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool LegacySniffMPEG4( 1726be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 1727e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t header[8]; 1728e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 17299a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber ssize_t n = source->readAt(4, header, sizeof(header)); 1730e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (n < (ssize_t)sizeof(header)) { 1731e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 1732e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1733e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1734e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8) 1735e1130662d0455231853e7d6880bb84d8547d7229James Dong || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8) 1736e1130662d0455231853e7d6880bb84d8547d7229James Dong || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8) 17376bce6d87b3fd98e68fb54328fb4dc8e40cd2c293Andreas Huber || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8) 1738dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8) 1739eea1eefeada90ec54488e1742e81e4226fc6ace5Andreas Huber || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) { 1740e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 1741e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *confidence = 0.1; 1742e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1743e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return true; 1744e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1745e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1746e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 1747e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1748e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1749261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) { 1750261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber static const uint32_t kCompatibleBrands[] = { 1751261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('i', 's', 'o', 'm'), 1752261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('i', 's', 'o', '2'), 1753261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('a', 'v', 'c', '1'), 1754261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('3', 'g', 'p', '4'), 1755261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('m', 'p', '4', '1'), 1756261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('m', 'p', '4', '2'), 1757261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber }; 1758261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1759261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber for (size_t i = 0; 1760261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]); 1761261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber ++i) { 1762261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (kCompatibleBrands[i] == fourcc) { 1763261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return true; 1764261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1765261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1766261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1767261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 1768261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber} 1769261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1770261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable 1771261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber// compatible brand is present. 1772261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool BetterSniffMPEG4( 1773261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 1774261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber uint8_t header[12]; 1775261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (source->readAt(0, header, 12) != 12 1776261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber || memcmp("ftyp", &header[4], 4)) { 1777261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 1778261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1779261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1780261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber size_t atomSize = U32_AT(&header[0]); 1781261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (atomSize < 16 || (atomSize % 4) != 0) { 1782261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 1783261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1784261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1785261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber bool success = false; 1786261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (isCompatibleBrand(U32_AT(&header[8]))) { 1787261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber success = true; 1788261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } else { 1789261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber size_t numCompatibleBrands = (atomSize - 16) / 4; 1790261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber for (size_t i = 0; i < numCompatibleBrands; ++i) { 1791261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber uint8_t tmp[4]; 1792261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (source->readAt(16 + i * 4, tmp, 4) != 4) { 1793261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 1794261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1795261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1796261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (isCompatibleBrand(U32_AT(&tmp[0]))) { 1797261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber success = true; 1798261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber break; 1799261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1800261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1801261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1802261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1803261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (!success) { 1804261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 1805261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1806261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1807261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 1808261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber *confidence = 0.3f; 1809261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1810261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return true; 1811261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber} 1812261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1813261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberbool SniffMPEG4( 1814261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 1815261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (BetterSniffMPEG4(source, mimeType, confidence)) { 1816261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return true; 1817261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1818261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1819261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (LegacySniffMPEG4(source, mimeType, confidence)) { 1820261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber LOGW("Identified supported mpeg4 through LegacySniffMPEG4."); 1821261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return true; 1822261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1823261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1824261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 1825261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber} 1826261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1827e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} // namespace android 1828e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1829