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 3031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber#include <media/stagefright/foundation/ADebug.h> 31e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/DataSource.h> 32d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#include "include/ESDS.h" 33e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBuffer.h> 34e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaBufferGroup.h> 35e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber#include <media/stagefright/MediaDefs.h> 36e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MediaSource.h> 37e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/MetaData.h> 38e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <media/stagefright/Utils.h> 39e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#include <utils/String8.h> 40e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 41e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubernamespace android { 42e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 43e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberclass MPEG4Source : public MediaSource { 44e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberpublic: 45e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Caller retains ownership of both "dataSource" and "sampleTable". 46be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber MPEG4Source(const sp<MetaData> &format, 47be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<DataSource> &dataSource, 48fa8de752507feaca695123911915070c1ce463b2Andreas Huber int32_t timeScale, 49be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<SampleTable> &sampleTable); 50e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 51e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual status_t start(MetaData *params = NULL); 52e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual status_t stop(); 53e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 54e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual sp<MetaData> getFormat(); 55e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 56e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber virtual status_t read( 57e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 58e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 59be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huberprotected: 60be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber virtual ~MPEG4Source(); 61be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber 62e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberprivate: 63ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex mLock; 64ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 65e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber sp<MetaData> mFormat; 66be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber sp<DataSource> mDataSource; 67e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t mTimescale; 68be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber sp<SampleTable> mSampleTable; 69e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t mCurrentSampleIndex; 70e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 71e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bool mIsAVC; 72db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t mNALLengthSize; 73db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 74e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bool mStarted; 75e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 76e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBufferGroup *mGroup; 77e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 78e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer *mBuffer; 79e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 804f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber bool mWantsNALFragments; 81e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 828a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber uint8_t *mSrcBuffer; 838a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber 84db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t parseNALSize(const uint8_t *data) const; 85db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 86e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MPEG4Source(const MPEG4Source &); 87e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MPEG4Source &operator=(const MPEG4Source &); 88e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber}; 89e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 90affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// This custom data source wraps an existing one and satisfies requests 91affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// falling entirely within a cached range from the cache while forwarding 92affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// all remaining requests to the wrapped datasource. 93affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// This is used to cache the full sampletable metadata for a single track, 94affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// possibly wrapping multiple times to cover all tracks, i.e. 95affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber// Each MPEG4DataSource caches the sampletable metadata for a single track. 96affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 97affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstruct MPEG4DataSource : public DataSource { 98affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber MPEG4DataSource(const sp<DataSource> &source); 99affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 100affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual status_t initCheck() const; 101affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual ssize_t readAt(off_t offset, void *data, size_t size); 102affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual status_t getSize(off_t *size); 103affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual uint32_t flags(); 104affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 105affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber status_t setCachedRange(off_t offset, size_t size); 106affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 107affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberprotected: 108affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber virtual ~MPEG4DataSource(); 109affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 110affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberprivate: 111affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber Mutex mLock; 112affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 113affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber sp<DataSource> mSource; 114affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber off_t mCachedOffset; 115affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber size_t mCachedSize; 116affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber uint8_t *mCache; 117affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 118affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber void clearCache(); 119affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 120affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber MPEG4DataSource(const MPEG4DataSource &); 121affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber MPEG4DataSource &operator=(const MPEG4DataSource &); 122affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber}; 123affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 124affa99c52957685f5a5652ab5254b92e729651c7Andreas HuberMPEG4DataSource::MPEG4DataSource(const sp<DataSource> &source) 125affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber : mSource(source), 126affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedOffset(0), 127affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedSize(0), 128affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCache(NULL) { 129affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 130affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 131affa99c52957685f5a5652ab5254b92e729651c7Andreas HuberMPEG4DataSource::~MPEG4DataSource() { 132affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber clearCache(); 133affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 134affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 135affa99c52957685f5a5652ab5254b92e729651c7Andreas Hubervoid MPEG4DataSource::clearCache() { 136affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (mCache) { 137affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber free(mCache); 138affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCache = NULL; 139affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 140affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 141affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedOffset = 0; 142affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedSize = 0; 143affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 144affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 145affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstatus_t MPEG4DataSource::initCheck() const { 146affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return mSource->initCheck(); 147affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 148affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 149affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberssize_t MPEG4DataSource::readAt(off_t offset, void *data, size_t size) { 150affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber Mutex::Autolock autoLock(mLock); 151affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 152affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (offset >= mCachedOffset 153affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber && offset + size <= mCachedOffset + mCachedSize) { 154affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber memcpy(data, &mCache[offset - mCachedOffset], size); 155affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return size; 156affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 157affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 158affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return mSource->readAt(offset, data, size); 159affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 160affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 161affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstatus_t MPEG4DataSource::getSize(off_t *size) { 162affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return mSource->getSize(size); 163affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 164affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 165affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberuint32_t MPEG4DataSource::flags() { 166affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return mSource->flags(); 167affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 168affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 169affa99c52957685f5a5652ab5254b92e729651c7Andreas Huberstatus_t MPEG4DataSource::setCachedRange(off_t offset, size_t size) { 170affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber Mutex::Autolock autoLock(mLock); 171affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 172affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber clearCache(); 173affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 174affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCache = (uint8_t *)malloc(size); 175affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 176affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (mCache == NULL) { 177affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return -ENOMEM; 178affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 179affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 180affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedOffset = offset; 181affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mCachedSize = size; 182affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 183affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber ssize_t err = mSource->readAt(mCachedOffset, mCache, mCachedSize); 184affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 185affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (err < (ssize_t)size) { 186affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber clearCache(); 187affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 188affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return ERROR_IO; 189affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 190affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 191affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber return OK; 192affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber} 193affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 194affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber//////////////////////////////////////////////////////////////////////////////// 195affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 196e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic void hexdump(const void *_data, size_t size) { 197e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const uint8_t *data = (const uint8_t *)_data; 198e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber size_t offset = 0; 199e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (offset < size) { 200e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("0x%04x ", offset); 201e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 202e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber size_t n = size - offset; 203e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (n > 16) { 204e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber n = 16; 205e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 206e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 207e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber for (size_t i = 0; i < 16; ++i) { 208e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (i == 8) { 209e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf(" "); 210e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 211e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 212e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (offset + i < size) { 213e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("%02x ", data[offset + i]); 214e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 215e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf(" "); 216e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 217e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 218e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 219e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf(" "); 220e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 221e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber for (size_t i = 0; i < n; ++i) { 222e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (isprint(data[offset + i])) { 223e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("%c", data[offset + i]); 224e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 225e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("."); 226e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 227e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 228e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 229e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("\n"); 230e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 231e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber offset += 16; 232e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 233e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 234e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 235e6c409632f773e41f33188272a0072be9fcb783fAndreas Huberstatic const char *FourCC2MIME(uint32_t fourcc) { 236e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber switch (fourcc) { 237e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'a'): 238e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_AUDIO_AAC; 239e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 240e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 241e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_AUDIO_AMR_NB; 242e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2432a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber case FOURCC('s', 'a', 'w', 'b'): 244e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_AUDIO_AMR_WB; 2452a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber 246e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'v'): 247e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_VIDEO_MPEG4; 248e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 249e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', '2', '6', '3'): 250e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_VIDEO_H263; 251e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 252e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('a', 'v', 'c', '1'): 253e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber return MEDIA_MIMETYPE_VIDEO_AVC; 254e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 255e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber default: 2564f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(!"should not be here."); 257e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return NULL; 258e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 259e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 260e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 261be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas HuberMPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source) 262e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber : mDataSource(source), 263e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mHaveMetadata(false), 2641cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber mHasVideo(false), 265e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mFirstTrack(NULL), 266c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mLastTrack(NULL), 267c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData(new MetaData) { 268e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 269e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 270e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Extractor::~MPEG4Extractor() { 271e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 272e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (track) { 273e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *next = track->next; 274e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 275e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber delete track; 276e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = next; 277e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 278e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mFirstTrack = mLastTrack = NULL; 279e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 280e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 2811cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Hubersp<MetaData> MPEG4Extractor::getMetaData() { 2821cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber status_t err; 2831cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber if ((err = readMetaData()) != OK) { 284c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return new MetaData; 2851cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber } 2861cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 287c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return mFileMetaData; 2881cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber} 2891cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 290be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersize_t MPEG4Extractor::countTracks() { 291e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 292e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if ((err = readMetaData()) != OK) { 293be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return 0; 294e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 295e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 296be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber size_t n = 0; 297e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 298e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (track) { 299be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber ++n; 300e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = track->next; 301e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 302e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 303be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return n; 304e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 305e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 306e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Hubersp<MetaData> MPEG4Extractor::getTrackMetaData( 307e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber size_t index, uint32_t flags) { 308e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 309e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if ((err = readMetaData()) != OK) { 310e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return NULL; 311e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 312e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 313e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 314e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (index > 0) { 315e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (track == NULL) { 316e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return NULL; 317e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 318e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 319e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = track->next; 320e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber --index; 321e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 322e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 3232a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber if (track == NULL) { 3242a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber return NULL; 3252a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber } 3262a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber 327e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber if ((flags & kIncludeExtensiveMetaData) 328e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber && !track->includes_expensive_metadata) { 329e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber track->includes_expensive_metadata = true; 330e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber 331e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber const char *mime; 332e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 333e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber if (!strncasecmp("video/", mime, 6)) { 334e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber uint32_t sampleIndex; 335e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber uint32_t sampleTime; 336e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber if (track->sampleTable->findThumbnailSample(&sampleIndex) == OK 3371faa92a1e93f311e86dca483ed7702091137de66Andreas Huber && track->sampleTable->getMetaDataForSample( 3381faa92a1e93f311e86dca483ed7702091137de66Andreas Huber sampleIndex, NULL /* offset */, NULL /* size */, 3391faa92a1e93f311e86dca483ed7702091137de66Andreas Huber &sampleTime) == OK) { 340e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber track->meta->setInt64( 341e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber kKeyThumbnailTime, 342e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber ((int64_t)sampleTime * 1000000) / track->timescale); 343e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber } 344e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber } 345e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber } 346e981c33446a98d5ccc0d73c1a840696d77cf0732Andreas Huber 347e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return track->meta; 348e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 349e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 350e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Extractor::readMetaData() { 351e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mHaveMetadata) { 352e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 353e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 354e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 355e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t offset = 0; 356e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 357e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while ((err = parseChunk(&offset, 0)) == OK) { 358e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 3591cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 360e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mHaveMetadata) { 361c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mHasVideo) { 362c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyMIMEType, "video/mp4"); 363c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else { 364c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyMIMEType, "audio/mp4"); 365c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 366c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 367e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 368e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 369e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 370e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 371e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 372e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 373e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatic void MakeFourCCString(uint32_t x, char *s) { 374e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[0] = x >> 24; 375e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[1] = (x >> 16) & 0xff; 376e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[2] = (x >> 8) & 0xff; 377e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[3] = x & 0xff; 378e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber s[4] = '\0'; 379e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 380e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 381c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstruct PathAdder { 382c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder(Vector<uint32_t> *path, uint32_t chunkType) 383c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber : mPath(path) { 384c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mPath->push(chunkType); 385c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 386c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 387c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber ~PathAdder() { 388c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mPath->pop(); 389c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 390c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 391c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberprivate: 392c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber Vector<uint32_t> *mPath; 393c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 394c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder(const PathAdder &); 395c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder &operator=(const PathAdder &); 396c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber}; 397c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 398c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatic bool underMetaDataPath(const Vector<uint32_t> &path) { 399c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return path.size() >= 5 400c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && path[0] == FOURCC('m', 'o', 'o', 'v') 401c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && path[1] == FOURCC('u', 'd', 't', 'a') 402c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && path[2] == FOURCC('m', 'e', 't', 'a') 403c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && path[3] == FOURCC('i', 'l', 's', 't'); 404c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber} 405c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 406c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber// Given a time in seconds since Jan 1 1904, produce a human-readable string. 407c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatic void convertTimeToDate(int64_t time_1904, String8 *s) { 408c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600); 409c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 410c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber char tmp[32]; 411c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber strftime(tmp, sizeof(tmp), "%Y%m%dT%H%M%S.000Z", gmtime(&time_1970)); 412c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 413c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber s->setTo(tmp); 414c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber} 415c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 416e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Extractor::parseChunk(off_t *offset, int depth) { 417e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t hdr[2]; 4189a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt(*offset, hdr, 8) < 8) { 419e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 420e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 421e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint64_t chunk_size = ntohl(hdr[0]); 422e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t chunk_type = ntohl(hdr[1]); 423e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t data_offset = *offset + 8; 424e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 425e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_size == 1) { 4269a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt(*offset + 8, &chunk_size, 8) < 8) { 427e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 428e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 429e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber chunk_size = ntoh64(chunk_size); 430e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset += 8; 431736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber 432736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber if (chunk_size < 16) { 433736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber // The smallest valid chunk is 16 bytes long in this case. 434736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber return ERROR_MALFORMED; 435736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber } 436736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber } else if (chunk_size < 8) { 437736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber // The smallest valid chunk is 8 bytes long. 438736c22d3e0b96a45e46ce43ac20a48ecbc373db7Andreas Huber return ERROR_MALFORMED; 439e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 440e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 441e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber char chunk[5]; 442e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MakeFourCCString(chunk_type, chunk); 443e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 444e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#if 0 445e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber static const char kWhitespace[] = " "; 446e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth]; 447e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size); 448e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 449e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber char buffer[256]; 450dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber size_t n = chunk_size; 451dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber if (n > sizeof(buffer)) { 452dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber n = sizeof(buffer); 453dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber } 454dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber if (mDataSource->readAt(*offset, buffer, n) 455dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber < (ssize_t)n) { 456dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber return ERROR_IO; 457e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 458dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber 459dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber hexdump(buffer, n); 460e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber#endif 461e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 462c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber PathAdder autoAdder(&mPath, chunk_type); 463c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 464e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t chunk_data_size = *offset + chunk_size - data_offset; 465e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 466c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (chunk_type != FOURCC('c', 'p', 'r', 't') 467c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber && mPath.size() == 5 && underMetaDataPath(mPath)) { 468c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber off_t stop_offset = *offset + chunk_size; 469c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset = data_offset; 470c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber while (*offset < stop_offset) { 471c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber status_t err = parseChunk(offset, depth + 1); 472c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (err != OK) { 473c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return err; 474c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 475c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 4765ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 4775ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 4785ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 4795ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 480c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 481c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return OK; 482c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 483c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 484e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber switch(chunk_type) { 485e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'o', 'o', 'v'): 486e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('t', 'r', 'a', 'k'): 487e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'd', 'i', 'a'): 488e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'i', 'n', 'f'): 489e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('d', 'i', 'n', 'f'): 490e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 'b', 'l'): 491e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'v', 'e', 'x'): 492e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'o', 'o', 'f'): 493e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('t', 'r', 'a', 'f'): 494e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'f', 'r', 'a'): 495c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('u', 'd', 't', 'a'): 496c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('i', 'l', 's', 't'): 497e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 498affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (chunk_type == FOURCC('s', 't', 'b', 'l')) { 499affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber LOGV("sampleTable chunk is %d bytes long.", (size_t)chunk_size); 500affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 5016da2ae11b62f155ee83c3e31fdd9cc53b2058586Andreas Huber if (mDataSource->flags() 5026da2ae11b62f155ee83c3e31fdd9cc53b2058586Andreas Huber & (DataSource::kWantsPrefetching 5036da2ae11b62f155ee83c3e31fdd9cc53b2058586Andreas Huber | DataSource::kIsCachingDataSource)) { 504affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber sp<MPEG4DataSource> cachedSource = 505affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber new MPEG4DataSource(mDataSource); 506affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 507affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber if (cachedSource->setCachedRange(*offset, chunk_size) == OK) { 508affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber mDataSource = cachedSource; 509affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 510affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 511eb9128f9b0ee660504621381fd96f82d5bf8a3fdAndreas Huber 512eb9128f9b0ee660504621381fd96f82d5bf8a3fdAndreas Huber mLastTrack->sampleTable = new SampleTable(mDataSource); 513affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber } 514affa99c52957685f5a5652ab5254b92e729651c7Andreas Huber 5154d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber bool isTrack = false; 5165ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_type == FOURCC('t', 'r', 'a', 'k')) { 5174d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber isTrack = true; 5184d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 5195ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber Track *track = new Track; 5205ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->next = NULL; 5215ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (mLastTrack) { 5225ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber mLastTrack->next = track; 5235ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else { 5245ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber mFirstTrack = track; 5255ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 5265ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber mLastTrack = track; 5275ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 5285ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->meta = new MetaData; 5295ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->includes_expensive_metadata = false; 5304d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber track->skipTrack = false; 5315ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->timescale = 0; 5325ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber track->meta->setCString(kKeyMIMEType, "application/octet-stream"); 5335ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 5345ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 535e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t stop_offset = *offset + chunk_size; 536e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset; 537e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (*offset < stop_offset) { 538e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 539e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 540e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 541e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 542e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 543e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 5445ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 5455ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 5465ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 5475ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 5484d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber if (isTrack) { 5494d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber if (mLastTrack->skipTrack) { 5504d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber Track *cur = mFirstTrack; 5514d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 5524d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber if (cur == mLastTrack) { 5534d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber delete cur; 5544d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber mFirstTrack = mLastTrack = NULL; 5554d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber } else { 5564d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber while (cur && cur->next != mLastTrack) { 5574d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber cur = cur->next; 5584d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber } 5594d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber cur->next = NULL; 5604d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber delete mLastTrack; 5614d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber mLastTrack = cur; 5624d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber } 5634d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 5644d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber return OK; 5654d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber } 5664d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 5675ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber status_t err = verifyTrack(mLastTrack); 5685ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 5695ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (err != OK) { 5705ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return err; 5715ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 5725ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else if (chunk_type == FOURCC('m', 'o', 'o', 'v')) { 573e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mHaveMetadata = true; 574e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 575e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return UNKNOWN_ERROR; // Return a dummy error. 576e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 577e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 578e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 579e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 580e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('t', 'k', 'h', 'd'): 581e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 58231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber status_t err; 58331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) { 58431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber return err; 585e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 586e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 587e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 588e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 589e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 590e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 591e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'd', 'h', 'd'): 592e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 593e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 4) { 594e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 595e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 596e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 597e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t version; 5989a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 599e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, &version, sizeof(version)) 600e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(version)) { 601e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 602e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 603e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 604e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t timescale_offset; 605e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 606e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 1) { 607e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset = data_offset + 4 + 16; 608e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else if (version == 0) { 609e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset = data_offset + 4 + 8; 610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 611e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t timescale; 6159a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 616e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset, ×cale, sizeof(timescale)) 617e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(timescale)) { 618e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 619e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 620e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 621e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->timescale = ntohl(timescale); 622e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 623e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int64_t duration; 624e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (version == 1) { 6259a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 626e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset + 4, &duration, sizeof(duration)) 627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(duration)) { 628e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 629e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 630e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber duration = ntoh64(duration); 631e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 632e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t duration32; 6339a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 634e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber timescale_offset + 4, &duration32, sizeof(duration32)) 635e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber < (ssize_t)sizeof(duration32)) { 636e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 637e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 638e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber duration = ntohl(duration32); 639e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 640fa8de752507feaca695123911915070c1ce463b2Andreas Huber mLastTrack->meta->setInt64( 641fa8de752507feaca695123911915070c1ce463b2Andreas Huber kKeyDuration, (duration * 1000000) / mLastTrack->timescale); 642e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 643e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 644e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 645e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 646e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 647e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 'd'): 648e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 649e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 8) { 650e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 651e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 652e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 653e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[8]; 6545ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_data_size < (off_t)sizeof(buffer)) { 6555ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 6565ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 6575ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 6589a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 659e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, 8) < 8) { 660e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 661e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 662e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 663e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (U32_AT(buffer) != 0) { 664e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Should be version 0, flags 0. 665e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 666e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 667e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 668e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t entry_count = U32_AT(&buffer[4]); 669e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 670e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (entry_count > 1) { 671e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // For now we only support a single type of media per track. 6724d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber 6734d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber mLastTrack->skipTrack = true; 6744d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber *offset += chunk_size; 6754d60fc5b43b74cdb45e1d1ba55972d48ebed37eeAndreas Huber break; 676e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 677e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 678e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t stop_offset = *offset + chunk_size; 679e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset + 8; 680e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber for (uint32_t i = 0; i < entry_count; ++i) { 681e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 682e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 683e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 684e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 685e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 6865ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 6875ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 6885ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 6895ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 690e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 691e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 692e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 693e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'a'): 694e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 'a', 'm', 'r'): 6952a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber case FOURCC('s', 'a', 'w', 'b'): 696e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 697e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[8 + 20]; 698e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 699e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Basic AudioSampleEntry size. 700e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 701e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 702e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 7039a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 704e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 705e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 706e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 707e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 708e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 709e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t num_channels = U16_AT(&buffer[16]); 710e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 711d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber uint16_t sample_size = U16_AT(&buffer[18]); 712d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber uint32_t sample_rate = U32_AT(&buffer[24]) >> 16; 713d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber 714e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB, 715d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber FourCC2MIME(chunk_type))) { 716d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber // AMR NB audio is always mono, 8kHz 717d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber num_channels = 1; 718d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber sample_rate = 8000; 719d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB, 720e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber FourCC2MIME(chunk_type))) { 721d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber // AMR WB audio is always mono, 16kHz 722e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber num_channels = 1; 723d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber sample_rate = 16000; 724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 725e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 726d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber#if 0 727d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber printf("*** coding='%s' %d channels, size %d, rate %d\n", 728d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber chunk, num_channels, sample_size, sample_rate); 729d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber#endif 730e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 731e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 732e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, num_channels); 733e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sample_rate); 734e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 735e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t stop_offset = *offset + chunk_size; 736e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset + sizeof(buffer); 737e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (*offset < stop_offset) { 738e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 739e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 740e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 741e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 742e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 7435ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 7445ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 7455ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 7465ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 747e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 748e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 749e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 750e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('m', 'p', '4', 'v'): 751e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', '2', '6', '3'): 752e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('a', 'v', 'c', '1'): 753e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 7541cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber mHasVideo = true; 7551cb02bf661807ffc6525dcc13e16d7ce027bef00Andreas Huber 756e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[78]; 757e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < (ssize_t)sizeof(buffer)) { 758e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Basic VideoSampleEntry size. 759e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 760e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 761e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 7629a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 763e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) { 764e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 765e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 766e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 767e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t data_ref_index = U16_AT(&buffer[6]); 768e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t width = U16_AT(&buffer[6 + 18]); 769e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint16_t height = U16_AT(&buffer[6 + 20]); 770e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 7712ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber // printf("*** coding='%s' width=%d height=%d\n", 7722ea14e231945afb6581fa8f54015b33bc74a19e5Andreas Huber // chunk, width, height); 773e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 774e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type)); 775e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeyWidth, width); 776e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setInt32(kKeyHeight, height); 777e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 778e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber off_t stop_offset = *offset + chunk_size; 779e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset = data_offset + sizeof(buffer); 780e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (*offset < stop_offset) { 781e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = parseChunk(offset, depth + 1); 782e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 783e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 784e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 785e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 7865ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 7875ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 7885ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 7895ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 790e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 791e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 792e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 793e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 'c', 'o'): 794e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('c', 'o', '6', '4'): 795e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 796e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 797e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setChunkOffsetParams( 798e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber chunk_type, data_offset, chunk_data_size); 799e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 800e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 801e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 802e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 803e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 804e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 805e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 806e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 807e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 808e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 'c'): 809e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 810e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 811e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setSampleToChunkParams( 812e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, chunk_data_size); 813e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 814e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 815e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 816e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 817e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 818e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 819e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 820e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 821e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 822e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 'z'): 823e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 'z', '2'): 824e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 825e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 826e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setSampleSizeParams( 827e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber chunk_type, data_offset, chunk_data_size); 828e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 829e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 830e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 831e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 832e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 8331bceff916a72246fa208605d50615823d7f1688bAndreas Huber size_t max_size; 834d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber err = mLastTrack->sampleTable->getMaxSampleSize(&max_size); 835d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber 836d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber if (err != OK) { 837d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber return err; 838d7f2225e7455f5e0da32f409a528ced283631c5dAndreas Huber } 8391bceff916a72246fa208605d50615823d7f1688bAndreas Huber 8401bceff916a72246fa208605d50615823d7f1688bAndreas Huber // Assume that a given buffer only contains at most 10 fragments, 8411bceff916a72246fa208605d50615823d7f1688bAndreas Huber // each fragment originally prefixed with a 2 byte length will 8421bceff916a72246fa208605d50615823d7f1688bAndreas Huber // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion, 8431bceff916a72246fa208605d50615823d7f1688bAndreas Huber // and thus will grow by 2 bytes per fragment. 8441bceff916a72246fa208605d50615823d7f1688bAndreas Huber mLastTrack->meta->setInt32(kKeyMaxInputSize, max_size + 10 * 2); 8451bceff916a72246fa208605d50615823d7f1688bAndreas Huber 846e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 847e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 848e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 849e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 850e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 't', 's'): 851e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 852e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 853e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setTimeToSampleParams( 854e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, chunk_data_size); 855e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 856e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 857e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 858e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 859e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 860e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 861e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 862e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 863e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 864e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('s', 't', 's', 's'): 865e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 866e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err = 867e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->sampleTable->setSyncSampleParams( 868e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, chunk_data_size); 869e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 870e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 871e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 872e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 873e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 874e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 875e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 876e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 877e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 878e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('e', 's', 'd', 's'): 879e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 880e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size < 4) { 881e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 882e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 883e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 884e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t buffer[256]; 885e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size > (off_t)sizeof(buffer)) { 886e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_BUFFER_TOO_SMALL; 887e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 888e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 8899a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 890e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 891e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 892e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 893e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 894e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (U32_AT(buffer) != 0) { 895e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // Should be version 0, flags 0. 896e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_MALFORMED; 897e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 898e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 899e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setData( 900e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4); 901e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 902d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (mPath.size() >= 2 903d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber && mPath[mPath.size() - 2] == FOURCC('m', 'p', '4', 'a')) { 904d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // Information from the ESDS must be relied on for proper 905d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // setup of sample rate and channel count for MPEG4 Audio. 906d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // The generic header appears to only contain generic 907d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber // information... 908d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 909d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber status_t err = updateAudioTrackInfoFromESDS_MPEG4Audio( 910d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber &buffer[4], chunk_data_size - 4); 911d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 912d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (err != OK) { 913d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return err; 914d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 915d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 916d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 917e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 918e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 919e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 920e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 921e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber case FOURCC('a', 'v', 'c', 'C'): 922e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 923e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber char buffer[256]; 924e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (chunk_data_size > (off_t)sizeof(buffer)) { 925e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_BUFFER_TOO_SMALL; 926e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 927e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 9289a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber if (mDataSource->readAt( 929e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber data_offset, buffer, chunk_data_size) < chunk_data_size) { 930e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return ERROR_IO; 931e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 932e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 933e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mLastTrack->meta->setData( 934e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber kKeyAVCC, kTypeAVCC, buffer, chunk_data_size); 935e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 936e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 937e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 938e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 939e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 940c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('m', 'e', 't', 'a'): 941c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 942c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint8_t buffer[4]; 9435ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (chunk_data_size < (off_t)sizeof(buffer)) { 9445ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 9455ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 9465ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 947c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt( 948c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber data_offset, buffer, 4) < 4) { 949c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_IO; 950c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 951c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 952c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (U32_AT(buffer) != 0) { 953c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber // Should be version 0, flags 0. 954dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber 955dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber // If it's not, let's assume this is one of those 956dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber // apparently malformed chunks that don't have flags 957dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber // and completely different semantics than what's 958dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber // in the MPEG4 specs and skip it. 959dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber *offset += chunk_size; 960dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber return OK; 961c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 962c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 963c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber off_t stop_offset = *offset + chunk_size; 964c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset = data_offset + sizeof(buffer); 965c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber while (*offset < stop_offset) { 966c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber status_t err = parseChunk(offset, depth + 1); 967c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (err != OK) { 968c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return err; 969c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 970c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 9715ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 9725ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (*offset != stop_offset) { 9735ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 9745ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 975c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 976c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 977c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 978c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('d', 'a', 't', 'a'): 979c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 980c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mPath.size() == 6 && underMetaDataPath(mPath)) { 981c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber status_t err = parseMetaData(data_offset, chunk_data_size); 982c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 983c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (err != OK) { 984c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return err; 985c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 986c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 987c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 988c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset += chunk_size; 989c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 990c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 991c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 992c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('m', 'v', 'h', 'd'): 993c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 994c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (chunk_data_size < 12) { 995c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_MALFORMED; 996c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 997c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 998c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint8_t header[12]; 999c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt( 1000c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber data_offset, header, sizeof(header)) 1001c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber < (ssize_t)sizeof(header)) { 1002c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_IO; 1003c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1004c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1005c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber int64_t creationTime; 1006c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (header[0] == 1) { 1007c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber creationTime = U64_AT(&header[4]); 10085ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else if (header[0] != 0) { 10095ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 1010c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else { 1011c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber creationTime = U32_AT(&header[4]); 1012c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1013c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1014c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber String8 s; 1015c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber convertTimeToDate(creationTime, &s); 1016c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1017c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyDate, s.string()); 1018c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1019c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber *offset += chunk_size; 1020c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1021c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1022c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1023e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber default: 1024e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber { 1025e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *offset += chunk_size; 1026e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber break; 1027e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1028e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1029e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1030e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1031e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1032e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 103331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huberstatus_t MPEG4Extractor::parseTrackHeader( 103431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber off_t data_offset, off_t data_size) { 103531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber if (data_size < 4) { 103631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber return ERROR_MALFORMED; 103731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber } 103831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 103931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber uint8_t version; 104031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber if (mDataSource->readAt(data_offset, &version, 1) < 1) { 104131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber return ERROR_IO; 104231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber } 104331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 104431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber size_t dynSize = (version == 1) ? 36 : 24; 104531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 104631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber uint8_t buffer[36 + 60]; 104731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 104831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber if (data_size != (off_t)dynSize + 60) { 104931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber return ERROR_MALFORMED; 105031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber } 105131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 105231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber if (mDataSource->readAt( 105331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber data_offset, buffer, data_size) < (ssize_t)data_size) { 105431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber return ERROR_IO; 105531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber } 105631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 105731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber uint64_t ctime, mtime, duration; 105831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber int32_t id; 105931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 106031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber if (version == 1) { 106131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber ctime = U64_AT(&buffer[4]); 106231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber mtime = U64_AT(&buffer[12]); 106331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber id = U32_AT(&buffer[20]); 106431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber duration = U64_AT(&buffer[28]); 106531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber } else if (version == 0) { 106631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber ctime = U32_AT(&buffer[4]); 106731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber mtime = U32_AT(&buffer[8]); 106831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber id = U32_AT(&buffer[12]); 106931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber duration = U32_AT(&buffer[20]); 107031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber } 107131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 107231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber size_t matrixOffset = dynSize + 16; 107331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber int32_t a00 = U32_AT(&buffer[matrixOffset]); 107431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber int32_t a01 = U32_AT(&buffer[matrixOffset + 4]); 107531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber int32_t dx = U32_AT(&buffer[matrixOffset + 8]); 107631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber int32_t a10 = U32_AT(&buffer[matrixOffset + 12]); 107731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber int32_t a11 = U32_AT(&buffer[matrixOffset + 16]); 107831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber int32_t dy = U32_AT(&buffer[matrixOffset + 20]); 107931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 108031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber#if 0 108131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber LOGI("x' = %.2f * x + %.2f * y + %.2f", 108231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f); 108331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber LOGI("y' = %.2f * x + %.2f * y + %.2f", 108431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f); 108531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber#endif 108631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 108731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber uint32_t rotationDegrees; 108831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 108931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber static const int32_t kFixedOne = 0x10000; 109031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) { 109131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber // Identity, no rotation 109231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber rotationDegrees = 0; 109331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) { 109431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber rotationDegrees = 90; 109531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) { 109631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber rotationDegrees = 270; 109731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) { 109831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber rotationDegrees = 180; 109931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber } else { 110031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber LOGW("We only support 0,90,180,270 degree rotation matrices"); 110131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber rotationDegrees = 0; 110231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber } 110331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 110431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber if (rotationDegrees != 0) { 110531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees); 110631dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber } 110731dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 110831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber#if 0 110931dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber uint32_t width = U32_AT(&buffer[dynSize + 52]); 111031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber uint32_t height = U32_AT(&buffer[dynSize + 56]); 111131dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber#endif 111231dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 111331dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber return OK; 111431dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber} 111531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber 1116c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huberstatus_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) { 1117c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (size < 4) { 1118c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_MALFORMED; 1119c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1120c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1121c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint8_t *buffer = new uint8_t[size + 1]; 1122c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (mDataSource->readAt( 1123c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber offset, buffer, size) != (ssize_t)size) { 1124c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber delete[] buffer; 1125c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer = NULL; 1126c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1127c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return ERROR_IO; 1128c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1129c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1130c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint32_t flags = U32_AT(buffer); 1131c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1132c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber uint32_t metadataKey = 0; 1133c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber switch (mPath[4]) { 1134c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'a', 'l', 'b'): 1135c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1136c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyAlbum; 1137c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1138c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1139c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'A', 'R', 'T'): 1140c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1141c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyArtist; 1142c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1143c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1144c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen case FOURCC('a', 'A', 'R', 'T'): 1145c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen { 1146c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen metadataKey = kKeyAlbumArtist; 1147c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen break; 1148c5d5ee34d7c1026ca8d5cd8b186e5a73c5230247Marco Nelissen } 1149c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'd', 'a', 'y'): 1150c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1151c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyYear; 1152c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1153c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1154c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'n', 'a', 'm'): 1155c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1156c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyTitle; 1157c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1158c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1159c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC(0xa9, 'w', 'r', 't'): 1160c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1161c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyWriter; 1162c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1163c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1164c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('c', 'o', 'v', 'r'): 1165c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1166c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyAlbumArt; 1167c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1168c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1169c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('g', 'n', 'r', 'e'): 1170c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1171c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey = kKeyGenre; 1172c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1173c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1174fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen case FOURCC(0xa9, 'g', 'e', 'n'): 1175fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen { 1176fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen metadataKey = kKeyGenre; 1177fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen break; 1178fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1179ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen case FOURCC('c', 'p', 'i', 'l'): 1180ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen { 1181ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen if (size == 9 && flags == 21) { 1182ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen char tmp[16]; 1183ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen sprintf(tmp, "%d", 1184ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen (int)buffer[size - 1]); 1185ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen 1186ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen mFileMetaData->setCString(kKeyCompilation, tmp); 1187ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen } 1188ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen break; 1189ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen } 1190c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber case FOURCC('t', 'r', 'k', 'n'): 1191c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber { 1192c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (size == 16 && flags == 0) { 1193c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber char tmp[16]; 1194c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber sprintf(tmp, "%d/%d", 1195c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber (int)buffer[size - 5], (int)buffer[size - 3]); 1196c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1197c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(kKeyCDTrackNumber, tmp); 1198c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1199c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1200c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1201fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen case FOURCC('d', 'i', 's', 'k'): 1202fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen { 1203fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen if (size == 14 && flags == 0) { 1204fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen char tmp[16]; 1205fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen sprintf(tmp, "%d/%d", 1206fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen (int)buffer[size - 3], (int)buffer[size - 1]); 1207fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen 1208fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen mFileMetaData->setCString(kKeyDiscNumber, tmp); 1209fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1210fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen break; 1211fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1212fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen 1213c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber default: 1214c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber break; 1215c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1216c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1217c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (size >= 8 && metadataKey) { 1218c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (metadataKey == kKeyAlbumArt) { 1219c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setData( 1220c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber kKeyAlbumArt, MetaData::TYPE_NONE, 1221c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer + 8, size - 8); 1222c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else if (metadataKey == kKeyGenre) { 1223c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber if (flags == 0) { 1224fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // uint8_t genre code, iTunes genre codes are 1225fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // the standard id3 codes, except they start 1226fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // at 1 instead of 0 (e.g. Pop is 14, not 13) 1227fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // We use standard id3 numbering, so subtract 1. 1228fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen int genrecode = (int)buffer[size - 1]; 1229fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen genrecode--; 1230fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen if (genrecode < 0) { 1231fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen genrecode = 255; // reserved for 'unknown genre' 1232fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } 1233c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber char genre[10]; 1234fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen sprintf(genre, "%d", genrecode); 1235c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1236c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString(metadataKey, genre); 1237fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen } else if (flags == 1) { 1238fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen // custom genre string 1239fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen buffer[size] = '\0'; 1240fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen 1241fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen mFileMetaData->setCString( 1242fe3b8e9fe5e68ef307fdac3ad94b15215038dbc3Marco Nelissen metadataKey, (const char *)buffer + 8); 1243c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1244c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } else { 1245c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer[size] = '\0'; 1246c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1247c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber mFileMetaData->setCString( 1248c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber metadataKey, (const char *)buffer + 8); 1249c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1250c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber } 1251c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1252c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber delete[] buffer; 1253c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber buffer = NULL; 1254c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1255c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber return OK; 1256c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber} 1257c2c9dd32511b555c637b8cadb8091eaa6088f92bAndreas Huber 1258be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Hubersp<MediaSource> MPEG4Extractor::getTrack(size_t index) { 1259e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber status_t err; 1260e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if ((err = readMetaData()) != OK) { 1261be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return NULL; 1262e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1263e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1264e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber Track *track = mFirstTrack; 1265e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber while (index > 0) { 1266e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (track == NULL) { 1267be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return NULL; 1268e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1269e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1270e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber track = track->next; 1271e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber --index; 1272e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1273e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 12742a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber if (track == NULL) { 12752a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber return NULL; 12762a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber } 12772a651177be1d29e8b4bdc84c84060514b15350f0Andreas Huber 1278be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber return new MPEG4Source( 1279fa8de752507feaca695123911915070c1ce463b2Andreas Huber track->meta, mDataSource, track->timescale, track->sampleTable); 1280e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1281e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 12825ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber// static 12835ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huberstatus_t MPEG4Extractor::verifyTrack(Track *track) { 12845ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber const char *mime; 12855ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber CHECK(track->meta->findCString(kKeyMIMEType, &mime)); 12865ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 12875ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber uint32_t type; 12885ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber const void *data; 12895ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber size_t size; 12905ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) { 12915ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (!track->meta->findData(kKeyAVCC, &type, &data, &size) 12925ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber || type != kTypeAVCC) { 12935ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 12945ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 12955ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) 12965ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { 12975ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber if (!track->meta->findData(kKeyESDS, &type, &data, &size) 12985ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber || type != kTypeESDS) { 12995ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return ERROR_MALFORMED; 13005ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 13015ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber } 13025ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 13035ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber return OK; 13045ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber} 13055ee0bce5e006610a06d6d8f3572098b1ccaded6dAndreas Huber 1306d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huberstatus_t MPEG4Extractor::updateAudioTrackInfoFromESDS_MPEG4Audio( 1307d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber const void *esds_data, size_t esds_size) { 1308d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber ESDS esds(esds_data, esds_size); 1309d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber 1310d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber uint8_t objectTypeIndication; 1311d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber if (esds.getObjectTypeIndication(&objectTypeIndication) != OK) { 1312d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber return ERROR_MALFORMED; 1313d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber } 1314d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber 1315d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber if (objectTypeIndication == 0xe1) { 1316d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber // This isn't MPEG4 audio at all, it's QCELP 14k... 1317d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber mLastTrack->meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_QCELP); 1318d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber return OK; 1319d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber } 1320d0332ad8d212d87fbf909fc780e6378b4d2c20c1Andreas Huber 1321d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber const uint8_t *csd; 1322d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber size_t csd_size; 1323d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (esds.getCodecSpecificInfo( 1324d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber (const void **)&csd, &csd_size) != OK) { 1325d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1326d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1327d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1328d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#if 0 1329d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber printf("ESD of size %d\n", csd_size); 1330d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber hexdump(csd, csd_size); 1331d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber#endif 1332d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 133308c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber if (csd_size == 0) { 133408c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber // There's no further information, i.e. no codec specific data 133508c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber // Let's assume that the information provided in the mpeg4 headers 133608c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber // is accurate and hope for the best. 133708c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber 133808c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber return OK; 133908c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber } 134008c94b265c4bf7105b593afb119053a2e16865e9Andreas Huber 1341d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (csd_size < 2) { 1342d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1343d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1344d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1345d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber uint32_t objectType = csd[0] >> 3; 1346d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1347d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (objectType == 31) { 1348d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_UNSUPPORTED; 1349d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1350d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1351d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber uint32_t freqIndex = (csd[0] & 7) << 1 | (csd[1] >> 7); 1352d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t sampleRate = 0; 1353d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t numChannels = 0; 1354d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (freqIndex == 15) { 1355d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (csd_size < 5) { 1356d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1357d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1358d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1359d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber sampleRate = (csd[1] & 0x7f) << 17 1360d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber | csd[2] << 9 1361d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber | csd[3] << 1 1362d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber | (csd[4] >> 7); 1363d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1364d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber numChannels = (csd[4] >> 3) & 15; 1365d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } else { 1366cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber static uint32_t kSamplingRate[] = { 1367cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 1368cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber 16000, 12000, 11025, 8000, 7350 1369cc14a8393b92cd1ed6cba74829396045605ab211Andreas Huber }; 1370d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1371d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (freqIndex == 13 || freqIndex == 14) { 1372d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_MALFORMED; 1373d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1374d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1375d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber sampleRate = kSamplingRate[freqIndex]; 1376d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber numChannels = (csd[1] >> 3) & 15; 1377d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1378d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1379d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (numChannels == 0) { 1380d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return ERROR_UNSUPPORTED; 1381d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1382d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1383d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t prevSampleRate; 1384d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber CHECK(mLastTrack->meta->findInt32(kKeySampleRate, &prevSampleRate)); 1385d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1386d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (prevSampleRate != sampleRate) { 13874a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber LOGV("mpeg4 audio sample rate different from previous setting. " 1388d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber "was: %d, now: %d", prevSampleRate, sampleRate); 1389d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1390d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1391d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber mLastTrack->meta->setInt32(kKeySampleRate, sampleRate); 1392d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1393d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber int32_t prevChannelCount; 1394d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber CHECK(mLastTrack->meta->findInt32(kKeyChannelCount, &prevChannelCount)); 1395d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1396d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber if (prevChannelCount != numChannels) { 13974a9375ef2a06fc36ec308835ef9e7e4eea2ba69fAndreas Huber LOGV("mpeg4 audio channel count different from previous setting. " 1398d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber "was: %d, now: %d", prevChannelCount, numChannels); 1399d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber } 1400d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1401d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber mLastTrack->meta->setInt32(kKeyChannelCount, numChannels); 1402d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1403d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber return OK; 1404d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber} 1405d2315967b4075875cd6681327ae3043fa2adfbcfAndreas Huber 1406e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber//////////////////////////////////////////////////////////////////////////////// 1407e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1408e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::MPEG4Source( 1409e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const sp<MetaData> &format, 1410be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<DataSource> &dataSource, 1411fa8de752507feaca695123911915070c1ce463b2Andreas Huber int32_t timeScale, 1412be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<SampleTable> &sampleTable) 1413e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber : mFormat(format), 1414e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mDataSource(dataSource), 1415fa8de752507feaca695123911915070c1ce463b2Andreas Huber mTimescale(timeScale), 1416e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mSampleTable(sampleTable), 1417e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentSampleIndex(0), 1418e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mIsAVC(false), 1419db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mNALLengthSize(0), 1420e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted(false), 1421e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup(NULL), 1422e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer(NULL), 14234f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mWantsNALFragments(false), 14248a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber mSrcBuffer(NULL) { 1425e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber const char *mime; 1426e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber bool success = mFormat->findCString(kKeyMIMEType, &mime); 14274f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(success); 1428e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1429e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC); 1430db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1431db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber if (mIsAVC) { 1432db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber uint32_t type; 1433db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber const void *data; 1434db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t size; 1435db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(format->findData(kKeyAVCC, &type, &data, &size)); 1436db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1437db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber const uint8_t *ptr = (const uint8_t *)data; 1438db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1439db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(size >= 7); 144031dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber CHECK_EQ((unsigned)ptr[0], 1u); // configurationVersion == 1 1441db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1442db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber // The number of bytes used to encode the length of a NAL unit. 1443db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mNALLengthSize = 1 + (ptr[4] & 3); 1444db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber } 1445e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1446e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1447e46b7be812d68e49710b34048662cbf18e2a6550Andreas HuberMPEG4Source::~MPEG4Source() { 1448e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mStarted) { 1449e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber stop(); 1450e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1451e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1452e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1453e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::start(MetaData *params) { 1454ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1455ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 14564f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(!mStarted); 1457e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1458e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int32_t val; 14594f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (params && params->findInt32(kKeyWantsNALFragments, &val) 1460e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber && val != 0) { 14614f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mWantsNALFragments = true; 1462e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } else { 14634f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mWantsNALFragments = false; 1464e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1465e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1466e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup = new MediaBufferGroup; 1467e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 14681bceff916a72246fa208605d50615823d7f1688bAndreas Huber int32_t max_size; 14691bceff916a72246fa208605d50615823d7f1688bAndreas Huber CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size)); 1470e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 14711bceff916a72246fa208605d50615823d7f1688bAndreas Huber mGroup->add_buffer(new MediaBuffer(max_size)); 14728a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber 14738a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber mSrcBuffer = new uint8_t[max_size]; 1474e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1475e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted = true; 1476e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1477e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1478e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1479e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1480e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::stop() { 1481ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1482ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 14834f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(mStarted); 1484e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1485e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mBuffer != NULL) { 1486e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->release(); 1487e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1488e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1489e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 14908a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber delete[] mSrcBuffer; 14918a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber mSrcBuffer = NULL; 14928a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber 1493e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber delete mGroup; 1494e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mGroup = NULL; 1495e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1496e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mStarted = false; 1497e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mCurrentSampleIndex = 0; 1498e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1499e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1500e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1501e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1502e46b7be812d68e49710b34048662cbf18e2a6550Andreas Hubersp<MetaData> MPEG4Source::getFormat() { 1503ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1504ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 1505e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return mFormat; 1506e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1507e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1508db5d662254f2ed788d32e2466739adc8d655c732Andreas Hubersize_t MPEG4Source::parseNALSize(const uint8_t *data) const { 1509db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber switch (mNALLengthSize) { 1510db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 1: 1511db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return *data; 1512db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 2: 1513db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return U16_AT(data); 1514db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 3: 1515db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return ((size_t)data[0] << 16) | U16_AT(&data[1]); 1516db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber case 4: 1517db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return U32_AT(data); 1518db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber } 1519db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1520db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber // This cannot happen, mNALLengthSize springs to life by adding 1 to 1521db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber // a 2-bit integer. 1522db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(!"Should not be here."); 1523db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1524db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber return 0; 1525db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber} 1526db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 1527e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huberstatus_t MPEG4Source::read( 1528e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber MediaBuffer **out, const ReadOptions *options) { 1529ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber Mutex::Autolock autoLock(mLock); 1530ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber 15314f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(mStarted); 1532e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1533e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out = NULL; 1534e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 15356624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber int64_t targetSampleTimeUs = -1; 15366624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 1537e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber int64_t seekTimeUs; 15386624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber ReadOptions::SeekMode mode; 15396624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 15406624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber uint32_t findFlags = 0; 15416624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber switch (mode) { 15426624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber case ReadOptions::SEEK_PREVIOUS_SYNC: 15436624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber findFlags = SampleTable::kFlagBefore; 15446624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber break; 15456624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber case ReadOptions::SEEK_NEXT_SYNC: 15466624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber findFlags = SampleTable::kFlagAfter; 15476624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber break; 15486624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber case ReadOptions::SEEK_CLOSEST_SYNC: 15496624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber case ReadOptions::SEEK_CLOSEST: 15506624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber findFlags = SampleTable::kFlagClosest; 15516624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber break; 15526624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber default: 15536624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber CHECK(!"Should not be here."); 15546624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber break; 15556624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 15566624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 1557e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint32_t sampleIndex; 15586624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber status_t err = mSampleTable->findSampleAtTime( 1559e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber seekTimeUs * mTimescale / 1000000, 15606624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber &sampleIndex, findFlags); 15616624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 15626624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 15636624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber // We found the closest sample already, now we want the sync 15646624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber // sample preceding it (or the sample itself of course), even 15656624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber // if the subsequent sync sample is closer. 15666624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber findFlags = SampleTable::kFlagBefore; 15676624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 15686624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 15696624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber uint32_t syncSampleIndex; 15706624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (err == OK) { 15716624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber err = mSampleTable->findSyncSampleNear( 15726624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber sampleIndex, &syncSampleIndex, findFlags); 15736624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 1574e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1575e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (err != OK) { 1576d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber if (err == ERROR_OUT_OF_RANGE) { 1577d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // An attempt to seek past the end of the stream would 1578d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // normally cause this ERROR_OUT_OF_RANGE error. Propagating 1579d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // this all the way to the MediaPlayer would cause abnormal 1580d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // termination. Legacy behaviour appears to be to behave as if 1581d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber // we had seeked to the end of stream, ending normally. 1582d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber err = ERROR_END_OF_STREAM; 1583d7d22eba3c1bb7212ccc566fedb16dbee44f51a2Andreas Huber } 1584e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return err; 1585e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1586e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 15876624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber uint32_t sampleTime; 158831dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber CHECK_EQ((status_t)OK, mSampleTable->getMetaDataForSample( 15896624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber sampleIndex, NULL, NULL, &sampleTime)); 15906624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 15916624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (mode == ReadOptions::SEEK_CLOSEST) { 15926624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber targetSampleTimeUs = (sampleTime * 1000000ll) / mTimescale; 15936624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 15946624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 15956624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber#if 0 15966624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber uint32_t syncSampleTime; 15976624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber CHECK_EQ(OK, mSampleTable->getMetaDataForSample( 15986624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber syncSampleIndex, NULL, NULL, &syncSampleTime)); 15996624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 16006624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber LOGI("seek to time %lld us => sample at time %lld us, " 16016624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber "sync sample at time %lld us", 16026624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber seekTimeUs, 16036624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber sampleTime * 1000000ll / mTimescale, 16046624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber syncSampleTime * 1000000ll / mTimescale); 16056624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber#endif 16066624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 16076624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber mCurrentSampleIndex = syncSampleIndex; 1608e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (mBuffer != NULL) { 1609e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->release(); 1610e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1611e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1612e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1613e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber // fall through 1614e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1615e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 16168a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber off_t offset; 16178a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber size_t size; 16184f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber uint32_t dts; 1619ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber bool isSyncSample; 16204f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber bool newBuffer = false; 16214f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (mBuffer == NULL) { 16224f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber newBuffer = true; 1623e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 16241faa92a1e93f311e86dca483ed7702091137de66Andreas Huber status_t err = 16251faa92a1e93f311e86dca483ed7702091137de66Andreas Huber mSampleTable->getMetaDataForSample( 1626ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber mCurrentSampleIndex, &offset, &size, &dts, &isSyncSample); 1627e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 16284f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (err != OK) { 16294f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return err; 16304f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 16314f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16324f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber err = mGroup->acquire_buffer(&mBuffer); 16331faa92a1e93f311e86dca483ed7702091137de66Andreas Huber 16344f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (err != OK) { 163531dc911aee2b50752c0eb7785176075cdaed139cAndreas Huber CHECK(mBuffer == NULL); 16364f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return err; 16374f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 16388a432776d003247c12222d8dd6a30ea4621aa2d0Andreas Huber } 1639e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 16404f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (!mIsAVC || mWantsNALFragments) { 16414f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (newBuffer) { 16424f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber ssize_t num_bytes_read = 16439a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size); 16444f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16454f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (num_bytes_read < (ssize_t)size) { 16464f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->release(); 16474f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer = NULL; 16484f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16494f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return ERROR_IO; 16504f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 16514f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1652ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(mBuffer != NULL); 16534f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->set_range(0, size); 16544f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->meta_data()->clear(); 1655fa8de752507feaca695123911915070c1ce463b2Andreas Huber mBuffer->meta_data()->setInt64( 1656fa8de752507feaca695123911915070c1ce463b2Andreas Huber kKeyTime, ((int64_t)dts * 1000000) / mTimescale); 16576624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 16586624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (targetSampleTimeUs >= 0) { 16596624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber mBuffer->meta_data()->setInt64( 16606624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber kKeyTargetTime, targetSampleTimeUs); 16616624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 16626624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 1663ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber if (isSyncSample) { 1664ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 1665ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber } 1666ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber 16674f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber ++mCurrentSampleIndex; 16684f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 16694f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16704f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (!mIsAVC) { 16714f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber *out = mBuffer; 16724f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer = NULL; 16734f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16744f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return OK; 16754f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 16764f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16774f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // Each NAL unit is split up into its constituent fragments and 16784f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // each one of them returned in its own buffer. 16794f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1680db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(mBuffer->range_length() >= mNALLengthSize); 16814f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16824f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber const uint8_t *src = 16834f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber (const uint8_t *)mBuffer->data() + mBuffer->range_offset(); 16844f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1685db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t nal_size = parseNALSize(src); 1686909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber if (mBuffer->range_length() < mNALLengthSize + nal_size) { 1687909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber LOGE("incomplete NAL unit."); 1688909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 1689909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer->release(); 1690909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer = NULL; 1691909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 1692909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber return ERROR_MALFORMED; 1693909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber } 16944f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 16954f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber MediaBuffer *clone = mBuffer->clone(); 1696ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(clone != NULL); 1697db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber clone->set_range(mBuffer->range_offset() + mNALLengthSize, nal_size); 16984f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1699ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(mBuffer != NULL); 17004f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->set_range( 1701db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mBuffer->range_offset() + mNALLengthSize + nal_size, 1702db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber mBuffer->range_length() - mNALLengthSize - nal_size); 17034f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 17044f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (mBuffer->range_length() == 0) { 17054f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->release(); 17064f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer = NULL; 17074f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 17084f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 17094f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber *out = clone; 17104f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 17114f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return OK; 17124f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } else { 17134f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // Whole NAL units are returned but each fragment is prefixed by 17144f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber // the start code (0x00 00 00 01). 17154f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1716e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ssize_t num_bytes_read = 17179a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber mDataSource->readAt(offset, mSrcBuffer, size); 1718e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1719e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (num_bytes_read < (ssize_t)size) { 1720e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->release(); 1721e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1722e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 17234f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber return ERROR_IO; 1724e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1725e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 17264f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber uint8_t *dstData = (uint8_t *)mBuffer->data(); 17274f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber size_t srcOffset = 0; 17284f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber size_t dstOffset = 0; 1729db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber 17304f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber while (srcOffset < size) { 1731db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK(srcOffset + mNALLengthSize <= size); 1732db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber size_t nalLength = parseNALSize(&mSrcBuffer[srcOffset]); 1733db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber srcOffset += mNALLengthSize; 1734909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 1735909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber if (srcOffset + nalLength > size) { 1736909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer->release(); 1737909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber mBuffer = NULL; 1738909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber 1739909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber return ERROR_MALFORMED; 1740909255a9cf425534e4a8b582a320686852dc59dcAndreas Huber } 17414f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 17424f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber if (nalLength == 0) { 17434f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber continue; 17444f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 17454f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 17464f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber CHECK(dstOffset + 4 <= mBuffer->size()); 17474f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 17484f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstData[dstOffset++] = 0; 17494f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstData[dstOffset++] = 0; 17504f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstData[dstOffset++] = 0; 17514f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstData[dstOffset++] = 1; 17524f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength); 17534f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber srcOffset += nalLength; 17544f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber dstOffset += nalLength; 17554f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber } 1756db5d662254f2ed788d32e2466739adc8d655c732Andreas Huber CHECK_EQ(srcOffset, size); 17574f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber 1758ba7ec917ea91364598de1ba7a29910cec08fd5deAndreas Huber CHECK(mBuffer != NULL); 17594f5e602e1773a2990bb1f34f09875bd5cd057e5aAndreas Huber mBuffer->set_range(0, dstOffset); 1760e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer->meta_data()->clear(); 1761fa8de752507feaca695123911915070c1ce463b2Andreas Huber mBuffer->meta_data()->setInt64( 1762fa8de752507feaca695123911915070c1ce463b2Andreas Huber kKeyTime, ((int64_t)dts * 1000000) / mTimescale); 17636624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 17646624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (targetSampleTimeUs >= 0) { 17656624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber mBuffer->meta_data()->setInt64( 17666624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber kKeyTargetTime, targetSampleTimeUs); 17676624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber } 17686624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber 1769ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber if (isSyncSample) { 1770ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); 1771ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber } 1772ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber 1773e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber ++mCurrentSampleIndex; 1774e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1775e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber *out = mBuffer; 1776e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber mBuffer = NULL; 1777e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1778e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return OK; 1779e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1780e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1781e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1782261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool LegacySniffMPEG4( 1783be06d26cdc70070654f1eedcd08c1c68cd587ad6Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 1784e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber uint8_t header[8]; 1785e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 17869a12baf929ea803915d7ab626b200ffefb4fbac7Andreas Huber ssize_t n = source->readAt(4, header, sizeof(header)); 1787e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (n < (ssize_t)sizeof(header)) { 1788e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 1789e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1790e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1791e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8) 1792e1130662d0455231853e7d6880bb84d8547d7229James Dong || !memcmp(header, "ftyp3gr6", 8) || !memcmp(header, "ftyp3gs6", 8) 1793e1130662d0455231853e7d6880bb84d8547d7229James Dong || !memcmp(header, "ftyp3ge6", 8) || !memcmp(header, "ftyp3gg6", 8) 17946bce6d87b3fd98e68fb54328fb4dc8e40cd2c293Andreas Huber || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8) 1795dfb8eee5bd1359d8042c1fd2f5143b416c09dfddAndreas Huber || !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8) 1796eea1eefeada90ec54488e1742e81e4226fc6ace5Andreas Huber || !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) { 1797e6c409632f773e41f33188272a0072be9fcb783fAndreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 1798efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber *confidence = 0.4; 1799e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1800e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return true; 1801e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber } 1802e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1803e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber return false; 1804e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} 1805e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1806261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool isCompatibleBrand(uint32_t fourcc) { 1807261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber static const uint32_t kCompatibleBrands[] = { 1808261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('i', 's', 'o', 'm'), 1809261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('i', 's', 'o', '2'), 1810261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('a', 'v', 'c', '1'), 1811261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('3', 'g', 'p', '4'), 1812261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('m', 'p', '4', '1'), 1813261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber FOURCC('m', 'p', '4', '2'), 1814261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber }; 1815261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1816261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber for (size_t i = 0; 1817261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]); 1818261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber ++i) { 1819261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (kCompatibleBrands[i] == fourcc) { 1820261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return true; 1821261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1822261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1823261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1824261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 1825261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber} 1826261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1827261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber// Attempt to actually parse the 'ftyp' atom and determine if a suitable 1828261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber// compatible brand is present. 1829261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberstatic bool BetterSniffMPEG4( 1830261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 1831261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber uint8_t header[12]; 1832261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (source->readAt(0, header, 12) != 12 1833261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber || memcmp("ftyp", &header[4], 4)) { 1834261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 1835261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1836261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1837261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber size_t atomSize = U32_AT(&header[0]); 1838261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (atomSize < 16 || (atomSize % 4) != 0) { 1839261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 1840261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1841261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1842261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber bool success = false; 1843261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (isCompatibleBrand(U32_AT(&header[8]))) { 1844261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber success = true; 1845261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } else { 1846261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber size_t numCompatibleBrands = (atomSize - 16) / 4; 1847261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber for (size_t i = 0; i < numCompatibleBrands; ++i) { 1848261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber uint8_t tmp[4]; 1849261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (source->readAt(16 + i * 4, tmp, 4) != 4) { 1850261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 1851261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1852261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1853261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (isCompatibleBrand(U32_AT(&tmp[0]))) { 1854261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber success = true; 1855261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber break; 1856261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1857261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1858261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1859261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1860261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (!success) { 1861261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 1862261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1863261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1864261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4; 1865efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber *confidence = 0.4f; 1866261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1867261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return true; 1868261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber} 1869261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1870261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huberbool SniffMPEG4( 1871efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 1872efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber sp<AMessage> *) { 1873261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (BetterSniffMPEG4(source, mimeType, confidence)) { 1874261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return true; 1875261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1876261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1877261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber if (LegacySniffMPEG4(source, mimeType, confidence)) { 1878261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber LOGW("Identified supported mpeg4 through LegacySniffMPEG4."); 1879261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return true; 1880261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber } 1881261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1882261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber return false; 1883261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber} 1884261eb0cbef1f3f7d3cde49d628b9c1e82dabcb76Andreas Huber 1885e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber} // namespace android 1886e46b7be812d68e49710b34048662cbf18e2a6550Andreas Huber 1887