MPEG4Extractor.cpp revision d7d22eba3c1bb7212ccc566fedb16dbee44f51a2
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; 431e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 432e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 433e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber char chunk[5]; 434e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MakeFourCCString(chunk_type, chunk); 435e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 436e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#if 0 437e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber static const char kWhitespace[] = " "; 438e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth]; 439e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size); 440e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 441e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber char buffer[256]; 442e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_size <= sizeof(buffer)) { 443c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt(*offset, buffer, chunk_size) 444c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber < (ssize_t)chunk_size) { 445e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 446e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 447e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 448e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber hexdump(buffer, chunk_size); 449e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 450e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#endif 451e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 452c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder autoAdder(&mPath, chunk_type); 453c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 454e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t chunk_data_size = *offset + chunk_size - data_offset; 455e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 456c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (chunk_type != FOURCC('c', 'p', 'r', 't') 457c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && mPath.size() == 5 && underMetaDataPath(mPath)) { 458c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber off_t stop_offset = *offset + chunk_size; 459c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset = data_offset; 460c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber while (*offset < stop_offset) { 461c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber status_t err = parseChunk(offset, depth + 1); 462c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (err != OK) { 463c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return err; 464c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 465c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 4665ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 4675ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 4685ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 4695ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 470c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 471c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return OK; 472c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 473c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 474e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber switch(chunk_type) { 475e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'o', 'o', 'v'): 476e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('t', 'r', 'a', 'k'): 477e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'd', 'i', 'a'): 478e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'i', 'n', 'f'): 479e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('d', 'i', 'n', 'f'): 480e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 'b', 'l'): 481e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'v', 'e', 'x'): 482e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'o', 'o', 'f'): 483e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('t', 'r', 'a', 'f'): 484e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'f', 'r', 'a'): 485e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 'k', 'i' ,'p'): 486c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('u', 'd', 't', 'a'): 487c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('i', 'l', 's', 't'): 488e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 489affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (chunk_type == FOURCC('s', 't', 'b', 'l')) { 490affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size); 491affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 492affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (mDataSource->flags() & DataSource::kWantsPrefetching) { 493affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber sp<MPEG4DataSource> cachedSource = 494affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber new MPEG4DataSource(mDataSource); 495affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 496affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (cachedSource->setCachedRange(*offset, chunk_size) == OK) { 497affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mDataSource = cachedSource; 498affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 499affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 500affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 501affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 5025ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_type == FOURCC('t', 'r', 'a', 'k')) { 5035ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber Track *track = new Track; 5045ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->next = NULL; 5055ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (mLastTrack) { 5065ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber mLastTrack->next = track; 5075ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else { 5085ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber mFirstTrack = track; 5095ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 5105ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber mLastTrack = track; 5115ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 5125ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->meta = new MetaData; 5135ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->includes_expensive_metadata = false; 5145ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->timescale = 0; 5155ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->sampleTable = new SampleTable(mDataSource); 5165ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->meta->setCString(kKeyMIMEType, "application/octet-stream"); 5175ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 5185ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 519e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t stop_offset = *offset + chunk_size; 520e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset; 521e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (*offset < stop_offset) { 522e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 523e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 524e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 525e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 526e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 527e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 5285ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 5295ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 5305ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 5315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 5325ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_type == FOURCC('t', 'r', 'a', 'k')) { 5335ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber status_t err = verifyTrack(mLastTrack); 5345ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 5355ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (err != OK) { 5365ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return err; 5375ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 5385ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { 539e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mHaveMetadata = true; 540e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 541e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return UNKNOWN_ERROR; // Return a dummy error. 542e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 543e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 544e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 545e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 546e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('t', 'k', 'h', 'd'): 547e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 5485ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_data_size < 4) { 5495ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 5505ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 551e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 552e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t version; 5539a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt(data_offset, &version, 1) < 1) { 554e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 555e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 556e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 557e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint64_t ctime, mtime, duration; 558e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t id; 559e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t width, height; 560e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 561e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 1) { 562e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size != 36 + 60) { 563e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 564e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 565e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 566e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[36 + 60]; 5679a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 568e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 569e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 570e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 571e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 572e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ctime = U64_AT(&buffer[4]); 573e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mtime = U64_AT(&buffer[12]); 574e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber id = U32_AT(&buffer[20]); 575e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber duration = U64_AT(&buffer[28]); 576e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber width = U32_AT(&buffer[88]); 577e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber height = U32_AT(&buffer[92]); 578e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else if (version == 0) { 579e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size != 24 + 60) { 580e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 581e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 582e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 583e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[24 + 60]; 5849a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 585e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 586e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 587e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 588e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ctime = U32_AT(&buffer[4]); 589e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mtime = U32_AT(&buffer[8]); 590e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber id = U32_AT(&buffer[12]); 591e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber duration = U32_AT(&buffer[20]); 592e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber width = U32_AT(&buffer[76]); 593e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber height = U32_AT(&buffer[80]); 594e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 595e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 596e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 597e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 598e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 599e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 600e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'd', 'h', 'd'): 601e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 602e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 4) { 603e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 604e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 605e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 606e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t version; 6079a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 608e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, &version, sizeof(version)) 609e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(version)) { 610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 611e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t timescale_offset; 614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 615e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 1) { 616e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset = data_offset + 4 + 16; 617e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else if (version == 0) { 618e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset = data_offset + 4 + 8; 619e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 620e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 621e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 622e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 623e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t timescale; 6249a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 625e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset, ×cale, sizeof(timescale)) 626e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(timescale)) { 627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 628e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 629e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 630e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->timescale = ntohl(timescale); 631e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 632e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int64_t duration; 633e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 1) { 6349a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset + 4, &duration, sizeof(duration)) 636e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(duration)) { 637e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 638e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 639e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber duration = ntoh64(duration); 640e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 641e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t duration32; 6429a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 643e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset + 4, &duration32, sizeof(duration32)) 644e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(duration32)) { 645e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 646e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 647e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber duration = ntohl(duration32); 648e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 649fa8de752507feaca695123911915070c1ce463b2Andreas Huber mLastTrack->meta->setInt64( 650fa8de752507feaca695123911915070c1ce463b2Andreas Huber kKeyDuration, (duration * 1000000) / mLastTrack->timescale); 651e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 652e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 653e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 654e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 655e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 656e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('h', 'd', 'l', 'r'): 657e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 658e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 25) { 659e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 660e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 661e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 662e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[24]; 6639a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt(data_offset, buffer, 24) < 24) { 664e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 665e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 666e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 667e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (U32_AT(buffer) != 0) { 668e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Should be version 0, flags 0. 669e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 670e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 671e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 672e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (U32_AT(&buffer[4]) != 0) { 673e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // pre_defined should be 0. 674e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 675e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 676e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 677e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mHandlerType = U32_AT(&buffer[8]); 678e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 679e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 680e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 681e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 682e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 'd'): 683e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 684e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 8) { 685e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 686e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 687e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 688e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[8]; 6895ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_data_size < (off_t)sizeof(buffer)) { 6905ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 6915ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 6925ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 6939a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 694e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, 8) < 8) { 695e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 696e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 697e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 698e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (U32_AT(buffer) != 0) { 699e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Should be version 0, flags 0. 700e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 701e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 702e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 703e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t entry_count = U32_AT(&buffer[4]); 704e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 705e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (entry_count > 1) { 706e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // For now we only support a single type of media per track. 707e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_UNSUPPORTED; 708e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 709e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 710e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t stop_offset = *offset + chunk_size; 711e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset + 8; 712e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber for (uint32_t i = 0; i < entry_count; ++i) { 713e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 714e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 715e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 716e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 717e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 7185ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 7195ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 7205ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 7215ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 722e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 723e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 725e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'a'): 726e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 7272a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber case FOURCC('s', 'a', 'w', 'b'): 728e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 729e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mHandlerType != FOURCC('s', 'o', 'u', 'n')) { 730e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 731e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 732e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 733e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[8 + 20]; 734e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 735e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Basic AudioSampleEntry size. 736e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 737e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 738e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 7399a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 740e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 741e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 742e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 743e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 744e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 745e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t num_channels = U16_AT(&buffer[16]); 746e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 747e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, 748e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber FourCC2MIME(chunk_type)) 749e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber || !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, 750e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber FourCC2MIME(chunk_type))) { 751e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // AMR audio is always mono. 752e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber num_channels = 1; 753e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 754e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 755e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t sample_size = U16_AT(&buffer[18]); 756e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t sample_rate = U32_AT(&buffer[24]) >> 16; 757e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 7582ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber // printf("*** coding='%s' %d channels, size %d, rate %d\n", 7592ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber // chunk, num_channels, sample_size, sample_rate); 760e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 761e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 762e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 763e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 764e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 765e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t stop_offset = *offset + chunk_size; 766e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset + sizeof(buffer); 767e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (*offset < stop_offset) { 768e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 769e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 770e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 771e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 772e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 7735ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 7745ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 7755ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 7765ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 777e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 778e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 779e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 780e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'v'): 781e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', '2', '6', '3'): 782e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('a', 'v', 'c', '1'): 783e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 7841cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber mHasVideo = true; 7851cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 786e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mHandlerType != FOURCC('v', 'i', 'd', 'e')) { 787e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 788e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 789e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 790e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[78]; 791e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 792e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Basic VideoSampleEntry size. 793e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 794e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 795e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 7969a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 797e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 798e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 799e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 800e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 801e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 802e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t width = U16_AT(&buffer[6 + 18]); 803e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t height = U16_AT(&buffer[6 + 20]); 804e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 8052ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber // printf("*** coding='%s' width=%d height=%d\n", 8062ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber // chunk, width, height); 807e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 808e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 809e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeyWidth, width); 810e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeyHeight, height); 811e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 812e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t stop_offset = *offset + chunk_size; 813e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset + sizeof(buffer); 814e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (*offset < stop_offset) { 815e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 816e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 817e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 818e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 819e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 8205ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 8215ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 8225ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 8235ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 824e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 825e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 826e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 827e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 'c', 'o'): 828e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('c', 'o', '6', '4'): 829e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 830e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 831e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setChunkOffsetParams( 832e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber chunk_type, data_offset, chunk_data_size); 833e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 834e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 835e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 836e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 837e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 838e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 839e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 840e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 841e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 842e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 'c'): 843e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 844e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 845e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setSampleToChunkParams( 846e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, chunk_data_size); 847e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 848e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 849e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 850e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 851e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 852e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 853e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 854e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 855e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 856e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 'z'): 857e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 'z', '2'): 858e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 859e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 860e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setSampleSizeParams( 861e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber chunk_type, data_offset, chunk_data_size); 862e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 863e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 864e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 865e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 866e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 8671bceff916a72246fa208605d50615823d7f1688bAndreas Huber size_t max_size; 8681bceff916a72246fa208605d50615823d7f1688bAndreas Huber CHECK_EQ(mLastTrack->sampleTable->getMaxSampleSize(&max_size), OK); 8691bceff916a72246fa208605d50615823d7f1688bAndreas Huber 8701bceff916a72246fa208605d50615823d7f1688bAndreas Huber // Assume that a given buffer only contains at most 10 fragments, 8711bceff916a72246fa208605d50615823d7f1688bAndreas Huber // each fragment originally prefixed with a 2 byte length will 8721bceff916a72246fa208605d50615823d7f1688bAndreas Huber // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion, 8731bceff916a72246fa208605d50615823d7f1688bAndreas Huber // and thus will grow by 2 bytes per fragment. 8741bceff916a72246fa208605d50615823d7f1688bAndreas Huber mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2); 8751bceff916a72246fa208605d50615823d7f1688bAndreas Huber 876e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 877e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 878e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 879e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 880e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 't', 's'): 881e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 882e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 883e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setTimeToSampleParams( 884e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, chunk_data_size); 885e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 886e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 887e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 888e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 889e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 890e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 891e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 892e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 893e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 894e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 's'): 895e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 896e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 897e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setSyncSampleParams( 898e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, chunk_data_size); 899e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 900e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 901e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 902e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 903e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 904e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 905e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 906e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 907e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 908e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('e', 's', 'd', 's'): 909e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 910e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 4) { 911e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 912e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 913e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 914e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[256]; 915e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size > (off_t)sizeof(buffer)) { 916e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_BUFFER_TOO_SMALL; 917e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 918e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 9199a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 920e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 921e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 922e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 923e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 924e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (U32_AT(buffer) != 0) { 925e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Should be version 0, flags 0. 926e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 927e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 928e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 929e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setData( 930e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); 931e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 932d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (mPath.size() >= 2 933d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) { 934d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // Information from the ESDS must be relied on for proper 935d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // setup of sample rate and channel count for MPEG4 Audio. 936d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // The generic header appears to only contain generic 937d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // information... 938d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 939d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio( 940d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber &buffer[4], chunk_data_size - 4); 941d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 942d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (err != OK) { 943d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return err; 944d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 945d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 946d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 947e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 948e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 949e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 950e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 951e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('a', 'v', 'c', 'C'): 952e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 953e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber char buffer[256]; 954e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size > (off_t)sizeof(buffer)) { 955e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_BUFFER_TOO_SMALL; 956e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 957e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 9589a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 959e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 960e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 961e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 962e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 963e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setData( 964e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber kKeyAVCC, kTypeAVCC, buffer, chunk_data_size); 965e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 966e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 967e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 968e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 969e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 970c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('m', 'e', 't', 'a'): 971c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 972c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint8_t buffer[4]; 9735ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_data_size < (off_t)sizeof(buffer)) { 9745ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 9755ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 9765ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 977c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt( 978c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber data_offset, buffer, 4) < 4) { 979c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_IO; 980c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 981c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 982c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (U32_AT(buffer) != 0) { 983c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber // Should be version 0, flags 0. 984c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_MALFORMED; 985c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 986c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 987c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber off_t stop_offset = *offset + chunk_size; 988c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset = data_offset + sizeof(buffer); 989c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber while (*offset < stop_offset) { 990c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber status_t err = parseChunk(offset, depth + 1); 991c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (err != OK) { 992c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return err; 993c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 994c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 9955ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 9965ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 9975ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 9985ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 999c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1000c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1001c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1002c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('d', 'a', 't', 'a'): 1003c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1004c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mPath.size() == 6 && underMetaDataPath(mPath)) { 1005c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber status_t err = parseMetaData(data_offset, chunk_data_size); 1006c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1007c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (err != OK) { 1008c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return err; 1009c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1010c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1011c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1012c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset += chunk_size; 1013c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1014c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1015c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1016c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('m', 'v', 'h', 'd'): 1017c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1018c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (chunk_data_size < 12) { 1019c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_MALFORMED; 1020c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1021c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1022c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint8_t header[12]; 1023c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt( 1024c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber data_offset, header, sizeof(header)) 1025c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber < (ssize_t)sizeof(header)) { 1026c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_IO; 1027c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1028c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1029c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber int64_t creationTime; 1030c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (header[0] == 1) { 1031c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber creationTime = U64_AT(&header[4]); 10325ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else if (header[0] != 0) { 10335ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 1034c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else { 1035c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber creationTime = U32_AT(&header[4]); 1036c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1037c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1038c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber String8 s; 1039c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber convertTimeToDate(creationTime, &s); 1040c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1041c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyDate, s.string()); 1042c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1043c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset += chunk_size; 1044c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1045c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1046c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1047e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber default: 1048e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 1049e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 1050e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 1051e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1052e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1053e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1054e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1055e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1056e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1057c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatus_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) { 1058c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (size < 4) { 1059c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_MALFORMED; 1060c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1061c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1062c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint8_t *buffer = new uint8_t[size + 1]; 1063c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt( 1064c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber offset, buffer, size) != (ssize_t)size) { 1065c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber delete[] buffer; 1066c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer = NULL; 1067c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1068c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_IO; 1069c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1070c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1071c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint32_t flags = U32_AT(buffer); 1072c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1073c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint32_t metadataKey = 0; 1074c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber switch (mPath[4]) { 1075c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'a', 'l', 'b'): 1076c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1077c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyAlbum; 1078c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1079c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1080c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'A', 'R', 'T'): 1081c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1082c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyArtist; 1083c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1084c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1085c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen case FOURCC('a', 'A', 'R', 'T'): 1086c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen { 1087c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen metadataKey = kKeyAlbumArtist; 1088c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen break; 1089c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen } 1090c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'd', 'a', 'y'): 1091c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1092c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyYear; 1093c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1094c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1095c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'n', 'a', 'm'): 1096c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1097c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyTitle; 1098c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1099c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1100c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'w', 'r', 't'): 1101c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1102c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyWriter; 1103c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1104c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1105c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('c', 'o', 'v', 'r'): 1106c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1107c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyAlbumArt; 1108c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1109c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1110c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('g', 'n', 'r', 'e'): 1111c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1112c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyGenre; 1113c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1114c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1115fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen case FOURCC(0xa9, 'g', 'e', 'n'): 1116fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen { 1117fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen metadataKey = kKeyGenre; 1118fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen break; 1119fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1120c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('t', 'r', 'k', 'n'): 1121c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1122c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (size == 16 && flags == 0) { 1123c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber char tmp[16]; 1124c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber sprintf(tmp, "%d/%d", 1125c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber (int)buffer[size - 5], (int)buffer[size - 3]); 1126c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1127c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyCDTrackNumber, tmp); 1128c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1129c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1130c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1131fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen case FOURCC('d', 'i', 's', 'k'): 1132fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen { 1133fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen if (size == 14 && flags == 0) { 1134fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen char tmp[16]; 1135fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen sprintf(tmp, "%d/%d", 1136fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen (int)buffer[size - 3], (int)buffer[size - 1]); 1137fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen 1138fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen mFileMetaData->setCString(kKeyDiscNumber, tmp); 1139fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1140fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen break; 1141fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1142fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen 1143c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber default: 1144c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1145c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1146c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1147c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (size >= 8 && metadataKey) { 1148c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (metadataKey == kKeyAlbumArt) { 1149c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setData( 1150c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber kKeyAlbumArt, MetaData::TYPE_NONE, 1151c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer + 8, size - 8); 1152c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else if (metadataKey == kKeyGenre) { 1153c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (flags == 0) { 1154fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // uint8_t genre code, iTunes genre codes are 1155fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // the standard id3 codes, except they start 1156fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // at 1 instead of 0 (e.g. Pop is 14, not 13) 1157fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // We use standard id3 numbering, so subtract 1. 1158fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen int genrecode = (int)buffer[size - 1]; 1159fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen genrecode--; 1160fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen if (genrecode < 0) { 1161fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen genrecode = 255; // reserved for 'unknown genre' 1162fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1163c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber char genre[10]; 1164fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen sprintf(genre, "%d", genrecode); 1165c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1166c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(metadataKey, genre); 1167fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } else if (flags == 1) { 1168fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // custom genre string 1169fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen buffer[size] = '\0'; 1170fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen 1171fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen mFileMetaData->setCString( 1172fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen metadataKey, (const char *)buffer + 8); 1173c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1174c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else { 1175c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer[size] = '\0'; 1176c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1177c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString( 1178c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey, (const char *)buffer + 8); 1179c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1180c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1181c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1182c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber delete[] buffer; 1183c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer = NULL; 1184c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1185c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return OK; 1186c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber} 1187c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1188be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) { 1189e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 1190e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if ((err = readMetaData()) != OK) { 1191be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return NULL; 1192e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1193e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1194e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 1195e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (index > 0) { 1196e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (track == NULL) { 1197be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return NULL; 1198e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1199e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1200e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = track->next; 1201e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber --index; 1202e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1203e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 12042a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber if (track == NULL) { 12052a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber return NULL; 12062a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber } 12072a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber 1208be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return new MPEG4Source( 1209fa8de752507feaca695123911915070c1ce463b2Andreas Huber track->meta, mDataSource, track->timescale, track->sampleTable); 1210e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1211e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 12125ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber// static 12135ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) { 12145ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber const char *mime; 12155ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 12165ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 12175ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber uint32_t type; 12185ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber const void *data; 12195ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber size_t size; 12205ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 12215ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (!track->meta->findData(kKeyAVCC, &type, &data, &size) 12225ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber || type != kTypeAVCC) { 12235ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 12245ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 12255ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 12265ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 12275ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (!track->meta->findData(kKeyESDS, &type, &data, &size) 12285ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber || type != kTypeESDS) { 12295ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 12305ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 12315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 12325ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 12335ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return OK; 12345ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber} 12355ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 1236d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( 1237d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber const void *esds_data, size_t esds_size) { 1238d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber ESDS esds(esds_data, esds_size); 1239d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber const uint8_t *csd; 1240d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber size_t csd_size; 1241d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (esds.getCodecSpecificInfo( 1242d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber (const void **)&csd, &csd_size) != OK) { 1243d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1244d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1245d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1246d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#if 0 1247d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber printf("ESD of size %d\n", csd_size); 1248d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber hexdump(csd, csd_size); 1249d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#endif 1250d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1251d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (csd_size < 2) { 1252d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1253d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1254d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1255d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber uint32_t objectType = csd[0] >> 3; 1256d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1257d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (objectType == 31) { 1258d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_UNSUPPORTED; 1259d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1260d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1261d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7); 1262d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t sampleRate = 0; 1263d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t numChannels = 0; 1264d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (freqIndex == 15) { 1265d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (csd_size < 5) { 1266d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1267d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1268d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1269d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber sampleRate = (csd[1] & 0x7f) << 17 1270d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber | csd[2] << 9 1271d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber | csd[3] << 1 1272d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber | (csd[4] >> 7); 1273d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1274d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber numChannels = (csd[4] >> 3) & 15; 1275d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } else { 1276d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber static uint32_t kSamplingRate[] = { 1277d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 1278d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 16000, 12000, 11025, 8000, 7350 1279d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber }; 1280d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1281d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (freqIndex == 13 || freqIndex == 14) { 1282d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1283d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1284d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1285d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber sampleRate = kSamplingRate[freqIndex]; 1286d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber numChannels = (csd[1] >> 3) & 15; 1287d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1288d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1289d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (numChannels == 0) { 1290d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_UNSUPPORTED; 1291d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1292d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1293d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t prevSampleRate; 1294d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate)); 1295d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1296d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (prevSampleRate != sampleRate) { 12974a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber LOGV("mpeg4 audio sample rate different from previous setting. " 1298d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber "was: %d, now: %d", prevSampleRate, sampleRate); 1299d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1300d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1301d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sampleRate); 1302d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1303d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t prevChannelCount; 1304d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount)); 1305d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1306d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (prevChannelCount != numChannels) { 13074a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber LOGV("mpeg4 audio channel count different from previous setting. " 1308d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber "was: %d, now: %d", prevChannelCount, numChannels); 1309d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1310d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1311d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, numChannels); 1312d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1313d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return OK; 1314d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber} 1315d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1316e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber//////////////////////////////////////////////////////////////////////////////// 1317e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1318e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::MPEG4Source( 1319e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const sp<MetaData> &format, 1320be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<DataSource> &dataSource, 1321fa8de752507feaca695123911915070c1ce463b2Andreas Huber int32_t timeScale, 1322be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<SampleTable> &sampleTable) 1323e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber : mFormat(format), 1324e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mDataSource(dataSource), 1325fa8de752507feaca695123911915070c1ce463b2Andreas Huber mTimescale(timeScale), 1326e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mSampleTable(sampleTable), 1327e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentSampleIndex(0), 1328e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mIsAVC(false), 1329db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mNALLengthSize(0), 1330e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted(false), 1331e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup(NULL), 1332e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer(NULL), 13334f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mWantsNALFragments(false), 13348a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber mSrcBuffer(NULL) { 1335e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const char *mime; 1336e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bool success = mFormat->findCString(kKeyMIMEType, &mime); 13374f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(success); 1338e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1339e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 1340db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1341db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber if (mIsAVC) { 1342db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber uint32_t type; 1343db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber const void *data; 1344db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t size; 1345db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(format->findData(kKeyAVCC, &type, &data, &size)); 1346db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1347db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber const uint8_t *ptr = (const uint8_t *)data; 1348db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1349db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(size >= 7); 1350db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK_EQ(ptr[0], 1); // configurationVersion == 1 1351db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1352db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber // The number of bytes used to encode the length of a NAL unit. 1353db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mNALLengthSize = 1 + (ptr[4] & 3); 1354db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber } 1355e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1356e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1357e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::~MPEG4Source() { 1358e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mStarted) { 1359e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber stop(); 1360e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1361e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1362e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1363e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::start(MetaData *params) { 1364ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1365ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 13664f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(!mStarted); 1367e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1368e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t val; 13694f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (params && params->findInt32(kKeyWantsNALFragments, &val) 1370e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber && val != 0) { 13714f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mWantsNALFragments = true; 1372e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 13734f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mWantsNALFragments = false; 1374e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1375e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1376e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup = new MediaBufferGroup; 1377e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 13781bceff916a72246fa208605d50615823d7f1688bAndreas Huber int32_t max_size; 13791bceff916a72246fa208605d50615823d7f1688bAndreas Huber CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size)); 1380e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 13811bceff916a72246fa208605d50615823d7f1688bAndreas Huber mGroup->add_buffer(new MediaBuffer(max_size)); 13828a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber 13838a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber mSrcBuffer = new uint8_t[max_size]; 1384e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1385e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted = true; 1386e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1387e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1388e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1389e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1390e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::stop() { 1391ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1392ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 13934f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(mStarted); 1394e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1395e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mBuffer != NULL) { 1396e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->release(); 1397e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1398e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1399e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 14008a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber delete[] mSrcBuffer; 14018a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber mSrcBuffer = NULL; 14028a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber 1403e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber delete mGroup; 1404e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup = NULL; 1405e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1406e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted = false; 1407e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentSampleIndex = 0; 1408e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1409e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1410e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1411e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1412e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> MPEG4Source::getFormat() { 1413ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1414ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 1415e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return mFormat; 1416e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1417e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1418db5d662254f2ed788d32e2466739adc8d655c732Andreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const { 1419db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber switch (mNALLengthSize) { 1420db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 1: 1421db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return *data; 1422db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 2: 1423db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return U16_AT(data); 1424db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 3: 1425db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return ((size_t)data[0] << 16) | U16_AT(&data[1]); 1426db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 4: 1427db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return U32_AT(data); 1428db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber } 1429db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1430db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber // This cannot happen, mNALLengthSize springs to life by adding 1 to 1431db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber // a 2-bit integer. 1432db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(!"Should not be here."); 1433db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1434db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return 0; 1435db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber} 1436db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1437e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::read( 1438e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer **out, const ReadOptions *options) { 1439ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1440ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 14414f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(mStarted); 1442e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1443e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out = NULL; 1444e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1445e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int64_t seekTimeUs; 1446e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (options && options->getSeekTo(&seekTimeUs)) { 1447e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t sampleIndex; 1448e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = mSampleTable->findClosestSample( 1449e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber seekTimeUs * mTimescale / 1000000, 1450e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber &sampleIndex, SampleTable::kSyncSample_Flag); 1451e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1452e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 1453d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber if (err == ERROR_OUT_OF_RANGE) { 1454d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // An attempt to seek past the end of the stream would 1455d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // normally cause this ERROR_OUT_OF_RANGE error. Propagating 1456d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // this all the way to the MediaPlayer would cause abnormal 1457d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // termination. Legacy behaviour appears to be to behave as if 1458d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // we had seeked to the end of stream, ending normally. 1459d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber err = ERROR_END_OF_STREAM; 1460d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber } 1461e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 1462e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1463e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1464e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentSampleIndex = sampleIndex; 1465e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mBuffer != NULL) { 1466e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->release(); 1467e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1468e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1469e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1470e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // fall through 1471e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1472e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 14738a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber off_t offset; 14748a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber size_t size; 14754f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber uint32_t dts; 14764f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber bool newBuffer = false; 14774f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (mBuffer == NULL) { 14784f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber newBuffer = true; 1479e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 14801faa92a1e93f311e86dca483ed7702091137de66Andreas Huber status_t err = 14811faa92a1e93f311e86dca483ed7702091137de66Andreas Huber mSampleTable->getMetaDataForSample( 14821faa92a1e93f311e86dca483ed7702091137de66Andreas Huber mCurrentSampleIndex, &offset, &size, &dts); 1483e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 14844f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (err != OK) { 14854f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return err; 14864f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 14874f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 14884f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber err = mGroup->acquire_buffer(&mBuffer); 14891faa92a1e93f311e86dca483ed7702091137de66Andreas Huber 14904f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (err != OK) { 14914f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK_EQ(mBuffer, NULL); 14924f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return err; 14934f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 14948a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber } 1495e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 14964f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (!mIsAVC || mWantsNALFragments) { 14974f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (newBuffer) { 14984f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber ssize_t num_bytes_read = 14999a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 15004f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15014f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (num_bytes_read < (ssize_t)size) { 15024f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->release(); 15034f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer = NULL; 15044f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15054f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return ERROR_IO; 15064f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 15074f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1508ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(mBuffer != NULL); 15094f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->set_range(0, size); 15104f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->meta_data()->clear(); 1511fa8de752507feaca695123911915070c1ce463b2Andreas Huber mBuffer->meta_data()->setInt64( 1512fa8de752507feaca695123911915070c1ce463b2Andreas Huber kKeyTime, ((int64_t)dts * 1000000) / mTimescale); 15134f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber ++mCurrentSampleIndex; 15144f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 15154f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15164f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (!mIsAVC) { 15174f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber *out = mBuffer; 15184f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer = NULL; 15194f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15204f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return OK; 15214f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 15224f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15234f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // Each NAL unit is split up into its constituent fragments and 15244f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // each one of them returned in its own buffer. 15254f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1526db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(mBuffer->range_length() >= mNALLengthSize); 15274f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15284f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber const uint8_t *src = 15294f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 15304f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1531db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t nal_size = parseNALSize(src); 1532909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber if (mBuffer->range_length() < mNALLengthSize + nal_size) { 1533909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber LOGE("incomplete NAL unit."); 1534909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 1535909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer->release(); 1536909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer = NULL; 1537909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 1538909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber return ERROR_MALFORMED; 1539909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber } 15404f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15414f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber MediaBuffer *clone = mBuffer->clone(); 1542ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(clone != NULL); 1543db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 15444f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1545ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(mBuffer != NULL); 15464f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->set_range( 1547db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mBuffer->range_offset() + mNALLengthSize + nal_size, 1548db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mBuffer->range_length() - mNALLengthSize - nal_size); 15494f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15504f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (mBuffer->range_length() == 0) { 15514f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->release(); 15524f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer = NULL; 15534f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 15544f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15554f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber *out = clone; 15564f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15574f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return OK; 15584f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } else { 15594f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // Whole NAL units are returned but each fragment is prefixed by 15604f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // the start code (0x00 00 00 01). 15614f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1562e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ssize_t num_bytes_read = 15639a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber mDataSource->readAt(offset, mSrcBuffer, size); 1564e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1565e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (num_bytes_read < (ssize_t)size) { 1566e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->release(); 1567e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1568e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 15694f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return ERROR_IO; 1570e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1571e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 15724f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber uint8_t *dstData = (uint8_t *)mBuffer->data(); 15734f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber size_t srcOffset = 0; 15744f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber size_t dstOffset = 0; 1575db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 15764f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber while (srcOffset < size) { 1577db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(srcOffset + mNALLengthSize <= size); 1578db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 1579db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber srcOffset += mNALLengthSize; 1580909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 1581909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber if (srcOffset + nalLength > size) { 1582909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer->release(); 1583909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer = NULL; 1584909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 1585909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber return ERROR_MALFORMED; 1586909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber } 15874f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15884f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (nalLength == 0) { 15894f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber continue; 15904f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 15914f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15924f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(dstOffset + 4 <= mBuffer->size()); 15934f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 15944f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstData[dstOffset++] = 0; 15954f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstData[dstOffset++] = 0; 15964f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstData[dstOffset++] = 0; 15974f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstData[dstOffset++] = 1; 15984f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 15994f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber srcOffset += nalLength; 16004f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstOffset += nalLength; 16014f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 1602db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK_EQ(srcOffset, size); 16034f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1604ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(mBuffer != NULL); 16054f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->set_range(0, dstOffset); 1606e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->meta_data()->clear(); 1607fa8de752507feaca695123911915070c1ce463b2Andreas Huber mBuffer->meta_data()->setInt64( 1608fa8de752507feaca695123911915070c1ce463b2Andreas Huber kKeyTime, ((int64_t)dts * 1000000) / mTimescale); 1609e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ++mCurrentSampleIndex; 1610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1611e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out = mBuffer; 1612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1615e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1616e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1617e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1618be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberbool SniffMPEG4( 1619be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 1620e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t header[8]; 1621e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 16229a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber ssize_t n = source->readAt(4, header, sizeof(header)); 1623e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (n < (ssize_t)sizeof(header)) { 1624e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 1625e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1626e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8) 16286bce6d87b3fd98e68fb54328fb4dc8e40cd2c293Andreas Huber || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8) 162901830a0814ae2db9141f49720d9e5aa2457854f0Andreas Huber || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)) { 1630e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 1631e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *confidence = 0.1; 1632e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1633e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return true; 1634e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1636e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 1637e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1638e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1639e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} // namespace android 1640e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1641