AVIExtractor.cpp revision f8374dec590223ebdd6959b26d9ba90749dd8328
1f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber/* 2f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * Copyright (C) 2011 The Android Open Source Project 3f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * 4f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * you may not use this file except in compliance with the License. 6f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * You may obtain a copy of the License at 7f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * 8f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * 10f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * Unless required by applicable law or agreed to in writing, software 11f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * See the License for the specific language governing permissions and 14f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber * limitations under the License. 15f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber */ 16f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 17f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber//#define LOG_NDEBUG 0 18f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#define LOG_TAG "AVIExtractor" 19f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <utils/Log.h> 20f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 21f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include "include/AVIExtractor.h" 22f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 23f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <binder/ProcessState.h> 24f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/foundation/hexdump.h> 25f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 26f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/foundation/ADebug.h> 27f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/DataSource.h> 28f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaBuffer.h> 29f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaBufferGroup.h> 30f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaDefs.h> 31f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MediaErrors.h> 32f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/MetaData.h> 33f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber#include <media/stagefright/Utils.h> 34f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 35f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubernamespace android { 36f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 37f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstruct AVIExtractor::AVISource : public MediaSource { 38f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber AVISource(const sp<AVIExtractor> &extractor, size_t trackIndex); 39f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 40f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber virtual status_t start(MetaData *params); 41f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber virtual status_t stop(); 42f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 43f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber virtual sp<MetaData> getFormat(); 44f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 45f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber virtual status_t read( 46f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber MediaBuffer **buffer, const ReadOptions *options); 47f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 48f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberprotected: 49f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber virtual ~AVISource(); 50f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 51f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberprivate: 52f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber sp<AVIExtractor> mExtractor; 53f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t mTrackIndex; 54f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const AVIExtractor::Track &mTrack; 55f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber MediaBufferGroup *mBufferGroup; 56f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t mSampleIndex; 57f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 58f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber DISALLOW_EVIL_CONSTRUCTORS(AVISource); 59f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber}; 60f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 61f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber//////////////////////////////////////////////////////////////////////////////// 62f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 63f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::AVISource::AVISource( 64f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const sp<AVIExtractor> &extractor, size_t trackIndex) 65f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber : mExtractor(extractor), 66f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mTrackIndex(trackIndex), 67f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mTrack(mExtractor->mTracks.itemAt(trackIndex)), 68f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mBufferGroup(NULL) { 69f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 70f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 71f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::AVISource::~AVISource() { 72f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (mBufferGroup) { 73f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber stop(); 74f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 75f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 76f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 77f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::AVISource::start(MetaData *params) { 78f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber CHECK(!mBufferGroup); 79f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 80f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mBufferGroup = new MediaBufferGroup; 81f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 82f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize)); 83f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize)); 84f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mSampleIndex = 0; 85f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 86f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 87f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 88f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 89f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::AVISource::stop() { 90f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber CHECK(mBufferGroup); 91f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 92f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber delete mBufferGroup; 93f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mBufferGroup = NULL; 94f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 95f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 96f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 97f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 98f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MetaData> AVIExtractor::AVISource::getFormat() { 99f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return mTrack.mMeta; 100f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 101f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 102f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::AVISource::read( 103f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber MediaBuffer **buffer, const ReadOptions *options) { 104f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber CHECK(mBufferGroup); 105f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 106f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *buffer = NULL; 107f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 108f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber int64_t seekTimeUs; 109f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ReadOptions::SeekMode seekMode; 110f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (options && options->getSeekTo(&seekTimeUs, &seekMode)) { 111f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber status_t err = 112f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mExtractor->getSampleIndexAtTime( 113f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mTrackIndex, seekTimeUs, seekMode, &mSampleIndex); 114f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 115f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (err != OK) { 116f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_END_OF_STREAM; 117f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 118f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 119f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 120f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber int64_t timeUs = 121f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber (mSampleIndex * 1000000ll * mTrack.mRate) / mTrack.mScale; 122f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 123f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber off64_t offset; 124f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t size; 125f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber bool isKey; 126f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber status_t err = mExtractor->getSampleInfo( 127f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mTrackIndex, mSampleIndex, &offset, &size, &isKey); 128f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 129f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ++mSampleIndex; 130f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 131f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (err != OK) { 132f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_END_OF_STREAM; 133f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 134f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 135f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber MediaBuffer *out; 136f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK); 137f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 138f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size); 139f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 140f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (n < (ssize_t)size) { 141f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED; 142f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 143f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 144f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber out->set_range(0, size); 145f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 146f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber out->meta_data()->setInt64(kKeyTime, timeUs); 147f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 148f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (isKey) { 149f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber out->meta_data()->setInt32(kKeyIsSyncFrame, 1); 150f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 151f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 152f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *buffer = out; 153f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 154f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 155f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 156f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 157f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber//////////////////////////////////////////////////////////////////////////////// 158f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 159f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::AVIExtractor(const sp<DataSource> &dataSource) 160f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber : mDataSource(dataSource) { 161f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mInitCheck = parseHeaders(); 162f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 163f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (mInitCheck != OK) { 164f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mTracks.clear(); 165f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 166f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 167f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 168f8374dec590223ebdd6959b26d9ba90749dd8328Andreas HuberAVIExtractor::~AVIExtractor() { 169f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 170f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 171f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersize_t AVIExtractor::countTracks() { 172f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return mTracks.size(); 173f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 174f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 175f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MediaSource> AVIExtractor::getTrack(size_t index) { 176f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return index < mTracks.size() ? new AVISource(this, index) : NULL; 177f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 178f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 179f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MetaData> AVIExtractor::getTrackMetaData( 180f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t index, uint32_t flags) { 181f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL; 182f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 183f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 184f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<MetaData> AVIExtractor::getMetaData() { 185f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber sp<MetaData> meta = new MetaData; 186f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 187f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (mInitCheck == OK) { 188f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI); 189f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 190f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 191f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return meta; 192f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 193f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 194f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseHeaders() { 195f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mTracks.clear(); 196f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mMovieOffset = 0; 197f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mFoundIndex = false; 198f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mOffsetsAreAbsolute = false; 199f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 200f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t res = parseChunk(0ll, -1ll); 201f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 202f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (res < 0) { 203f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return (status_t)res; 204f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 205f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 206f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (mMovieOffset == 0ll || !mFoundIndex) { 207f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 208f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 209f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 210f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 211f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 212f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 213f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) { 214f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (size >= 0 && size < 8) { 215f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 216f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 217f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 218f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint8_t tmp[12]; 219f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t n = mDataSource->readAt(offset, tmp, 8); 220f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 221f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (n < 8) { 222f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return (n < 0) ? n : (ssize_t)ERROR_MALFORMED; 223f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 224f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 225f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t fourcc = U32_AT(tmp); 226f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t chunkSize = U32LE_AT(&tmp[4]); 227f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 228f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (size >= 0 && chunkSize + 8 > size) { 229f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 230f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 231f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 232f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber static const char kPrefix[] = " "; 233f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth]; 234f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 235f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (fourcc == FOURCC('L', 'I', 'S', 'T') 236f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber || fourcc == FOURCC('R', 'I', 'F', 'F')) { 237f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber // It's a list of chunks 238f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 239f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (size >= 0 && size < 12) { 240f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 241f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 242f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 243f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber n = mDataSource->readAt(offset + 8, &tmp[8], 4); 244f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 245f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (n < 4) { 246f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return (n < 0) ? n : (ssize_t)ERROR_MALFORMED; 247f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 248f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 249f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t subFourcc = U32_AT(&tmp[8]); 250f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 251f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber LOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d", 252f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber prefix, 253f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber offset, 254f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber (char)(subFourcc >> 24), 255f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber (char)((subFourcc >> 16) & 0xff), 256f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber (char)((subFourcc >> 8) & 0xff), 257f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber (char)(subFourcc & 0xff), 258f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber chunkSize - 4); 259f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 260f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (subFourcc == FOURCC('m', 'o', 'v', 'i')) { 261f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber // We're not going to parse this, but will take note of the 262f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber // offset. 263f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 264f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mMovieOffset = offset; 265f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } else { 266f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber off64_t subOffset = offset + 12; 267f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber off64_t subOffsetLimit = subOffset + chunkSize - 4; 268f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber while (subOffset < subOffsetLimit) { 269f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t res = 270f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1); 271f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 272f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (res < 0) { 273f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return res; 274f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 275f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 276f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber subOffset += res; 277f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 278f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 279f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } else { 280f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber LOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'", 281f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber prefix, 282f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber offset, 283f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber (char)(fourcc >> 24), 284f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber (char)((fourcc >> 16) & 0xff), 285f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber (char)((fourcc >> 8) & 0xff), 286f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber (char)(fourcc & 0xff)); 287f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 288f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber status_t err = OK; 289f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 290f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber switch (fourcc) { 291f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('s', 't', 'r', 'h'): 292f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber { 293f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber err = parseStreamHeader(offset + 8, chunkSize); 294f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber break; 295f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 296f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 297f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('s', 't', 'r', 'f'): 298f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber { 299f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber err = parseStreamFormat(offset + 8, chunkSize); 300f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber break; 301f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 302f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 303f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('i', 'd', 'x', '1'): 304f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber { 305f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber err = parseIndex(offset + 8, chunkSize); 306f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber break; 307f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 308f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 309f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber default: 310f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber break; 311f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 312f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 313f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (err != OK) { 314f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return err; 315f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 316f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 317f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 318f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (chunkSize & 1) { 319f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ++chunkSize; 320f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 321f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 322f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return chunkSize + 8; 323f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 324f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 325f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatic const char *GetMIMETypeForHandler(uint32_t handler) { 326f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber switch (handler) { 327f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber // Wow... shamelessly copied from 328f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4 329f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 330f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('3', 'I', 'V', '2'): 331f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('3', 'i', 'v', '2'): 332f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('B', 'L', 'Z', '0'): 333f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('D', 'I', 'G', 'I'): 334f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('D', 'I', 'V', '1'): 335f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('d', 'i', 'v', '1'): 336f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('D', 'I', 'V', 'X'): 337f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('d', 'i', 'v', 'x'): 338f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('D', 'X', '5', '0'): 339f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('d', 'x', '5', '0'): 340f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('D', 'X', 'G', 'M'): 341f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('E', 'M', '4', 'A'): 342f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('E', 'P', 'H', 'V'): 343f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('F', 'M', 'P', '4'): 344f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('f', 'm', 'p', '4'): 345f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('F', 'V', 'F', 'W'): 346f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('H', 'D', 'X', '4'): 347f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('h', 'd', 'x', '4'): 348f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('M', '4', 'C', 'C'): 349f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('M', '4', 'S', '2'): 350f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('m', '4', 's', '2'): 351f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('M', 'P', '4', 'S'): 352f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('m', 'p', '4', 's'): 353f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('M', 'P', '4', 'V'): 354f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('m', 'p', '4', 'v'): 355f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('M', 'V', 'X', 'M'): 356f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('R', 'M', 'P', '4'): 357f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('S', 'E', 'D', 'G'): 358f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('S', 'M', 'P', '4'): 359f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('U', 'M', 'P', '4'): 360f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('W', 'V', '1', 'F'): 361f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('X', 'V', 'I', 'D'): 362f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('X', 'v', 'i', 'D'): 363f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('x', 'v', 'i', 'd'): 364f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case FOURCC('X', 'V', 'I', 'X'): 365f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return MEDIA_MIMETYPE_VIDEO_MPEG4; 366f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 367f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber default: 368f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return NULL; 369f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 370f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 371f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 372f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) { 373f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (size != 56) { 374f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 375f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 376f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 377f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (mTracks.size() > 99) { 378f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return -ERANGE; 379f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 380f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 381f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber sp<ABuffer> buffer = new ABuffer(size); 382f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 383f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 384f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (n < (ssize_t)size) { 385f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return n < 0 ? (status_t)n : ERROR_MALFORMED; 386f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 387f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 388f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const uint8_t *data = buffer->data(); 389f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 390f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t type = U32_AT(data); 391f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t handler = U32_AT(&data[4]); 392f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t flags = U32LE_AT(&data[8]); 393f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 394f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber sp<MetaData> meta = new MetaData; 395f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 396f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t rate = U32LE_AT(&data[20]); 397f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t scale = U32LE_AT(&data[24]); 398f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 399f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const char *mime = NULL; 400f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber Track::Kind kind = Track::OTHER; 401f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 402f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (type == FOURCC('v', 'i', 'd', 's')) { 403f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mime = GetMIMETypeForHandler(handler); 404f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 405f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (mime && strncasecmp(mime, "video/", 6)) { 406f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 407f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 408f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 409f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber kind = Track::VIDEO; 410f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } else if (type == FOURCC('a', 'u', 'd', 's')) { 411f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (mime && strncasecmp(mime, "audio/", 6)) { 412f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 413f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 414f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 415f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber kind = Track::AUDIO; 416f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 417f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 418f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (!mime) { 419f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mime = "application/octet-stream"; 420f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 421f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 422f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber meta->setCString(kKeyMIMEType, mime); 423f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 424f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mTracks.push(); 425f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber Track *track = &mTracks.editItemAt(mTracks.size() - 1); 426f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 427f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mMeta = meta; 428f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mRate = rate; 429f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mScale = scale; 430f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mKind = kind; 431f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mNumSyncSamples = 0; 432f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mThumbnailSampleSize = 0; 433f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mThumbnailSampleIndex = -1; 434f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mMaxSampleSize = 0; 435f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 436f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 437f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 438f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 439f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) { 440f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (mTracks.isEmpty()) { 441f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 442f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 443f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 444f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber Track *track = &mTracks.editItemAt(mTracks.size() - 1); 445f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 446f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (track->mKind == Track::OTHER) { 447f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber // We don't support this content, but that's not a parsing error. 448f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 449f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 450f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 451f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber bool isVideo = (track->mKind == Track::VIDEO); 452f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 453f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if ((isVideo && size < 40) || (!isVideo && size < 18)) { 454f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber // Expected a BITMAPINFO or WAVEFORMATEX structure, respectively. 455f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 456f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 457f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 458f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber sp<ABuffer> buffer = new ABuffer(size); 459f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 460f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 461f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (n < (ssize_t)size) { 462f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return n < 0 ? (status_t)n : ERROR_MALFORMED; 463f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 464f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 465f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const uint8_t *data = buffer->data(); 466f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 467f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (isVideo) { 468f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t width = U32LE_AT(&data[4]); 469f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t height = U32LE_AT(&data[8]); 470f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 471f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mMeta->setInt32(kKeyWidth, width); 472f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mMeta->setInt32(kKeyHeight, height); 473f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } else { 474f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t format = U16LE_AT(data); 475f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (format == 0x55) { 476f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 477f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 478f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 479f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t numChannels = U16LE_AT(&data[2]); 480f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t sampleRate = U32LE_AT(&data[4]); 481f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 482f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mMeta->setInt32(kKeyChannelCount, numChannels); 483f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mMeta->setInt32(kKeySampleRate, sampleRate); 484f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 485f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 486f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 487f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 488f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 489f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber// static 490f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberbool AVIExtractor::IsCorrectChunkType( 491f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) { 492f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t chunkBase = chunkType & 0xffff; 493f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 494f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber switch (kind) { 495f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case Track::VIDEO: 496f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber { 497f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (chunkBase != FOURCC(0, 0, 'd', 'c') 498f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber && chunkBase != FOURCC(0, 0, 'd', 'b')) { 499f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return false; 500f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 501f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber break; 502f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 503f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 504f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case Track::AUDIO: 505f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber { 506f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (chunkBase != FOURCC(0, 0, 'w', 'b')) { 507f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return false; 508f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 509f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber break; 510f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 511f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 512f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber default: 513f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber break; 514f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 515f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 516f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (trackIndex < 0) { 517f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return true; 518f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 519f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 520f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint8_t hi = chunkType >> 24; 521f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint8_t lo = (chunkType >> 16) & 0xff; 522f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 523f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (hi < '0' || hi > '9' || lo < '0' || lo > '9') { 524f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return false; 525f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 526f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 527f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (trackIndex != (10 * (hi - '0') + (lo - '0'))) { 528f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return false; 529f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 530f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 531f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return true; 532f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 533f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 534f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::parseIndex(off64_t offset, size_t size) { 535f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if ((size % 16) != 0) { 536f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 537f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 538f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 539f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber sp<ABuffer> buffer = new ABuffer(size); 540f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 541f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 542f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (n < (ssize_t)size) { 543f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return n < 0 ? (status_t)n : ERROR_MALFORMED; 544f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 545f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 546f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const uint8_t *data = buffer->data(); 547f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 548f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber while (size > 0) { 549f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t chunkType = U32_AT(data); 550f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 551f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint8_t hi = chunkType >> 24; 552f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint8_t lo = (chunkType >> 16) & 0xff; 553f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 554f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (hi < '0' || hi > '9' || lo < '0' || lo > '9') { 555f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 556f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 557f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 558f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t trackIndex = 10 * (hi - '0') + (lo - '0'); 559f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 560f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (trackIndex >= mTracks.size()) { 561f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 562f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 563f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 564f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber Track *track = &mTracks.editItemAt(trackIndex); 565f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 566f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (!IsCorrectChunkType(-1, track->mKind, chunkType)) { 567f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 568f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 569f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 570f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (track->mKind == Track::OTHER) { 571f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber data += 16; 572f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size -= 16; 573f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber continue; 574f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 575f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 576f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t flags = U32LE_AT(&data[4]); 577f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t offset = U32LE_AT(&data[8]); 578f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t chunkSize = U32LE_AT(&data[12]); 579f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 580f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (chunkSize > track->mMaxSampleSize) { 581f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mMaxSampleSize = chunkSize; 582f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 583f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 584f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mSamples.push(); 585f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 586f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber SampleInfo *info = 587f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber &track->mSamples.editItemAt(track->mSamples.size() - 1); 588f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 589f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber info->mOffset = offset; 590f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber info->mIsKey = (flags & 0x10) != 0; 591f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 592f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (info->mIsKey) { 593f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber static const size_t kMaxNumSyncSamplesToScan = 20; 594f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 595f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) { 596f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (chunkSize > track->mThumbnailSampleSize) { 597f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mThumbnailSampleSize = chunkSize; 598f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 599f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mThumbnailSampleIndex = 600f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mSamples.size() - 1; 601f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 602f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 603f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 604f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ++track->mNumSyncSamples; 605f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 606f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 607f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber data += 16; 608f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size -= 16; 609f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 610f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 611f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (!mTracks.isEmpty()) { 612f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber off64_t offset; 613f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t size; 614f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber bool isKey; 615f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber status_t err = getSampleInfo(0, 0, &offset, &size, &isKey); 616f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 617f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (err != OK) { 618f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mOffsetsAreAbsolute = !mOffsetsAreAbsolute; 619f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber err = getSampleInfo(0, 0, &offset, &size, &isKey); 620f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 621f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (err != OK) { 622f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return err; 623f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 624f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 625f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 626f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber LOGV("Chunk offsets are %s", 627f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative"); 628f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 629f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 630f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 631f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber Track *track = &mTracks.editItemAt(i); 632f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 633f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber int64_t durationUs = 634f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber (track->mSamples.size() * 1000000ll * track->mRate) / track->mScale; 635f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 636f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber LOGV("track %d duration = %.2f secs", i, durationUs / 1E6); 637f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 638f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mMeta->setInt64(kKeyDuration, durationUs); 639f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize); 640f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 641f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const char *tmp; 642f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp)); 643f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 644f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber AString mime = tmp; 645f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 646f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (!strncasecmp("video/", mime.c_str(), 6) 647f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber && track->mThumbnailSampleIndex >= 0) { 648f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber int64_t thumbnailTimeUs = 649f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber (track->mThumbnailSampleIndex * 1000000ll * track->mRate) 650f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber / track->mScale; 651f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 652f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 653f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 654f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) { 655f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber status_t err = addMPEG4CodecSpecificData(i); 656f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 657f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (err != OK) { 658f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return err; 659f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 660f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 661f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 662f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 663f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 664f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mFoundIndex = true; 665f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 666f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 667f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 668f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 669f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatic size_t GetSizeWidth(size_t x) { 670f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t n = 1; 671f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber while (x > 127) { 672f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ++n; 673f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber x >>= 7; 674f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 675f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return n; 676f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 677f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 678f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatic uint8_t *EncodeSize(uint8_t *dst, size_t x) { 679f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber while (x > 127) { 680f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *dst++ = (x & 0x7f) | 0x80; 681f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber x >>= 7; 682f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 683f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *dst++ = x; 684f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return dst; 685f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 686f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 687f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Hubersp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) { 688f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t len1 = config->size() + GetSizeWidth(config->size()) + 1; 689f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13; 690f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3; 691f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 692f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber sp<ABuffer> csd = new ABuffer(len3); 693f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint8_t *dst = csd->data(); 694f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *dst++ = 0x03; 695f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber dst = EncodeSize(dst, len2 + 3); 696f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *dst++ = 0x00; // ES_ID 697f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *dst++ = 0x00; 698f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 699f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 700f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *dst++ = 0x04; 701f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber dst = EncodeSize(dst, len1 + 13); 702f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *dst++ = 0x01; // Video ISO/IEC 14496-2 Simple Profile 703f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber for (size_t i = 0; i < 12; ++i) { 704f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *dst++ = 0x00; 705f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 706f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 707f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *dst++ = 0x05; 708f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber dst = EncodeSize(dst, config->size()); 709f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber memcpy(dst, config->data(), config->size()); 710f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber dst += config->size(); 711f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 712f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber // hexdump(csd->data(), csd->size()); 713f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 714f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return csd; 715f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 716f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 717f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) { 718f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber Track *track = &mTracks.editItemAt(trackIndex); 719f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 720f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber off64_t offset; 721f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t size; 722f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber bool isKey; 723f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber status_t err = getSampleInfo(trackIndex, 0, &offset, &size, &isKey); 724f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 725f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (err != OK) { 726f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return err; 727f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 728f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 729f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber sp<ABuffer> buffer = new ABuffer(size); 730f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 731f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 732f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (n < (ssize_t)size) { 733f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return n < 0 ? (status_t)n : ERROR_MALFORMED; 734f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 735f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 736f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber // Extract everything up to the first VOP start code from the first 737f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber // frame's encoded data and use it to construct an ESDS with the 738f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber // codec specific data. 739f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 740f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t i = 0; 741f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber bool found = false; 742f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber while (i + 3 < buffer->size()) { 743f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) { 744f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber found = true; 745f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber break; 746f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 747f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 748f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ++i; 749f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 750f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 751f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (!found) { 752f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 753f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 754f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 755f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber buffer->setRange(0, i); 756f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 757f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer); 758f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size()); 759f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 760f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 761f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 762f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 763f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::getSampleInfo( 764f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t trackIndex, size_t sampleIndex, 765f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber off64_t *offset, size_t *size, bool *isKey) { 766f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (trackIndex >= mTracks.size()) { 767f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return -ERANGE; 768f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 769f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 770f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const Track &track = mTracks.itemAt(trackIndex); 771f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 772f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (sampleIndex >= track.mSamples.size()) { 773f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return -ERANGE; 774f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 775f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 776f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const SampleInfo &info = track.mSamples.itemAt(sampleIndex); 777f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 778f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (!mOffsetsAreAbsolute) { 779f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *offset = info.mOffset + mMovieOffset + 8; 780f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } else { 781f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *offset = info.mOffset; 782f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 783f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 784f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *size = 0; 785f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 786f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint8_t tmp[8]; 787f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t n = mDataSource->readAt(*offset, tmp, 8); 788f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 789f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (n < 8) { 790f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED; 791f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 792f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 793f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber uint32_t chunkType = U32_AT(tmp); 794f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 795f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) { 796f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return ERROR_MALFORMED; 797f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 798f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 799f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *offset += 8; 800f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *size = U32LE_AT(&tmp[4]); 801f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 802f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *isKey = info.mIsKey; 803f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 804f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 805f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 806f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 807f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberstatus_t AVIExtractor::getSampleIndexAtTime( 808f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t trackIndex, 809f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber int64_t timeUs, MediaSource::ReadOptions::SeekMode mode, 810f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t *sampleIndex) const { 811f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (trackIndex >= mTracks.size()) { 812f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return -ERANGE; 813f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 814f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 815f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const Track &track = mTracks.itemAt(trackIndex); 816f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 817f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t closestSampleIndex = 818f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber timeUs / track.mRate * track.mScale / 1000000ll; 819f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 820f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t numSamples = track.mSamples.size(); 821f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 822f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (closestSampleIndex < 0) { 823f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber closestSampleIndex = 0; 824f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } else if (closestSampleIndex >= numSamples) { 825f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber closestSampleIndex = numSamples - 1; 826f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 827f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 828f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) { 829f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *sampleIndex = closestSampleIndex; 830f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 831f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 832f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 833f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 834f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t prevSyncSampleIndex = closestSampleIndex; 835f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber while (prevSyncSampleIndex >= 0) { 836f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const SampleInfo &info = 837f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track.mSamples.itemAt(prevSyncSampleIndex); 838f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 839f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (info.mIsKey) { 840f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber break; 841f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 842f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 843f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber --prevSyncSampleIndex; 844f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 845f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 846f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ssize_t nextSyncSampleIndex = closestSampleIndex; 847f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber while (nextSyncSampleIndex < numSamples) { 848f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const SampleInfo &info = 849f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber track.mSamples.itemAt(nextSyncSampleIndex); 850f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 851f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (info.mIsKey) { 852f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber break; 853f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 854f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 855f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber ++nextSyncSampleIndex; 856f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 857f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 858f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber switch (mode) { 859f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC: 860f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber { 861f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *sampleIndex = prevSyncSampleIndex; 862f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 863f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR; 864f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 865f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 866f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case MediaSource::ReadOptions::SEEK_NEXT_SYNC: 867f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber { 868f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *sampleIndex = nextSyncSampleIndex; 869f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 870f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR; 871f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 872f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 873f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC: 874f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber { 875f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) { 876f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return UNKNOWN_ERROR; 877f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 878f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 879f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (prevSyncSampleIndex < 0) { 880f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *sampleIndex = nextSyncSampleIndex; 881f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 882f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 883f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 884f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (nextSyncSampleIndex >= numSamples) { 885f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *sampleIndex = prevSyncSampleIndex; 886f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 887f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 888f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 889f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t dist1 = closestSampleIndex - prevSyncSampleIndex; 890f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber size_t dist2 = nextSyncSampleIndex - closestSampleIndex; 891f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 892f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *sampleIndex = 893f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex; 894f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 895f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return OK; 896f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 897f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 898f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber default: 899f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber TRESPASS(); 900f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber break; 901f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 902f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 903f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 904f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huberbool SniffAVI( 905f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 906f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber sp<AMessage> *) { 907f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber char tmp[12]; 908f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (source->readAt(0, tmp, 12) < 12) { 909f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return false; 910f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 911f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 912f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) { 913f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI); 914f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber *confidence = 0.2; 915f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 916f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return true; 917f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber } 918f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 919f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber return false; 920f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} 921f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber 922f8374dec590223ebdd6959b26d9ba90749dd8328Andreas Huber} // namespace android 923