AVIExtractor.cpp revision 3001e4721237af2754fc2ac57100dd4ea00c67cb
1cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber/* 2cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * Copyright (C) 2011 The Android Open Source Project 3cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * 4cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * you may not use this file except in compliance with the License. 6cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * You may obtain a copy of the License at 7cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * 8cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * 10cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * Unless required by applicable law or agreed to in writing, software 11cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * See the License for the specific language governing permissions and 14cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber * limitations under the License. 15cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber */ 16cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 17cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber//#define LOG_NDEBUG 0 18cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#define LOG_TAG "AVIExtractor" 19cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <utils/Log.h> 20cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 213001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber#include "include/avc_utils.h" 22cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include "include/AVIExtractor.h" 23cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 24cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <binder/ProcessState.h> 25cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/foundation/hexdump.h> 26cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/foundation/ABuffer.h> 27cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/foundation/ADebug.h> 28cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/DataSource.h> 29cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/MediaBuffer.h> 30cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/MediaBufferGroup.h> 31cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/MediaDefs.h> 32cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/MediaErrors.h> 33cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/MetaData.h> 34cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber#include <media/stagefright/Utils.h> 35cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 36cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubernamespace android { 37cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 38cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstruct AVIExtractor::AVISource : public MediaSource { 39cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber AVISource(const sp<AVIExtractor> &extractor, size_t trackIndex); 40cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 41cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber virtual status_t start(MetaData *params); 42cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber virtual status_t stop(); 43cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 44cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber virtual sp<MetaData> getFormat(); 45cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 46cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber virtual status_t read( 47cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber MediaBuffer **buffer, const ReadOptions *options); 48cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 49cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberprotected: 50cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber virtual ~AVISource(); 51cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 52cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberprivate: 53cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber sp<AVIExtractor> mExtractor; 54cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t mTrackIndex; 55cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const AVIExtractor::Track &mTrack; 56cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber MediaBufferGroup *mBufferGroup; 57cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t mSampleIndex; 58cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 59cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber DISALLOW_EVIL_CONSTRUCTORS(AVISource); 60cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber}; 61cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 62cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber//////////////////////////////////////////////////////////////////////////////// 63cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 64cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::AVISource::AVISource( 65cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const sp<AVIExtractor> &extractor, size_t trackIndex) 66cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber : mExtractor(extractor), 67cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mTrackIndex(trackIndex), 68cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mTrack(mExtractor->mTracks.itemAt(trackIndex)), 69cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mBufferGroup(NULL) { 70cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 71cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 72cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::AVISource::~AVISource() { 73cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (mBufferGroup) { 74cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber stop(); 75cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 76cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 77cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 78cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::AVISource::start(MetaData *params) { 79cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber CHECK(!mBufferGroup); 80cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 81cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mBufferGroup = new MediaBufferGroup; 82cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 83cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize)); 84cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize)); 85cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mSampleIndex = 0; 86cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 87cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 88cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 89cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 90cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::AVISource::stop() { 91cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber CHECK(mBufferGroup); 92cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 93cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber delete mBufferGroup; 94cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mBufferGroup = NULL; 95cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 96cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 97cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 98cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 99cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MetaData> AVIExtractor::AVISource::getFormat() { 100cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return mTrack.mMeta; 101cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 102cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 103cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::AVISource::read( 104cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber MediaBuffer **buffer, const ReadOptions *options) { 105cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber CHECK(mBufferGroup); 106cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 107cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *buffer = NULL; 108cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 109cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber int64_t seekTimeUs; 110cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ReadOptions::SeekMode seekMode; 111cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &seekMode)) { 112cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber status_t err = 113cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mExtractor->getSampleIndexAtTime( 114cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mTrackIndex, seekTimeUs, seekMode, &mSampleIndex); 115cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 116cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (err != OK) { 117cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_END_OF_STREAM; 118cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 119cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 120cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 121cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber off64_t offset; 122cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t size; 123cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber bool isKey; 12463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber int64_t timeUs; 125cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber status_t err = mExtractor->getSampleInfo( 12663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs); 127cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 128cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ++mSampleIndex; 129cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 130cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (err != OK) { 131cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_END_OF_STREAM; 132cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 133cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 134cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber MediaBuffer *out; 135cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK); 136cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 137cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size); 138cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 139cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (n < (ssize_t)size) { 140cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED; 141cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 142cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 143cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber out->set_range(0, size); 144cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 145cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber out->meta_data()->setInt64(kKeyTime, timeUs); 146cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 147cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (isKey) { 148cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber out->meta_data()->setInt32(kKeyIsSyncFrame, 1); 149cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 150cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 151cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *buffer = out; 152cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 153cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 154cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 155cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 156cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber//////////////////////////////////////////////////////////////////////////////// 157cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 158cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::AVIExtractor(const sp<DataSource> &dataSource) 159cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber : mDataSource(dataSource) { 160cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mInitCheck = parseHeaders(); 161cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 162cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (mInitCheck != OK) { 163cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mTracks.clear(); 164cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 165cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 166cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 167cabb7da7125a80c55233bd23959327424e9646ccAndreas HuberAVIExtractor::~AVIExtractor() { 168cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 169cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 170cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersize_t AVIExtractor::countTracks() { 171cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return mTracks.size(); 172cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 173cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 174cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MediaSource> AVIExtractor::getTrack(size_t index) { 175cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return index < mTracks.size() ? new AVISource(this, index) : NULL; 176cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 177cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 178cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MetaData> AVIExtractor::getTrackMetaData( 179cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t index, uint32_t flags) { 180cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL; 181cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 182cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 183cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<MetaData> AVIExtractor::getMetaData() { 184cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber sp<MetaData> meta = new MetaData; 185cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 186cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (mInitCheck == OK) { 187cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI); 188cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 189cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 190cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return meta; 191cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 192cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 193cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseHeaders() { 194cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mTracks.clear(); 195cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mMovieOffset = 0; 196cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mFoundIndex = false; 197cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mOffsetsAreAbsolute = false; 198cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 199cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t res = parseChunk(0ll, -1ll); 200cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 201cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (res < 0) { 202cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return (status_t)res; 203cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 204cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 205cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (mMovieOffset == 0ll || !mFoundIndex) { 206cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 207cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 208cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 209cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 210cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 211cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 212cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) { 213cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (size >= 0 && size < 8) { 214cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 215cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 216cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 217cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint8_t tmp[12]; 218cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t n = mDataSource->readAt(offset, tmp, 8); 219cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 220cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (n < 8) { 221cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return (n < 0) ? n : (ssize_t)ERROR_MALFORMED; 222cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 223cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 224cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t fourcc = U32_AT(tmp); 225cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t chunkSize = U32LE_AT(&tmp[4]); 226cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 227cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (size >= 0 && chunkSize + 8 > size) { 228cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 229cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 230cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 231cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber static const char kPrefix[] = " "; 232cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth]; 233cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 234cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (fourcc == FOURCC('L', 'I', 'S', 'T') 235cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber || fourcc == FOURCC('R', 'I', 'F', 'F')) { 236cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber // It's a list of chunks 237cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 238cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (size >= 0 && size < 12) { 239cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 240cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 241cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 242cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber n = mDataSource->readAt(offset + 8, &tmp[8], 4); 243cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 244cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (n < 4) { 245cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return (n < 0) ? n : (ssize_t)ERROR_MALFORMED; 246cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 247cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 248cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t subFourcc = U32_AT(&tmp[8]); 249cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 250cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber LOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d", 251cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber prefix, 252cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber offset, 253cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber (char)(subFourcc >> 24), 254cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber (char)((subFourcc >> 16) & 0xff), 255cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber (char)((subFourcc >> 8) & 0xff), 256cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber (char)(subFourcc & 0xff), 257cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber chunkSize - 4); 258cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 259cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (subFourcc == FOURCC('m', 'o', 'v', 'i')) { 260cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber // We're not going to parse this, but will take note of the 261cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber // offset. 262cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 263cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mMovieOffset = offset; 264cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } else { 265cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber off64_t subOffset = offset + 12; 266cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber off64_t subOffsetLimit = subOffset + chunkSize - 4; 267cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber while (subOffset < subOffsetLimit) { 268cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t res = 269cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1); 270cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 271cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (res < 0) { 272cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return res; 273cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 274cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 275cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber subOffset += res; 276cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 277cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 278cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } else { 279cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber LOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'", 280cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber prefix, 281cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber offset, 282cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber (char)(fourcc >> 24), 283cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber (char)((fourcc >> 16) & 0xff), 284cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber (char)((fourcc >> 8) & 0xff), 285cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber (char)(fourcc & 0xff)); 286cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 287cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber status_t err = OK; 288cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 289cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber switch (fourcc) { 290cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('s', 't', 'r', 'h'): 291cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber { 292cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber err = parseStreamHeader(offset + 8, chunkSize); 293cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber break; 294cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 295cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 296cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('s', 't', 'r', 'f'): 297cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber { 298cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber err = parseStreamFormat(offset + 8, chunkSize); 299cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber break; 300cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 301cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 302cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('i', 'd', 'x', '1'): 303cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber { 304cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber err = parseIndex(offset + 8, chunkSize); 305cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber break; 306cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 307cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 308cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber default: 309cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber break; 310cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 311cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 312cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (err != OK) { 313cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return err; 314cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 315cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 316cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 317cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (chunkSize & 1) { 318cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ++chunkSize; 319cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 320cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 321cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return chunkSize + 8; 322cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 323cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 324cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatic const char *GetMIMETypeForHandler(uint32_t handler) { 325cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber switch (handler) { 326cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber // Wow... shamelessly copied from 327cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4 328cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 329cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('3', 'I', 'V', '2'): 330cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('3', 'i', 'v', '2'): 331cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('B', 'L', 'Z', '0'): 332cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('D', 'I', 'G', 'I'): 333cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('D', 'I', 'V', '1'): 334cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('d', 'i', 'v', '1'): 335cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('D', 'I', 'V', 'X'): 336cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('d', 'i', 'v', 'x'): 337cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('D', 'X', '5', '0'): 338cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('d', 'x', '5', '0'): 339cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('D', 'X', 'G', 'M'): 340cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('E', 'M', '4', 'A'): 341cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('E', 'P', 'H', 'V'): 342cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('F', 'M', 'P', '4'): 343cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('f', 'm', 'p', '4'): 344cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('F', 'V', 'F', 'W'): 345cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('H', 'D', 'X', '4'): 346cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('h', 'd', 'x', '4'): 347cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('M', '4', 'C', 'C'): 348cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('M', '4', 'S', '2'): 349cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('m', '4', 's', '2'): 350cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('M', 'P', '4', 'S'): 351cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('m', 'p', '4', 's'): 352cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('M', 'P', '4', 'V'): 353cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('m', 'p', '4', 'v'): 354cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('M', 'V', 'X', 'M'): 355cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('R', 'M', 'P', '4'): 356cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('S', 'E', 'D', 'G'): 357cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('S', 'M', 'P', '4'): 358cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('U', 'M', 'P', '4'): 359cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('W', 'V', '1', 'F'): 360cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('X', 'V', 'I', 'D'): 361cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('X', 'v', 'i', 'D'): 362cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('x', 'v', 'i', 'd'): 363cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case FOURCC('X', 'V', 'I', 'X'): 364cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return MEDIA_MIMETYPE_VIDEO_MPEG4; 365cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 3663001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber // from http://wiki.multimedia.cx/index.php?title=H264 3673001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber case FOURCC('a', 'v', 'c', '1'): 3683001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber case FOURCC('d', 'a', 'v', 'c'): 3693001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber case FOURCC('x', '2', '6', '4'): 3703001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber case FOURCC('v', 's', 's', 'h'): 3713001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber return MEDIA_MIMETYPE_VIDEO_AVC; 3723001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 373cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber default: 374cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return NULL; 375cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 376cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 377cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 378cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) { 379cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (size != 56) { 380cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 381cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 382cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 383cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (mTracks.size() > 99) { 384cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return -ERANGE; 385cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 386cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 387cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber sp<ABuffer> buffer = new ABuffer(size); 388cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 389cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 390cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (n < (ssize_t)size) { 391cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return n < 0 ? (status_t)n : ERROR_MALFORMED; 392cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 393cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 394cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const uint8_t *data = buffer->data(); 395cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 396cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t type = U32_AT(data); 397cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t handler = U32_AT(&data[4]); 398cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t flags = U32LE_AT(&data[8]); 399cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 400cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber sp<MetaData> meta = new MetaData; 401cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 402cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t rate = U32LE_AT(&data[20]); 403cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t scale = U32LE_AT(&data[24]); 404cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 40563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber uint32_t sampleSize = U32LE_AT(&data[44]); 40663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber 407cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const char *mime = NULL; 408cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber Track::Kind kind = Track::OTHER; 409cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 410cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (type == FOURCC('v', 'i', 'd', 's')) { 411cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mime = GetMIMETypeForHandler(handler); 412cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 413cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (mime && strncasecmp(mime, "video/", 6)) { 414cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 415cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 416cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 4173001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber if (mime == NULL) { 4183001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber LOGW("Unsupported video format '%c%c%c%c'", 4193001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber (char)(handler >> 24), 4203001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber (char)((handler >> 16) & 0xff), 4213001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber (char)((handler >> 8) & 0xff), 4223001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber (char)(handler & 0xff)); 4233001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber } 4243001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 425cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber kind = Track::VIDEO; 426cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } else if (type == FOURCC('a', 'u', 'd', 's')) { 427cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (mime && strncasecmp(mime, "audio/", 6)) { 428cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 429cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 430cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 431cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber kind = Track::AUDIO; 432cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 433cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 434cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (!mime) { 435cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mime = "application/octet-stream"; 436cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 437cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 438cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber meta->setCString(kKeyMIMEType, mime); 439cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 440cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mTracks.push(); 441cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber Track *track = &mTracks.editItemAt(mTracks.size() - 1); 442cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 443cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mMeta = meta; 444cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mRate = rate; 445cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mScale = scale; 44663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber track->mBytesPerSample = sampleSize; 447cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mKind = kind; 448cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mNumSyncSamples = 0; 449cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mThumbnailSampleSize = 0; 450cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mThumbnailSampleIndex = -1; 451cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mMaxSampleSize = 0; 452cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 453cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 454cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 455cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 456cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) { 457cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (mTracks.isEmpty()) { 458cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 459cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 460cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 461cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber Track *track = &mTracks.editItemAt(mTracks.size() - 1); 462cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 463cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (track->mKind == Track::OTHER) { 464cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber // We don't support this content, but that's not a parsing error. 465cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 466cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 467cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 468cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber bool isVideo = (track->mKind == Track::VIDEO); 469cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 470cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if ((isVideo && size < 40) || (!isVideo && size < 18)) { 471cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber // Expected a BITMAPINFO or WAVEFORMATEX structure, respectively. 472cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 473cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 474cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 475cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber sp<ABuffer> buffer = new ABuffer(size); 476cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 477cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 478cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (n < (ssize_t)size) { 479cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return n < 0 ? (status_t)n : ERROR_MALFORMED; 480cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 481cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 482cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const uint8_t *data = buffer->data(); 483cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 484cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (isVideo) { 485cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t width = U32LE_AT(&data[4]); 486cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t height = U32LE_AT(&data[8]); 487cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 488cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mMeta->setInt32(kKeyWidth, width); 489cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mMeta->setInt32(kKeyHeight, height); 490cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } else { 491cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t format = U16LE_AT(data); 4923001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 493cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (format == 0x55) { 494cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); 4953001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber } else { 4963001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber LOGW("Unsupported audio format = 0x%04x", format); 497cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 498cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 499cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t numChannels = U16LE_AT(&data[2]); 500cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t sampleRate = U32LE_AT(&data[4]); 501cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 502cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mMeta->setInt32(kKeyChannelCount, numChannels); 503cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mMeta->setInt32(kKeySampleRate, sampleRate); 504cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 505cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 506cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 507cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 508cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 509cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber// static 510cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberbool AVIExtractor::IsCorrectChunkType( 511cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) { 512cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t chunkBase = chunkType & 0xffff; 513cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 514cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber switch (kind) { 515cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case Track::VIDEO: 516cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber { 517cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (chunkBase != FOURCC(0, 0, 'd', 'c') 518cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber && chunkBase != FOURCC(0, 0, 'd', 'b')) { 519cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return false; 520cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 521cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber break; 522cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 523cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 524cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case Track::AUDIO: 525cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber { 526cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (chunkBase != FOURCC(0, 0, 'w', 'b')) { 527cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return false; 528cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 529cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber break; 530cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 531cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 532cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber default: 533cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber break; 534cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 535cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 536cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (trackIndex < 0) { 537cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return true; 538cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 539cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 540cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint8_t hi = chunkType >> 24; 541cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint8_t lo = (chunkType >> 16) & 0xff; 542cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 543cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (hi < '0' || hi > '9' || lo < '0' || lo > '9') { 544cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return false; 545cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 546cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 547cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (trackIndex != (10 * (hi - '0') + (lo - '0'))) { 548cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return false; 549cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 550cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 551cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return true; 552cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 553cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 554cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::parseIndex(off64_t offset, size_t size) { 555cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if ((size % 16) != 0) { 556cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 557cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 558cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 559cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber sp<ABuffer> buffer = new ABuffer(size); 560cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 561cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 562cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (n < (ssize_t)size) { 563cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return n < 0 ? (status_t)n : ERROR_MALFORMED; 564cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 565cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 566cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const uint8_t *data = buffer->data(); 567cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 568cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber while (size > 0) { 569cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t chunkType = U32_AT(data); 570cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 571cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint8_t hi = chunkType >> 24; 572cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint8_t lo = (chunkType >> 16) & 0xff; 573cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 574cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (hi < '0' || hi > '9' || lo < '0' || lo > '9') { 575cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 576cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 577cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 578cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t trackIndex = 10 * (hi - '0') + (lo - '0'); 579cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 580cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (trackIndex >= mTracks.size()) { 581cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 582cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 583cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 584cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber Track *track = &mTracks.editItemAt(trackIndex); 585cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 586cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (!IsCorrectChunkType(-1, track->mKind, chunkType)) { 587cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 588cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 589cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 590cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (track->mKind == Track::OTHER) { 591cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber data += 16; 592cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size -= 16; 593cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber continue; 594cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 595cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 596cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t flags = U32LE_AT(&data[4]); 597cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t offset = U32LE_AT(&data[8]); 598cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t chunkSize = U32LE_AT(&data[12]); 599cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 600cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (chunkSize > track->mMaxSampleSize) { 601cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mMaxSampleSize = chunkSize; 602cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 603cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 604cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mSamples.push(); 605cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 606cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber SampleInfo *info = 607cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber &track->mSamples.editItemAt(track->mSamples.size() - 1); 608cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 609cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber info->mOffset = offset; 610cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber info->mIsKey = (flags & 0x10) != 0; 611cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 612cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (info->mIsKey) { 613cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber static const size_t kMaxNumSyncSamplesToScan = 20; 614cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 615cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) { 616cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (chunkSize > track->mThumbnailSampleSize) { 617cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mThumbnailSampleSize = chunkSize; 618cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 619cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mThumbnailSampleIndex = 620cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mSamples.size() - 1; 621cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 622cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 623cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 624cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ++track->mNumSyncSamples; 625cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 626cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 627cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber data += 16; 628cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size -= 16; 629cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 630cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 631cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (!mTracks.isEmpty()) { 632cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber off64_t offset; 633cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t size; 634cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber bool isKey; 63563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber int64_t timeUs; 63663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs); 637cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 638cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (err != OK) { 639cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mOffsetsAreAbsolute = !mOffsetsAreAbsolute; 64063749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs); 641cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 642cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (err != OK) { 643cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return err; 644cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 645cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 646cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 647cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber LOGV("Chunk offsets are %s", 648cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative"); 649cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 650cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 651cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber for (size_t i = 0; i < mTracks.size(); ++i) { 652cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber Track *track = &mTracks.editItemAt(i); 653cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 65463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber int64_t durationUs; 65563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber CHECK_EQ((status_t)OK, 65663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber getSampleTime(i, track->mSamples.size() - 1, &durationUs)); 657cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 658cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber LOGV("track %d duration = %.2f secs", i, durationUs / 1E6); 659cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 660cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mMeta->setInt64(kKeyDuration, durationUs); 661cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize); 662cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 663cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const char *tmp; 664cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp)); 665cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 666cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber AString mime = tmp; 667cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 6683001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber if (!strncasecmp("video/", mime.c_str(), 6)) { 6693001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber if (track->mThumbnailSampleIndex >= 0) { 6703001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber int64_t thumbnailTimeUs; 6713001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber CHECK_EQ((status_t)OK, 6723001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber getSampleTime(i, track->mThumbnailSampleIndex, 6733001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber &thumbnailTimeUs)); 674cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 6753001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs); 6763001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber } 6773001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 6783001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber status_t err = OK; 679cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 680cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) { 6813001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber err = addMPEG4CodecSpecificData(i); 6823001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) { 6833001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber err = addH264CodecSpecificData(i); 6843001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber } 685cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 6863001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber if (err != OK) { 6873001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber return err; 688cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 689cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 69063749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber 69163749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber if (track->mBytesPerSample != 0) { 69263749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber // Assume all chunks are the same size for now. 69363749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber 69463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber off64_t offset; 69563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber size_t size; 69663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber bool isKey; 69763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber int64_t sampleTimeUs; 69863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber CHECK_EQ((status_t)OK, 69963749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber getSampleInfo( 70063749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber i, 0, 70163749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber &offset, &size, &isKey, &sampleTimeUs)); 70263749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber 70363749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber track->mRate *= size / track->mBytesPerSample; 70463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber } 705cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 706cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 707cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mFoundIndex = true; 708cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 709cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 710cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 711cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 712cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatic size_t GetSizeWidth(size_t x) { 713cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t n = 1; 714cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber while (x > 127) { 715cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ++n; 716cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber x >>= 7; 717cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 718cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return n; 719cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 720cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 721cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatic uint8_t *EncodeSize(uint8_t *dst, size_t x) { 722cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber while (x > 127) { 723cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *dst++ = (x & 0x7f) | 0x80; 724cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber x >>= 7; 725cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 726cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *dst++ = x; 727cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return dst; 728cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 729cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 730cabb7da7125a80c55233bd23959327424e9646ccAndreas Hubersp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) { 731cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t len1 = config->size() + GetSizeWidth(config->size()) + 1; 732cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13; 733cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3; 734cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 735cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber sp<ABuffer> csd = new ABuffer(len3); 736cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint8_t *dst = csd->data(); 737cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *dst++ = 0x03; 738cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber dst = EncodeSize(dst, len2 + 3); 739cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *dst++ = 0x00; // ES_ID 740cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *dst++ = 0x00; 741cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag 742cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 743cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *dst++ = 0x04; 744cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber dst = EncodeSize(dst, len1 + 13); 745cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *dst++ = 0x01; // Video ISO/IEC 14496-2 Simple Profile 746cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber for (size_t i = 0; i < 12; ++i) { 747cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *dst++ = 0x00; 748cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 749cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 750cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *dst++ = 0x05; 751cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber dst = EncodeSize(dst, config->size()); 752cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber memcpy(dst, config->data(), config->size()); 753cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber dst += config->size(); 754cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 755cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber // hexdump(csd->data(), csd->size()); 756cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 757cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return csd; 758cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 759cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 760cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) { 761cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber Track *track = &mTracks.editItemAt(trackIndex); 762cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 763cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber off64_t offset; 764cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t size; 765cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber bool isKey; 76663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber int64_t timeUs; 76763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber status_t err = 76863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs); 769cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 770cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (err != OK) { 771cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return err; 772cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 773cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 774cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber sp<ABuffer> buffer = new ABuffer(size); 775cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 776cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 777cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (n < (ssize_t)size) { 778cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return n < 0 ? (status_t)n : ERROR_MALFORMED; 779cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 780cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 781cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber // Extract everything up to the first VOP start code from the first 782cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber // frame's encoded data and use it to construct an ESDS with the 783cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber // codec specific data. 784cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 785cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t i = 0; 786cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber bool found = false; 787cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber while (i + 3 < buffer->size()) { 788cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) { 789cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber found = true; 790cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber break; 791cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 792cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 793cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ++i; 794cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 795cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 796cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (!found) { 797cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 798cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 799cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 800cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber buffer->setRange(0, i); 801cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 802cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer); 803cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size()); 804cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 805cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 806cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 807cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 8083001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huberstatus_t AVIExtractor::addH264CodecSpecificData(size_t trackIndex) { 8093001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber Track *track = &mTracks.editItemAt(trackIndex); 8103001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8113001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber off64_t offset; 8123001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber size_t size; 8133001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber bool isKey; 8143001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber int64_t timeUs; 8153001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8163001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber // Extract codec specific data from the first non-empty sample. 8173001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8183001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber size_t sampleIndex = 0; 8193001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber for (;;) { 8203001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber status_t err = 8213001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber getSampleInfo( 8223001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber trackIndex, sampleIndex, &offset, &size, &isKey, &timeUs); 8233001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8243001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber if (err != OK) { 8253001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber return err; 8263001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber } 8273001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8283001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber if (size > 0) { 8293001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber break; 8303001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber } 8313001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8323001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber ++sampleIndex; 8333001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber } 8343001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8353001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber sp<ABuffer> buffer = new ABuffer(size); 8363001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size()); 8373001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8383001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber if (n < (ssize_t)size) { 8393001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber return n < 0 ? (status_t)n : ERROR_MALFORMED; 8403001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber } 8413001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8423001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber sp<MetaData> meta = MakeAVCCodecSpecificData(buffer); 8433001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8443001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber if (meta == NULL) { 8453001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber LOGE("Unable to extract AVC codec specific data"); 8463001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber return ERROR_MALFORMED; 8473001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber } 8483001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8493001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber int32_t width, height; 8503001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber CHECK(meta->findInt32(kKeyWidth, &width)); 8513001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber CHECK(meta->findInt32(kKeyHeight, &height)); 8523001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8533001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber uint32_t type; 8543001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber const void *csd; 8553001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber size_t csdSize; 8563001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize)); 8573001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8583001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber track->mMeta->setInt32(kKeyWidth, width); 8593001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber track->mMeta->setInt32(kKeyHeight, width); 8603001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber track->mMeta->setData(kKeyAVCC, type, csd, csdSize); 8613001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 8623001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber return OK; 8633001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber} 8643001e4721237af2754fc2ac57100dd4ea00c67cbAndreas Huber 865cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::getSampleInfo( 866cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t trackIndex, size_t sampleIndex, 86763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber off64_t *offset, size_t *size, bool *isKey, 86863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber int64_t *sampleTimeUs) { 869cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (trackIndex >= mTracks.size()) { 870cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return -ERANGE; 871cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 872cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 873cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const Track &track = mTracks.itemAt(trackIndex); 874cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 875cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (sampleIndex >= track.mSamples.size()) { 876cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return -ERANGE; 877cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 878cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 879cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const SampleInfo &info = track.mSamples.itemAt(sampleIndex); 880cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 881cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (!mOffsetsAreAbsolute) { 882cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *offset = info.mOffset + mMovieOffset + 8; 883cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } else { 884cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *offset = info.mOffset; 885cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 886cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 887cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *size = 0; 888cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 889cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint8_t tmp[8]; 890cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t n = mDataSource->readAt(*offset, tmp, 8); 891cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 892cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (n < 8) { 893cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED; 894cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 895cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 896cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber uint32_t chunkType = U32_AT(tmp); 897cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 898cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) { 899cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return ERROR_MALFORMED; 900cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 901cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 902cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *offset += 8; 903cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *size = U32LE_AT(&tmp[4]); 904cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 905cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *isKey = info.mIsKey; 906cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 90763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale; 90863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber 909cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 910cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 911cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 91263749954aa828b3f73b4738659eaea5eaeeca874Andreas Huberstatus_t AVIExtractor::getSampleTime( 91363749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) { 91463749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber off64_t offset; 91563749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber size_t size; 91663749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber bool isKey; 91763749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber return getSampleInfo( 91863749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs); 91963749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber} 92063749954aa828b3f73b4738659eaea5eaeeca874Andreas Huber 921cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberstatus_t AVIExtractor::getSampleIndexAtTime( 922cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t trackIndex, 923cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber int64_t timeUs, MediaSource::ReadOptions::SeekMode mode, 924cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t *sampleIndex) const { 925cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (trackIndex >= mTracks.size()) { 926cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return -ERANGE; 927cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 928cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 929cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const Track &track = mTracks.itemAt(trackIndex); 930cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 931cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t closestSampleIndex = 932cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber timeUs / track.mRate * track.mScale / 1000000ll; 933cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 934cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t numSamples = track.mSamples.size(); 935cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 936cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (closestSampleIndex < 0) { 937cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber closestSampleIndex = 0; 938cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } else if (closestSampleIndex >= numSamples) { 939cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber closestSampleIndex = numSamples - 1; 940cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 941cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 942cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) { 943cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *sampleIndex = closestSampleIndex; 944cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 945cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 946cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 947cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 948cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t prevSyncSampleIndex = closestSampleIndex; 949cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber while (prevSyncSampleIndex >= 0) { 950cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const SampleInfo &info = 951cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track.mSamples.itemAt(prevSyncSampleIndex); 952cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 953cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (info.mIsKey) { 954cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber break; 955cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 956cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 957cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber --prevSyncSampleIndex; 958cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 959cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 960cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ssize_t nextSyncSampleIndex = closestSampleIndex; 961cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber while (nextSyncSampleIndex < numSamples) { 962cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const SampleInfo &info = 963cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber track.mSamples.itemAt(nextSyncSampleIndex); 964cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 965cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (info.mIsKey) { 966cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber break; 967cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 968cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 969cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber ++nextSyncSampleIndex; 970cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 971cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 972cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber switch (mode) { 973cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC: 974cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber { 975cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *sampleIndex = prevSyncSampleIndex; 976cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 977cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR; 978cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 979cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 980cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case MediaSource::ReadOptions::SEEK_NEXT_SYNC: 981cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber { 982cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *sampleIndex = nextSyncSampleIndex; 983cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 984cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR; 985cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 986cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 987cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC: 988cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber { 989cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) { 990cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return UNKNOWN_ERROR; 991cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 992cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 993cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (prevSyncSampleIndex < 0) { 994cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *sampleIndex = nextSyncSampleIndex; 995cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 996cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 997cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 998cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (nextSyncSampleIndex >= numSamples) { 999cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *sampleIndex = prevSyncSampleIndex; 1000cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 1001cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 1002cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 1003cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t dist1 = closestSampleIndex - prevSyncSampleIndex; 1004cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber size_t dist2 = nextSyncSampleIndex - closestSampleIndex; 1005cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 1006cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber *sampleIndex = 1007cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex; 1008cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 1009cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return OK; 1010cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 1011cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 1012cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber default: 1013cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber TRESPASS(); 1014cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber break; 1015cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 1016cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 1017cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 1018cabb7da7125a80c55233bd23959327424e9646ccAndreas Huberbool SniffAVI( 1019cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 1020cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber sp<AMessage> *) { 1021cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber char tmp[12]; 1022cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (source->readAt(0, tmp, 12) < 12) { 1023cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return false; 1024cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 1025cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 1026cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) { 1027cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI); 1028f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber 1029f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber // Just a tad over the mp3 extractor's confidence, since 1030f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber // these .avi files may contain .mp3 content that otherwise would 1031f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber // mistakenly lead to us identifying the entire file as a .mp3 file. 1032f8c84b343488c29cc6ef224a7df751c94955e029Andreas Huber *confidence = 0.21; 1033cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 1034cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return true; 1035cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber } 1036cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 1037cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber return false; 1038cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} 1039cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber 1040cabb7da7125a80c55233bd23959327424e9646ccAndreas Huber} // namespace android 1041