OggExtractor.cpp revision f1d5aa162c02a16b7195a43a9bcea4d592600ac4
1ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber/* 2ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * Copyright (C) 2010 The Android Open Source Project 3ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * 4ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * you may not use this file except in compliance with the License. 6ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * You may obtain a copy of the License at 7ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * 8ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * 10ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * Unless required by applicable law or agreed to in writing, software 11ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * See the License for the specific language governing permissions and 14ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber * limitations under the License. 15ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber */ 16ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 17ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//#define LOG_NDEBUG 0 18ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#define LOG_TAG "OggExtractor" 19ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <utils/Log.h> 20ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 21ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include "include/OggExtractor.h" 22ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 23ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <cutils/properties.h> 24f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h> 25ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/DataSource.h> 26ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaBuffer.h> 27ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaBufferGroup.h> 28ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaDefs.h> 29ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaErrors.h> 30ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaSource.h> 31ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MetaData.h> 32ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/Utils.h> 33ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <utils/String8.h> 34ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 35ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberextern "C" { 36ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber #include <Tremolo/codec_internal.h> 37ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 38ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb); 39ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb); 40ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb); 41ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 42ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 43ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubernamespace android { 44ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 45ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstruct OggSource : public MediaSource { 46ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber OggSource(const sp<OggExtractor> &extractor); 47ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 48ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber virtual sp<MetaData> getFormat(); 49ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 50ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber virtual status_t start(MetaData *params = NULL); 51ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber virtual status_t stop(); 52ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 53ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber virtual status_t read( 54ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 55ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 56ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberprotected: 57ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber virtual ~OggSource(); 58ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 59ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberprivate: 60ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sp<OggExtractor> mExtractor; 61ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber bool mStarted; 62ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 63ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber OggSource(const OggSource &); 64ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber OggSource &operator=(const OggSource &); 65ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}; 66ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 67ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstruct MyVorbisExtractor { 68ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MyVorbisExtractor(const sp<DataSource> &source); 69ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber virtual ~MyVorbisExtractor(); 70ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 71ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sp<MetaData> getFormat() const; 72ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 73ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // Returns an approximate bitrate in bits per second. 74ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint64_t approxBitrate(); 75ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 763fd91baee812919f53a85c5c05f32606313f8334Andreas Huber status_t seekToTime(int64_t timeUs); 77c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong status_t seekToOffset(off64_t offset); 78ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t readNextPacket(MediaBuffer **buffer); 79ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 805a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber status_t init(); 81ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber sp<MetaData> getFileMetaData() { return mFileMeta; } 834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 84ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberprivate: 85ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber struct Page { 86ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint64_t mGranulePosition; 87ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint32_t mSerialNo; 88ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint32_t mPageNo; 89ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t mFlags; 90ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t mNumSegments; 91ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t mLace[255]; 92ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber }; 93ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 943fd91baee812919f53a85c5c05f32606313f8334Andreas Huber struct TOCEntry { 953fd91baee812919f53a85c5c05f32606313f8334Andreas Huber off64_t mPageOffset; 963fd91baee812919f53a85c5c05f32606313f8334Andreas Huber int64_t mTimeUs; 973fd91baee812919f53a85c5c05f32606313f8334Andreas Huber }; 983fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 99ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sp<DataSource> mSource; 100c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t mOffset; 101ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber Page mCurrentPage; 102db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber uint64_t mPrevGranulePosition; 103ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t mCurrentPageSize; 104db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber bool mFirstPacketInPage; 105db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber uint64_t mCurrentPageSamples; 106ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t mNextLaceIndex; 107ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 108c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t mFirstDataOffset; 10996f52cde23982f668592418a9548045237d5e327Andreas Huber 110ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber vorbis_info mVi; 111ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber vorbis_comment mVc; 112ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 113ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sp<MetaData> mMeta; 1144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber sp<MetaData> mFileMeta; 115ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1163fd91baee812919f53a85c5c05f32606313f8334Andreas Huber Vector<TOCEntry> mTableOfContents; 1173fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 118c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ssize_t readPage(off64_t offset, Page *page); 119c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong status_t findNextPage(off64_t startOffset, off64_t *pageOffset); 120ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1215a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber status_t verifyHeader( 122ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer, uint8_t type); 123ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber void parseFileMetaData(); 1254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1263fd91baee812919f53a85c5c05f32606313f8334Andreas Huber status_t findPrevGranulePosition(off64_t pageOffset, uint64_t *granulePos); 1273fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 1283fd91baee812919f53a85c5c05f32606313f8334Andreas Huber void buildTableOfContents(); 129db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 130ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MyVorbisExtractor(const MyVorbisExtractor &); 131ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MyVorbisExtractor &operator=(const MyVorbisExtractor &); 132ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}; 133ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 134856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt( 135856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const sp<MetaData> &fileMeta, const void *data, size_t size); 136856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten 137ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 138ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 139ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor) 140ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mExtractor(extractor), 141ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted(false) { 142ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 143ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 144ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::~OggSource() { 145ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mStarted) { 146ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber stop(); 147ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 148ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 149ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 150ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggSource::getFormat() { 151ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mExtractor->mImpl->getFormat(); 152ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 153ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 154ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::start(MetaData *params) { 155ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mStarted) { 156ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return INVALID_OPERATION; 157ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 158ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 159ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted = true; 160ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 161ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 162ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 163ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 164ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::stop() { 165ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted = false; 166ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 167ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 168ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 169ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 170ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::read( 171ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer **out, const ReadOptions *options) { 172ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = NULL; 173ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 174ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t seekTimeUs; 175abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 176abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 1773fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (mExtractor->mImpl->seekToTime(seekTimeUs) != OK) { 178ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_END_OF_STREAM; 179ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 180ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 181ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 182ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *packet; 183ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t err = mExtractor->mImpl->readNextPacket(&packet); 184ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 185ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (err != OK) { 186ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return err; 187ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 188ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 189ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0 190ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t timeUs; 191ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) { 192df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("found time = %lld us", timeUs); 193ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } else { 194df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("NO time"); 195ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 196ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif 197ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1988bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber packet->meta_data()->setInt32(kKeyIsSyncFrame, 1); 1998bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 200ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = packet; 201ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 202ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 203ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 204ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 205ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 206ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 207ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberMyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source) 208ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mSource(source), 209ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset(0), 210db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mPrevGranulePosition(0), 211ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize(0), 212db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage(true), 213db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPageSamples(0), 21496f52cde23982f668592418a9548045237d5e327Andreas Huber mNextLaceIndex(0), 21596f52cde23982f668592418a9548045237d5e327Andreas Huber mFirstDataOffset(-1) { 216ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPage.mNumSegments = 0; 2174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 2184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_info_init(&mVi); 2194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_comment_init(&mVc); 220ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 221ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 222ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberMyVorbisExtractor::~MyVorbisExtractor() { 2234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_comment_clear(&mVc); 2244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_info_clear(&mVi); 225ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 226ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 227ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> MyVorbisExtractor::getFormat() const { 228ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mMeta; 229ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 230ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 231ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::findNextPage( 232c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t startOffset, off64_t *pageOffset) { 233ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset = startOffset; 234ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 235ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (;;) { 236ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char signature[4]; 237ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = mSource->readAt(*pageOffset, &signature, 4); 238ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 239ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n < 4) { 240ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset = 0; 241ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 242ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM; 243ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 244ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 245ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (!memcmp(signature, "OggS", 4)) { 246ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (*pageOffset > startOffset) { 2473856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("skipped %lld bytes of junk to reach next frame", 248ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset - startOffset); 249ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 250ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 251ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 252ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 253ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 254ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ++*pageOffset; 255ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 256ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 257ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 258db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// Given the offset of the "current" page, find the page immediately preceding 259db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// it (if any) and return its granule position. 260db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// To do this we back up from the "current" page's offset until we find any 261db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// page preceding it and then scan forward to just before the current page. 2623fd91baee812919f53a85c5c05f32606313f8334Andreas Huberstatus_t MyVorbisExtractor::findPrevGranulePosition( 2633fd91baee812919f53a85c5c05f32606313f8334Andreas Huber off64_t pageOffset, uint64_t *granulePos) { 2643fd91baee812919f53a85c5c05f32606313f8334Andreas Huber *granulePos = 0; 2653fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 266c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t prevPageOffset = 0; 267c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t prevGuess = pageOffset; 268db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber for (;;) { 269db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevGuess >= 5000) { 270db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber prevGuess -= 5000; 271db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } else { 272db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber prevGuess = 0; 273db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 274db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 2753856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("backing up %lld bytes", pageOffset - prevGuess); 276db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 2773fd91baee812919f53a85c5c05f32606313f8334Andreas Huber status_t err = findNextPage(prevGuess, &prevPageOffset); 2783fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (err != OK) { 2793fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return err; 2803fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 281db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 282db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevPageOffset < pageOffset || prevGuess == 0) { 283db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber break; 284db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 285db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 286db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 287db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevPageOffset == pageOffset) { 288db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // We did not find a page preceding this one. 2893fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return UNKNOWN_ERROR; 290db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 291db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 2923856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("prevPageOffset at %lld, pageOffset at %lld", 2933fd91baee812919f53a85c5c05f32606313f8334Andreas Huber prevPageOffset, pageOffset); 294db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 295db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber for (;;) { 296db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber Page prevPage; 297db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber ssize_t n = readPage(prevPageOffset, &prevPage); 298db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 299db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (n <= 0) { 3003fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return (status_t)n; 301db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 302db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 303db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber prevPageOffset += n; 304db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 305db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevPageOffset == pageOffset) { 3063fd91baee812919f53a85c5c05f32606313f8334Andreas Huber *granulePos = prevPage.mGranulePosition; 3073fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return OK; 308db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 309db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 310db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber} 311db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 3123fd91baee812919f53a85c5c05f32606313f8334Andreas Huberstatus_t MyVorbisExtractor::seekToTime(int64_t timeUs) { 3133fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (mTableOfContents.isEmpty()) { 3143fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // Perform approximate seeking based on avg. bitrate. 3153fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 3163fd91baee812919f53a85c5c05f32606313f8334Andreas Huber off64_t pos = timeUs * approxBitrate() / 8000000ll; 3173fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 3183856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("seeking to offset %lld", pos); 3193fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return seekToOffset(pos); 3203fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 3213fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 3223fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t left = 0; 3233fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t right = mTableOfContents.size(); 3243fd91baee812919f53a85c5c05f32606313f8334Andreas Huber while (left < right) { 3253fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t center = left / 2 + right / 2 + (left & right & 1); 3263fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 3273fd91baee812919f53a85c5c05f32606313f8334Andreas Huber const TOCEntry &entry = mTableOfContents.itemAt(center); 3283fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 3293fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (timeUs < entry.mTimeUs) { 3303fd91baee812919f53a85c5c05f32606313f8334Andreas Huber right = center; 3313fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } else if (timeUs > entry.mTimeUs) { 3323fd91baee812919f53a85c5c05f32606313f8334Andreas Huber left = center + 1; 3333fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } else { 3343fd91baee812919f53a85c5c05f32606313f8334Andreas Huber left = right = center; 3353fd91baee812919f53a85c5c05f32606313f8334Andreas Huber break; 3363fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 3373fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 3383fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 3393fd91baee812919f53a85c5c05f32606313f8334Andreas Huber const TOCEntry &entry = mTableOfContents.itemAt(left); 3403fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 3413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("seeking to entry %d / %d at offset %lld", 3423fd91baee812919f53a85c5c05f32606313f8334Andreas Huber left, mTableOfContents.size(), entry.mPageOffset); 3433fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 3443fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return seekToOffset(entry.mPageOffset); 3453fd91baee812919f53a85c5c05f32606313f8334Andreas Huber} 3463fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 347c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MyVorbisExtractor::seekToOffset(off64_t offset) { 34896f52cde23982f668592418a9548045237d5e327Andreas Huber if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) { 34996f52cde23982f668592418a9548045237d5e327Andreas Huber // Once we know where the actual audio data starts (past the headers) 35096f52cde23982f668592418a9548045237d5e327Andreas Huber // don't ever seek to anywhere before that. 35196f52cde23982f668592418a9548045237d5e327Andreas Huber offset = mFirstDataOffset; 35296f52cde23982f668592418a9548045237d5e327Andreas Huber } 35396f52cde23982f668592418a9548045237d5e327Andreas Huber 354c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t pageOffset; 355ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t err = findNextPage(offset, &pageOffset); 356ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 357ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (err != OK) { 358ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return err; 359ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 360ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 361db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // We found the page we wanted to seek to, but we'll also need 362db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // the page preceding it to determine how many valid samples are on 363db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // this page. 3643fd91baee812919f53a85c5c05f32606313f8334Andreas Huber findPrevGranulePosition(pageOffset, &mPrevGranulePosition); 365db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 366ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset = pageOffset; 367ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 368ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize = 0; 369db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = true; 370db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPageSamples = 0; 371ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPage.mNumSegments = 0; 372ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = 0; 373ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 374ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // XXX what if new page continues packet from last??? 375ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 376ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 377ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 378ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 379c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MyVorbisExtractor::readPage(off64_t offset, Page *page) { 380ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t header[27]; 381df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber ssize_t n; 382df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber if ((n = mSource->readAt(offset, header, sizeof(header))) 383ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber < (ssize_t)sizeof(header)) { 3843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("failed to read %d bytes at offset 0x%016llx, got %ld bytes", 385df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber sizeof(header), offset, n); 386ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 387df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber if (n < 0) { 388df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber return n; 389df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber } else if (n == 0) { 390df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber return ERROR_END_OF_STREAM; 391df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber } else { 392df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber return ERROR_IO; 393df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber } 394ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 395ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 396ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (memcmp(header, "OggS", 4)) { 397ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_MALFORMED; 398ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 399ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 400ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (header[4] != 0) { 401ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // Wrong version. 402ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 403ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_UNSUPPORTED; 404ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 405ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 406ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mFlags = header[5]; 407ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 408ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (page->mFlags & ~7) { 409ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // Only bits 0-2 are defined in version 0. 410ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_MALFORMED; 411ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 412ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 413ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mGranulePosition = U64LE_AT(&header[6]); 414ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 415ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0 416ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber printf("granulePosition = %llu (0x%llx)\n", 417ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mGranulePosition, page->mGranulePosition); 418ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif 419ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 420ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mSerialNo = U32LE_AT(&header[14]); 421ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mPageNo = U32LE_AT(&header[18]); 422ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 423ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mNumSegments = header[26]; 424ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mSource->readAt( 425ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber offset + sizeof(header), page->mLace, page->mNumSegments) 426ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber < (ssize_t)page->mNumSegments) { 427ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_IO; 428ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 429ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 430ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t totalSize = 0;; 431ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 432ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber totalSize += page->mLace[i]; 433ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 434ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 4355a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#if 0 436ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber String8 tmp; 437ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 438ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char x[32]; 439ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]); 440ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 441ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp.append(x); 442ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 443ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 4443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string()); 4455a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#endif 446ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 447ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return sizeof(header) + page->mNumSegments + totalSize; 448ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 449ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 450ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { 451ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = NULL; 452ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 453ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer = NULL; 454ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t timeUs = -1; 455ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 456ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (;;) { 457ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t i; 458ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t packetSize = 0; 459ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber bool gotFullPacket = false; 460ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) { 461ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t lace = mCurrentPage.mLace[i]; 462ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 463ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packetSize += lace; 464ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 465ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (lace < 255) { 466ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber gotFullPacket = true; 467ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ++i; 468ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 469ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 470ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 471ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 472ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mNextLaceIndex < mCurrentPage.mNumSegments) { 473c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments; 474ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t j = 0; j < mNextLaceIndex; ++j) { 475ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber dataOffset += mCurrentPage.mLace[j]; 476ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 477ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 478ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t fullSize = packetSize; 479ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 480ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber fullSize += buffer->range_length(); 481ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 482ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *tmp = new MediaBuffer(fullSize); 483ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 484ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber memcpy(tmp->data(), buffer->data(), buffer->range_length()); 485ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp->set_range(0, buffer->range_length()); 486ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->release(); 487ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber } else { 488ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // XXX Not only is this not technically the correct time for 489ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // this packet, we also stamp every packet in this page 490ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // with the same time. This needs fixing later. 491ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber 492ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber if (mVi.rate) { 493ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber // Rate may not have been initialized yet if we're currently 494ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber // reading the configuration packets... 495ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber // Fortunately, the timestamp doesn't matter for those. 496ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate; 497ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber } 498ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp->set_range(0, 0); 499ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 500ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer = tmp; 501ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 502ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = mSource->readAt( 503ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber dataOffset, 504ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber (uint8_t *)buffer->data() + buffer->range_length(), 505ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packetSize); 506ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 507ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n < (ssize_t)packetSize) { 5083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("failed to read %d bytes at 0x%016llx, got %ld bytes", 509df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber packetSize, dataOffset, n); 510ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_IO; 511ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 512ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 513ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->set_range(0, fullSize); 514ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 515ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = i; 516ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 517ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (gotFullPacket) { 518ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // We've just read the entire packet. 519ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 520ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (timeUs >= 0) { 521ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 522ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 523ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 524db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (mFirstPacketInPage) { 525db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber buffer->meta_data()->setInt32( 526db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber kKeyValidSamples, mCurrentPageSamples); 527db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = false; 528db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 529db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 530ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = buffer; 531ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 532ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 533ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 534ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 535ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // fall through, the buffer now contains the start of the packet. 536ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 537ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 538ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments); 539ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 540ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset += mCurrentPageSize; 541ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = readPage(mOffset, &mCurrentPage); 542ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 543ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n <= 0) { 544ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer) { 545ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->release(); 546ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer = NULL; 547ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 548ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5493856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("readPage returned %ld", n); 550ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 551ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; 552ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 553ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 554db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPageSamples = 555db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPage.mGranulePosition - mPrevGranulePosition; 556db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = true; 557db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 558db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mPrevGranulePosition = mCurrentPage.mGranulePosition; 559db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 560ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize = n; 561ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = 0; 562ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 563ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 564ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if ((mCurrentPage.mFlags & 1) == 0) { 565ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // This page does not continue the packet, i.e. the packet 566ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // is already complete. 567ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 568ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (timeUs >= 0) { 569ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 570ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 571ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 572db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber buffer->meta_data()->setInt32( 573db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber kKeyValidSamples, mCurrentPageSamples); 574db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = false; 575db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 576ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = buffer; 577ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 578ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 579ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 580ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 581ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 582ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 583ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5845a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huberstatus_t MyVorbisExtractor::init() { 585ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta = new MetaData; 586ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 587ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 588ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *packet; 5895a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber status_t err; 5905a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if ((err = readNextPacket(&packet)) != OK) { 5915a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return err; 5925a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 5933856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("read packet of size %d\n", packet->range_length()); 5945a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber err = verifyHeader(packet, 1); 595ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet->release(); 596ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet = NULL; 5975a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (err != OK) { 5985a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return err; 5995a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 600ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 6015a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if ((err = readNextPacket(&packet)) != OK) { 6025a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return err; 6035a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 6043856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("read packet of size %d\n", packet->range_length()); 6055a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber err = verifyHeader(packet, 3); 606ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet->release(); 607ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet = NULL; 6085a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (err != OK) { 6095a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return err; 6105a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 611ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 6125a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if ((err = readNextPacket(&packet)) != OK) { 6135a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return err; 6145a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 6153856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("read packet of size %d\n", packet->range_length()); 6165a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber err = verifyHeader(packet, 5); 617ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet->release(); 618ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet = NULL; 6195a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (err != OK) { 6205a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return err; 6215a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 62296f52cde23982f668592418a9548045237d5e327Andreas Huber 62396f52cde23982f668592418a9548045237d5e327Andreas Huber mFirstDataOffset = mOffset + mCurrentPageSize; 6245a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber 6253fd91baee812919f53a85c5c05f32606313f8334Andreas Huber off64_t size; 6263fd91baee812919f53a85c5c05f32606313f8334Andreas Huber uint64_t lastGranulePosition; 6273fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (!(mSource->flags() & DataSource::kIsCachingDataSource) 6283fd91baee812919f53a85c5c05f32606313f8334Andreas Huber && mSource->getSize(&size) == OK 6293fd91baee812919f53a85c5c05f32606313f8334Andreas Huber && findPrevGranulePosition(size, &lastGranulePosition) == OK) { 6303fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // Let's assume it's cheap to seek to the end. 6313fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // The granule position of the final page in the stream will 6323fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // give us the exact duration of the content, something that 6333fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // we can only approximate using avg. bitrate if seeking to 6343fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // the end is too expensive or impossible (live streaming). 6353fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6363fd91baee812919f53a85c5c05f32606313f8334Andreas Huber int64_t durationUs = lastGranulePosition * 1000000ll / mVi.rate; 6373fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6383fd91baee812919f53a85c5c05f32606313f8334Andreas Huber mMeta->setInt64(kKeyDuration, durationUs); 6393fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6403fd91baee812919f53a85c5c05f32606313f8334Andreas Huber buildTableOfContents(); 6413fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 6423fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6435a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return OK; 644ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 645ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 6463fd91baee812919f53a85c5c05f32606313f8334Andreas Hubervoid MyVorbisExtractor::buildTableOfContents() { 6473fd91baee812919f53a85c5c05f32606313f8334Andreas Huber off64_t offset = mFirstDataOffset; 6483fd91baee812919f53a85c5c05f32606313f8334Andreas Huber Page page; 6493fd91baee812919f53a85c5c05f32606313f8334Andreas Huber ssize_t pageSize; 6503fd91baee812919f53a85c5c05f32606313f8334Andreas Huber while ((pageSize = readPage(offset, &page)) > 0) { 6513fd91baee812919f53a85c5c05f32606313f8334Andreas Huber mTableOfContents.push(); 6523fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6533fd91baee812919f53a85c5c05f32606313f8334Andreas Huber TOCEntry &entry = 6543fd91baee812919f53a85c5c05f32606313f8334Andreas Huber mTableOfContents.editItemAt(mTableOfContents.size() - 1); 6553fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6563fd91baee812919f53a85c5c05f32606313f8334Andreas Huber entry.mPageOffset = offset; 6573fd91baee812919f53a85c5c05f32606313f8334Andreas Huber entry.mTimeUs = page.mGranulePosition * 1000000ll / mVi.rate; 6583fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6593fd91baee812919f53a85c5c05f32606313f8334Andreas Huber offset += (size_t)pageSize; 6603fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 6613fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6623fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // Limit the maximum amount of RAM we spend on the table of contents, 6633fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // if necessary thin out the table evenly to trim it down to maximum 6643fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // size. 6653fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6663fd91baee812919f53a85c5c05f32606313f8334Andreas Huber static const size_t kMaxTOCSize = 8192; 6673fd91baee812919f53a85c5c05f32606313f8334Andreas Huber static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry); 6683fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6693fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t numerator = mTableOfContents.size(); 6703fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6713fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (numerator > kMaxNumTOCEntries) { 6723fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t denom = numerator - kMaxNumTOCEntries; 6733fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6743fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t accum = 0; 6753fd91baee812919f53a85c5c05f32606313f8334Andreas Huber for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) { 6763fd91baee812919f53a85c5c05f32606313f8334Andreas Huber accum += denom; 6773fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (accum >= numerator) { 6783fd91baee812919f53a85c5c05f32606313f8334Andreas Huber mTableOfContents.removeAt(i); 6793fd91baee812919f53a85c5c05f32606313f8334Andreas Huber accum -= numerator; 6803fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 6813fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 6823fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 6833fd91baee812919f53a85c5c05f32606313f8334Andreas Huber} 6843fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 6855a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huberstatus_t MyVorbisExtractor::verifyHeader( 686ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer, uint8_t type) { 687ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber const uint8_t *data = 688ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 689ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 690ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t size = buffer->range_length(); 691ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 6925a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { 6935a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return ERROR_MALFORMED; 6945a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 695ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 696ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ogg_buffer buf; 697ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.data = (uint8_t *)data; 698ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.size = size; 699ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.refcount = 1; 700ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.ptr.owner = NULL; 701ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 702ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ogg_reference ref; 703ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.buffer = &buf; 704ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.begin = 0; 705ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.length = size; 706ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.next = NULL; 707ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 708ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_buffer bits; 709ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_readinit(&bits, &ref); 710ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 711ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(oggpack_read(&bits, 8), type); 712ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < 6; ++i) { 713ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_read(&bits, 8); // skip 'vorbis' 714ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 715ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 716ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber switch (type) { 717ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 1: 718ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 719ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits)); 720ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 721ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setData(kKeyVorbisInfo, 0, data, size); 722ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setInt32(kKeySampleRate, mVi.rate); 723ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setInt32(kKeyChannelCount, mVi.channels); 724ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 7253856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("lower-bitrate = %ld", mVi.bitrate_lower); 7263856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("upper-bitrate = %ld", mVi.bitrate_upper); 7273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); 7283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("window-bitrate = %ld", mVi.bitrate_window); 729ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 730c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t size; 731ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mSource->getSize(&size) == OK) { 732ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint64_t bps = approxBitrate(); 733f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang if (bps != 0) { 734f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang mMeta->setInt64(kKeyDuration, size * 8000000ll / bps); 735f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang } 736ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 737ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 738ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 739ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 740ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 3: 741ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 7425a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (0 != _vorbis_unpack_comment(&mVc, &bits)) { 7435a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return ERROR_MALFORMED; 7445a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 7454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber parseFileMetaData(); 747ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 748ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 749ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 750ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 5: 751ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 7525a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (0 != _vorbis_unpack_books(&mVi, &bits)) { 7535a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return ERROR_MALFORMED; 7545a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 755ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 756ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setData(kKeyVorbisBooks, 0, data, size); 757ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 758ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 759ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 7605a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber 7615a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return OK; 762ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 763ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 764ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberuint64_t MyVorbisExtractor::approxBitrate() { 765ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mVi.bitrate_nominal != 0) { 766ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mVi.bitrate_nominal; 767ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 768ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 769ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return (mVi.bitrate_lower + mVi.bitrate_upper) / 2; 770ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 771ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 7724595be952e3b1d6776a023e3f447c057797f1505Andreas Hubervoid MyVorbisExtractor::parseFileMetaData() { 7734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta = new MetaData; 7744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); 7754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 776856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten for (int i = 0; i < mVc.comments; ++i) { 777856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const char *comment = mVc.user_comments[i]; 778856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten size_t commentLength = mVc.comment_lengths[i]; 779856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten parseVorbisComment(mFileMeta, comment, commentLength); 780df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); 781856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten } 782856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten} 783856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten 784856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenvoid parseVorbisComment( 785856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const sp<MetaData> &fileMeta, const char *comment, size_t commentLength) 786856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten{ 7874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber struct { 7884595be952e3b1d6776a023e3f447c057797f1505Andreas Huber const char *const mTag; 7894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t mKey; 7904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } kMap[] = { 7914595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "TITLE", kKeyTitle }, 7924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "ARTIST", kKeyArtist }, 79311f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { "ALBUMARTIST", kKeyAlbumArtist }, 79411f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { "ALBUM ARTIST", kKeyAlbumArtist }, 79511f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { "COMPILATION", kKeyCompilation }, 7964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "ALBUM", kKeyAlbum }, 7974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "COMPOSER", kKeyComposer }, 7984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "GENRE", kKeyGenre }, 7994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "AUTHOR", kKeyAuthor }, 8004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "TRACKNUMBER", kKeyCDTrackNumber }, 8014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "DISCNUMBER", kKeyDiscNumber }, 8024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "DATE", kKeyDate }, 8034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "LYRICIST", kKeyWriter }, 8044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, 8058ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber { "ANDROID_LOOP", kKeyAutoLoop }, 8064595be952e3b1d6776a023e3f447c057797f1505Andreas Huber }; 8074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { 8094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t tagLen = strlen(kMap[j].mTag); 8104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (!strncasecmp(kMap[j].mTag, comment, tagLen) 8114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber && comment[tagLen] == '=') { 8124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (kMap[j].mKey == kKeyAlbumArt) { 8134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber extractAlbumArt( 814856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta, 8154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber &comment[tagLen + 1], 816856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten commentLength - tagLen - 1); 8178ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber } else if (kMap[j].mKey == kKeyAutoLoop) { 8188ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber if (!strcasecmp(&comment[tagLen + 1], "true")) { 819856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setInt32(kKeyAutoLoop, true); 8208ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber } 8214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else { 822856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); 8234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 8284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber// The returned buffer should be free()d. 8304595be952e3b1d6776a023e3f447c057797f1505Andreas Huberstatic uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) { 8314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber *outSize = 0; 8324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if ((size % 4) != 0) { 8344595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return NULL; 8354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8364595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8374595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t n = size; 8384595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t padding = 0; 8394595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (n >= 1 && s[n - 1] == '=') { 8404595be952e3b1d6776a023e3f447c057797f1505Andreas Huber padding = 1; 8414595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8424595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (n >= 2 && s[n - 2] == '=') { 8434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber padding = 2; 8444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8474595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t outLen = 3 * size / 4 - padding; 8484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber *outSize = outLen; 8504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber void *buffer = malloc(outLen); 8524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint8_t *out = (uint8_t *)buffer; 8544595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t j = 0; 8554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t accum = 0; 8564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber for (size_t i = 0; i < n; ++i) { 8574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber char c = s[i]; 8584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber unsigned value; 8594595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (c >= 'A' && c <= 'Z') { 8604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = c - 'A'; 8614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c >= 'a' && c <= 'z') { 8624595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 26 + c - 'a'; 8634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c >= '0' && c <= '9') { 8644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 52 + c - '0'; 8654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c == '+') { 8664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 62; 8674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c == '/') { 8684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 63; 8694595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c != '=') { 8704595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return NULL; 8714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else { 8724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (i < n - padding) { 8734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return NULL; 8744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 0; 8774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber accum = (accum << 6) | value; 8804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (((i + 1) % 4) == 0) { 8824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber out[j++] = (accum >> 16); 8834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } 8854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (j < outLen) { out[j++] = accum & 0xff; } 8864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber accum = 0; 8884595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8914595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return (uint8_t *)buffer; 8924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 8934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 894856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt( 895856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const sp<MetaData> &fileMeta, const void *data, size_t size) { 8963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("extractAlbumArt from '%s'", (const char *)data); 8974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t flacSize; 8994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize); 9004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flac == NULL) { 90229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("malformed base64 encoded data."); 9034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return; 9044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 9054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9063856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("got flac of size %d", flacSize); 9074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t picType; 9094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t typeLen; 9104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t descLen; 9114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t dataLen; 9124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber char type[128]; 9134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 8) { 9154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 9164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 9174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber picType = U32_AT(flac); 9194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (picType != 3) { 9214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber // This is not a front cover. 9224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 9234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 9244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber typeLen = U32_AT(&flac[4]); 9264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (typeLen + 1 > sizeof(type)) { 9274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 9284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 9294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9304595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 8 + typeLen) { 9314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 9324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 9334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9344595be952e3b1d6776a023e3f447c057797f1505Andreas Huber memcpy(type, &flac[8], typeLen); 9354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber type[typeLen] = '\0'; 9364595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("picType = %d, type = '%s'", picType, type); 9384595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9394595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (!strcmp(type, "-->")) { 9404595be952e3b1d6776a023e3f447c057797f1505Andreas Huber // This is not inline cover art, but an external url instead. 9414595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 9424595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 9434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber descLen = U32_AT(&flac[8 + typeLen]); 9454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 32 + typeLen + descLen) { 9474595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 9484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 9494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]); 9514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 32 + typeLen + descLen + dataLen) { 9534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 9544595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 9554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9563856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("got image data, %d trailing bytes", 9574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber flacSize - 32 - typeLen - descLen - dataLen); 9584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 959856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setData( 9604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen); 9614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 962856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setCString(kKeyAlbumArtMIME, type); 9634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 9644595be952e3b1d6776a023e3f447c057797f1505Andreas Huberexit: 9654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber free(flac); 9664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber flac = NULL; 9674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 9684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 969ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 970ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 971ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source) 972ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mDataSource(source), 973ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mInitCheck(NO_INIT), 974ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl(NULL) { 975ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl = new MyVorbisExtractor(mDataSource); 9765a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber mInitCheck = mImpl->seekToOffset(0); 977ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 9785a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (mInitCheck == OK) { 9795a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber mInitCheck = mImpl->init(); 9805a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 981ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 982ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 983ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::~OggExtractor() { 984ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber delete mImpl; 985ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl = NULL; 986ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 987ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 988ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersize_t OggExtractor::countTracks() { 989ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mInitCheck != OK ? 0 : 1; 990ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 991ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 992ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MediaSource> OggExtractor::getTrack(size_t index) { 993ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (index >= 1) { 994ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return NULL; 995ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 996ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 997ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return new OggSource(this); 998ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 999ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1000ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData( 1001ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t index, uint32_t flags) { 1002ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (index >= 1) { 1003ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return NULL; 1004ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1005ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1006ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mImpl->getFormat(); 1007ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1008ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1009ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getMetaData() { 10104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return mImpl->getFileMetaData(); 1011ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1012ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1013ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberbool SniffOgg( 10145a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 10155a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 1016ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char tmp[4]; 1017ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) { 1018ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return false; 1019ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1020ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1021ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG); 1022ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *confidence = 0.2f; 1023ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1024ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return true; 1025ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1026ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1027ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} // namespace android 1028