OggExtractor.cpp revision 856990b491d84b7ed4fefe337485c8997ba9dd02
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> 24ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/DataSource.h> 25ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaBuffer.h> 26ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaBufferGroup.h> 27ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaDebug.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 76c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong status_t seekToOffset(off64_t offset); 77ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t readNextPacket(MediaBuffer **buffer); 78ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 795a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber status_t init(); 80ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber sp<MetaData> getFileMetaData() { return mFileMeta; } 824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 83ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberprivate: 84ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber struct Page { 85ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint64_t mGranulePosition; 86ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint32_t mSerialNo; 87ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint32_t mPageNo; 88ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t mFlags; 89ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t mNumSegments; 90ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t mLace[255]; 91ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber }; 92ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 93ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sp<DataSource> mSource; 94c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t mOffset; 95ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber Page mCurrentPage; 96db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber uint64_t mPrevGranulePosition; 97ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t mCurrentPageSize; 98db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber bool mFirstPacketInPage; 99db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber uint64_t mCurrentPageSamples; 100ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t mNextLaceIndex; 101ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 102c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t mFirstDataOffset; 10396f52cde23982f668592418a9548045237d5e327Andreas Huber 104ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber vorbis_info mVi; 105ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber vorbis_comment mVc; 106ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 107ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sp<MetaData> mMeta; 1084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber sp<MetaData> mFileMeta; 109ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 110c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ssize_t readPage(off64_t offset, Page *page); 111c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong status_t findNextPage(off64_t startOffset, off64_t *pageOffset); 112ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1135a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber status_t verifyHeader( 114ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer, uint8_t type); 115ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber void parseFileMetaData(); 1174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 118c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong uint64_t findPrevGranulePosition(off64_t pageOffset); 119db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 120ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MyVorbisExtractor(const MyVorbisExtractor &); 121ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MyVorbisExtractor &operator=(const MyVorbisExtractor &); 122ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}; 123ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 124856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt( 125856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const sp<MetaData> &fileMeta, const void *data, size_t size); 126856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten 127ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 128ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 129ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor) 130ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mExtractor(extractor), 131ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted(false) { 132ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 133ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 134ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::~OggSource() { 135ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mStarted) { 136ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber stop(); 137ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 138ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 139ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 140ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggSource::getFormat() { 141ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mExtractor->mImpl->getFormat(); 142ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 143ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 144ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::start(MetaData *params) { 145ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mStarted) { 146ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return INVALID_OPERATION; 147ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 148ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 149ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted = true; 150ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 151ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 152ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 153ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 154ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::stop() { 155ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted = false; 156ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 157ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 158ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 159ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 160ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::read( 161ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer **out, const ReadOptions *options) { 162ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = NULL; 163ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 164ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t seekTimeUs; 165abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 166abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 167c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll; 1683e8843e8db702c8c9c97df2b4a31b66ea12961e6Andreas Huber LOGV("seeking to offset %ld", pos); 169ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 170ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mExtractor->mImpl->seekToOffset(pos) != OK) { 171ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_END_OF_STREAM; 172ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 173ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 174ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 175ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *packet; 176ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t err = mExtractor->mImpl->readNextPacket(&packet); 177ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 178ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (err != OK) { 179ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return err; 180ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 181ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 182ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0 183ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t timeUs; 184ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) { 185ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGI("found time = %lld us", timeUs); 186ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } else { 187ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGI("NO time"); 188ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 189ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif 190ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1918bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber packet->meta_data()->setInt32(kKeyIsSyncFrame, 1); 1928bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 193ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = packet; 194ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 195ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 196ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 197ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 198ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 199ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 200ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberMyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source) 201ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mSource(source), 202ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset(0), 203db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mPrevGranulePosition(0), 204ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize(0), 205db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage(true), 206db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPageSamples(0), 20796f52cde23982f668592418a9548045237d5e327Andreas Huber mNextLaceIndex(0), 20896f52cde23982f668592418a9548045237d5e327Andreas Huber mFirstDataOffset(-1) { 209ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPage.mNumSegments = 0; 2104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 2114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_info_init(&mVi); 2124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_comment_init(&mVc); 213ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 214ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 215ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberMyVorbisExtractor::~MyVorbisExtractor() { 2164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_comment_clear(&mVc); 2174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_info_clear(&mVi); 218ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 219ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 220ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> MyVorbisExtractor::getFormat() const { 221ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mMeta; 222ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 223ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 224ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::findNextPage( 225c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t startOffset, off64_t *pageOffset) { 226ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset = startOffset; 227ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 228ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (;;) { 229ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char signature[4]; 230ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = mSource->readAt(*pageOffset, &signature, 4); 231ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 232ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n < 4) { 233ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset = 0; 234ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 235ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM; 236ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 237ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 238ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (!memcmp(signature, "OggS", 4)) { 239ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (*pageOffset > startOffset) { 240ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("skipped %ld bytes of junk to reach next frame", 241ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset - startOffset); 242ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 243ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 244ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 245ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 246ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 247ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ++*pageOffset; 248ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 249ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 250ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 251db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// Given the offset of the "current" page, find the page immediately preceding 252db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// it (if any) and return its granule position. 253db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// To do this we back up from the "current" page's offset until we find any 254db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// page preceding it and then scan forward to just before the current page. 255c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Donguint64_t MyVorbisExtractor::findPrevGranulePosition(off64_t pageOffset) { 256c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t prevPageOffset = 0; 257c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t prevGuess = pageOffset; 258db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber for (;;) { 259db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevGuess >= 5000) { 260db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber prevGuess -= 5000; 261db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } else { 262db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber prevGuess = 0; 263db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 264db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 265db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber LOGV("backing up %ld bytes", pageOffset - prevGuess); 266db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 267db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber CHECK_EQ(findNextPage(prevGuess, &prevPageOffset), (status_t)OK); 268db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 269db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevPageOffset < pageOffset || prevGuess == 0) { 270db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber break; 271db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 272db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 273db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 274db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevPageOffset == pageOffset) { 275db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // We did not find a page preceding this one. 276db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber return 0; 277db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 278db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 279db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber LOGV("prevPageOffset at %ld, pageOffset at %ld", prevPageOffset, pageOffset); 280db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 281db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber for (;;) { 282db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber Page prevPage; 283db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber ssize_t n = readPage(prevPageOffset, &prevPage); 284db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 285db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (n <= 0) { 286db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber return 0; 287db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 288db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 289db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber prevPageOffset += n; 290db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 291db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevPageOffset == pageOffset) { 292db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber return prevPage.mGranulePosition; 293db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 294db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 295db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber} 296db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 297c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t MyVorbisExtractor::seekToOffset(off64_t offset) { 29896f52cde23982f668592418a9548045237d5e327Andreas Huber if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) { 29996f52cde23982f668592418a9548045237d5e327Andreas Huber // Once we know where the actual audio data starts (past the headers) 30096f52cde23982f668592418a9548045237d5e327Andreas Huber // don't ever seek to anywhere before that. 30196f52cde23982f668592418a9548045237d5e327Andreas Huber offset = mFirstDataOffset; 30296f52cde23982f668592418a9548045237d5e327Andreas Huber } 30396f52cde23982f668592418a9548045237d5e327Andreas Huber 304c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t pageOffset; 305ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t err = findNextPage(offset, &pageOffset); 306ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 307ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (err != OK) { 308ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return err; 309ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 310ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 311db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // We found the page we wanted to seek to, but we'll also need 312db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // the page preceding it to determine how many valid samples are on 313db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // this page. 314db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mPrevGranulePosition = findPrevGranulePosition(pageOffset); 315db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 316ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset = pageOffset; 317ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 318ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize = 0; 319db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = true; 320db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPageSamples = 0; 321ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPage.mNumSegments = 0; 322ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = 0; 323ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 324ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // XXX what if new page continues packet from last??? 325ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 326ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 327ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 328ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 329c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t MyVorbisExtractor::readPage(off64_t offset, Page *page) { 330ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t header[27]; 331ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mSource->readAt(offset, header, sizeof(header)) 332ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber < (ssize_t)sizeof(header)) { 3333e8843e8db702c8c9c97df2b4a31b66ea12961e6Andreas Huber LOGV("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset); 334ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 335ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_IO; 336ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 337ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 338ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (memcmp(header, "OggS", 4)) { 339ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_MALFORMED; 340ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 341ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 342ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (header[4] != 0) { 343ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // Wrong version. 344ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 345ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_UNSUPPORTED; 346ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 347ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 348ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mFlags = header[5]; 349ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 350ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (page->mFlags & ~7) { 351ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // Only bits 0-2 are defined in version 0. 352ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_MALFORMED; 353ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 354ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 355ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mGranulePosition = U64LE_AT(&header[6]); 356ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 357ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0 358ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber printf("granulePosition = %llu (0x%llx)\n", 359ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mGranulePosition, page->mGranulePosition); 360ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif 361ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 362ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mSerialNo = U32LE_AT(&header[14]); 363ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mPageNo = U32LE_AT(&header[18]); 364ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 365ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mNumSegments = header[26]; 366ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mSource->readAt( 367ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber offset + sizeof(header), page->mLace, page->mNumSegments) 368ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber < (ssize_t)page->mNumSegments) { 369ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_IO; 370ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 371ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 372ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t totalSize = 0;; 373ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 374ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber totalSize += page->mLace[i]; 375ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 376ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 3775a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#if 0 378ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber String8 tmp; 379ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 380ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char x[32]; 381ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]); 382ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 383ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp.append(x); 384ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 385ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 3865a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string()); 3875a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#endif 388ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 389ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return sizeof(header) + page->mNumSegments + totalSize; 390ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 391ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 392ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { 393ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = NULL; 394ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 395ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer = NULL; 396ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t timeUs = -1; 397ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 398ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (;;) { 399ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t i; 400ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t packetSize = 0; 401ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber bool gotFullPacket = false; 402ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) { 403ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t lace = mCurrentPage.mLace[i]; 404ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 405ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packetSize += lace; 406ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 407ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (lace < 255) { 408ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber gotFullPacket = true; 409ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ++i; 410ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 411ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 412ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 413ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 414ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mNextLaceIndex < mCurrentPage.mNumSegments) { 415c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments; 416ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t j = 0; j < mNextLaceIndex; ++j) { 417ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber dataOffset += mCurrentPage.mLace[j]; 418ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 419ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 420ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t fullSize = packetSize; 421ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 422ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber fullSize += buffer->range_length(); 423ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 424ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *tmp = new MediaBuffer(fullSize); 425ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 426ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber memcpy(tmp->data(), buffer->data(), buffer->range_length()); 427ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp->set_range(0, buffer->range_length()); 428ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->release(); 429ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber } else { 430ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // XXX Not only is this not technically the correct time for 431ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // this packet, we also stamp every packet in this page 432ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // with the same time. This needs fixing later. 433ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber 434ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber if (mVi.rate) { 435ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber // Rate may not have been initialized yet if we're currently 436ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber // reading the configuration packets... 437ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber // Fortunately, the timestamp doesn't matter for those. 438ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate; 439ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber } 440ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp->set_range(0, 0); 441ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 442ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer = tmp; 443ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 444ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = mSource->readAt( 445ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber dataOffset, 446ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber (uint8_t *)buffer->data() + buffer->range_length(), 447ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packetSize); 448ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 449ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n < (ssize_t)packetSize) { 4503e8843e8db702c8c9c97df2b4a31b66ea12961e6Andreas Huber LOGV("failed to read %d bytes at 0x%08lx", packetSize, dataOffset); 451ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_IO; 452ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 453ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 454ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->set_range(0, fullSize); 455ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 456ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = i; 457ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 458ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (gotFullPacket) { 459ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // We've just read the entire packet. 460ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 461ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (timeUs >= 0) { 462ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 463ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 464ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 465db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (mFirstPacketInPage) { 466db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber buffer->meta_data()->setInt32( 467db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber kKeyValidSamples, mCurrentPageSamples); 468db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = false; 469db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 470db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 471ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = buffer; 472ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 473ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 474ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 475ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 476ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // fall through, the buffer now contains the start of the packet. 477ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 478ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 479ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments); 480ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 481ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset += mCurrentPageSize; 482ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = readPage(mOffset, &mCurrentPage); 483ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 484ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n <= 0) { 485ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer) { 486ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->release(); 487ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer = NULL; 488ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 489ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 4903e8843e8db702c8c9c97df2b4a31b66ea12961e6Andreas Huber LOGV("readPage returned %ld", n); 491ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 492ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; 493ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 494ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 495db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPageSamples = 496db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPage.mGranulePosition - mPrevGranulePosition; 497db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = true; 498db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 499db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mPrevGranulePosition = mCurrentPage.mGranulePosition; 500db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 501ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize = n; 502ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = 0; 503ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 504ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 505ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if ((mCurrentPage.mFlags & 1) == 0) { 506ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // This page does not continue the packet, i.e. the packet 507ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // is already complete. 508ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 509ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (timeUs >= 0) { 510ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 511ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 512ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 513db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber buffer->meta_data()->setInt32( 514db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber kKeyValidSamples, mCurrentPageSamples); 515db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = false; 516db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 517ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = buffer; 518ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 519ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 520ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 521ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 522ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 523ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 524ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5255a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huberstatus_t MyVorbisExtractor::init() { 526ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta = new MetaData; 527ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 528ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 529ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *packet; 5305a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber status_t err; 5315a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if ((err = readNextPacket(&packet)) != OK) { 5325a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return err; 5335a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 534ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("read packet of size %d\n", packet->range_length()); 5355a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber err = verifyHeader(packet, 1); 536ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet->release(); 537ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet = NULL; 5385a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (err != OK) { 5395a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return err; 5405a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 541ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5425a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if ((err = readNextPacket(&packet)) != OK) { 5435a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return err; 5445a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 545ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("read packet of size %d\n", packet->range_length()); 5465a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber err = verifyHeader(packet, 3); 547ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet->release(); 548ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet = NULL; 5495a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (err != OK) { 5505a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return err; 5515a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 552ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5535a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if ((err = readNextPacket(&packet)) != OK) { 5545a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return err; 5555a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 556ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("read packet of size %d\n", packet->range_length()); 5575a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber err = verifyHeader(packet, 5); 558ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet->release(); 559ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet = NULL; 5605a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (err != OK) { 5615a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return err; 5625a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 56396f52cde23982f668592418a9548045237d5e327Andreas Huber 56496f52cde23982f668592418a9548045237d5e327Andreas Huber mFirstDataOffset = mOffset + mCurrentPageSize; 5655a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber 5665a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return OK; 567ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 568ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5695a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huberstatus_t MyVorbisExtractor::verifyHeader( 570ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer, uint8_t type) { 571ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber const uint8_t *data = 572ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 573ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 574ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t size = buffer->range_length(); 575ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5765a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { 5775a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return ERROR_MALFORMED; 5785a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 579ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 580ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ogg_buffer buf; 581ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.data = (uint8_t *)data; 582ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.size = size; 583ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.refcount = 1; 584ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.ptr.owner = NULL; 585ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 586ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ogg_reference ref; 587ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.buffer = &buf; 588ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.begin = 0; 589ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.length = size; 590ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.next = NULL; 591ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 592ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_buffer bits; 593ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_readinit(&bits, &ref); 594ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 595ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(oggpack_read(&bits, 8), type); 596ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < 6; ++i) { 597ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_read(&bits, 8); // skip 'vorbis' 598ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 599ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 600ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber switch (type) { 601ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 1: 602ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 603ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits)); 604ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 605ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setData(kKeyVorbisInfo, 0, data, size); 606ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setInt32(kKeySampleRate, mVi.rate); 607ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setInt32(kKeyChannelCount, mVi.channels); 608ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 609ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("lower-bitrate = %ld", mVi.bitrate_lower); 610ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("upper-bitrate = %ld", mVi.bitrate_upper); 611ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); 612ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("window-bitrate = %ld", mVi.bitrate_window); 613ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 614c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t size; 615ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mSource->getSize(&size) == OK) { 616ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint64_t bps = approxBitrate(); 617ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 618ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setInt64(kKeyDuration, size * 8000000ll / bps); 619ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 620ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 621ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 622ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 623ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 3: 624ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 6255a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (0 != _vorbis_unpack_comment(&mVc, &bits)) { 6265a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return ERROR_MALFORMED; 6275a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 6284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber parseFileMetaData(); 630ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 631ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 632ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 633ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 5: 634ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 6355a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (0 != _vorbis_unpack_books(&mVi, &bits)) { 6365a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return ERROR_MALFORMED; 6375a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 638ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 639ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setData(kKeyVorbisBooks, 0, data, size); 640ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 641ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 642ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 6435a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber 6445a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return OK; 645ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 646ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 647ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberuint64_t MyVorbisExtractor::approxBitrate() { 648ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mVi.bitrate_nominal != 0) { 649ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mVi.bitrate_nominal; 650ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 651ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 652ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return (mVi.bitrate_lower + mVi.bitrate_upper) / 2; 653ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 654ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 6554595be952e3b1d6776a023e3f447c057797f1505Andreas Hubervoid MyVorbisExtractor::parseFileMetaData() { 6564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta = new MetaData; 6574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); 6584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 659856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten for (int i = 0; i < mVc.comments; ++i) { 660856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const char *comment = mVc.user_comments[i]; 661856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten size_t commentLength = mVc.comment_lengths[i]; 662856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten parseVorbisComment(mFileMeta, comment, commentLength); 663856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten //LOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); 664856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten } 665856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten} 666856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten 667856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenvoid parseVorbisComment( 668856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const sp<MetaData> &fileMeta, const char *comment, size_t commentLength) 669856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten{ 6704595be952e3b1d6776a023e3f447c057797f1505Andreas Huber struct { 6714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber const char *const mTag; 6724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t mKey; 6734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } kMap[] = { 6744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "TITLE", kKeyTitle }, 6754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "ARTIST", kKeyArtist }, 67611f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { "ALBUMARTIST", kKeyAlbumArtist }, 67711f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { "ALBUM ARTIST", kKeyAlbumArtist }, 67811f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { "COMPILATION", kKeyCompilation }, 6794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "ALBUM", kKeyAlbum }, 6804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "COMPOSER", kKeyComposer }, 6814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "GENRE", kKeyGenre }, 6824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "AUTHOR", kKeyAuthor }, 6834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "TRACKNUMBER", kKeyCDTrackNumber }, 6844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "DISCNUMBER", kKeyDiscNumber }, 6854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "DATE", kKeyDate }, 6864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "LYRICIST", kKeyWriter }, 6874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, 6888ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber { "ANDROID_LOOP", kKeyAutoLoop }, 6894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber }; 6904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6914595be952e3b1d6776a023e3f447c057797f1505Andreas Huber for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { 6924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t tagLen = strlen(kMap[j].mTag); 6934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (!strncasecmp(kMap[j].mTag, comment, tagLen) 6944595be952e3b1d6776a023e3f447c057797f1505Andreas Huber && comment[tagLen] == '=') { 6954595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (kMap[j].mKey == kKeyAlbumArt) { 6964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber extractAlbumArt( 697856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta, 6984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber &comment[tagLen + 1], 699856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten commentLength - tagLen - 1); 7008ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber } else if (kMap[j].mKey == kKeyAutoLoop) { 7018ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber if (!strcasecmp(&comment[tagLen + 1], "true")) { 702856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setInt32(kKeyAutoLoop, true); 7038ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber } 7044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else { 705856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); 7064595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 7114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber// The returned buffer should be free()d. 7134595be952e3b1d6776a023e3f447c057797f1505Andreas Huberstatic uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) { 7144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber *outSize = 0; 7154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if ((size % 4) != 0) { 7174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return NULL; 7184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t n = size; 7214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t padding = 0; 7224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (n >= 1 && s[n - 1] == '=') { 7234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber padding = 1; 7244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (n >= 2 && s[n - 2] == '=') { 7264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber padding = 2; 7274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7304595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t outLen = 3 * size / 4 - padding; 7314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber *outSize = outLen; 7334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7344595be952e3b1d6776a023e3f447c057797f1505Andreas Huber void *buffer = malloc(outLen); 7354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7364595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint8_t *out = (uint8_t *)buffer; 7374595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t j = 0; 7384595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t accum = 0; 7394595be952e3b1d6776a023e3f447c057797f1505Andreas Huber for (size_t i = 0; i < n; ++i) { 7404595be952e3b1d6776a023e3f447c057797f1505Andreas Huber char c = s[i]; 7414595be952e3b1d6776a023e3f447c057797f1505Andreas Huber unsigned value; 7424595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (c >= 'A' && c <= 'Z') { 7434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = c - 'A'; 7444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c >= 'a' && c <= 'z') { 7454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 26 + c - 'a'; 7464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c >= '0' && c <= '9') { 7474595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 52 + c - '0'; 7484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c == '+') { 7494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 62; 7504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c == '/') { 7514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 63; 7524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c != '=') { 7534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return NULL; 7544595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else { 7554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (i < n - padding) { 7564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return NULL; 7574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7594595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 0; 7604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7624595be952e3b1d6776a023e3f447c057797f1505Andreas Huber accum = (accum << 6) | value; 7634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (((i + 1) % 4) == 0) { 7654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber out[j++] = (accum >> 16); 7664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } 7684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (j < outLen) { out[j++] = accum & 0xff; } 7694595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7704595be952e3b1d6776a023e3f447c057797f1505Andreas Huber accum = 0; 7714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return (uint8_t *)buffer; 7754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 7764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 777856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt( 778856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const sp<MetaData> &fileMeta, const void *data, size_t size) { 7794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber LOGV("extractAlbumArt from '%s'", (const char *)data); 7804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t flacSize; 7824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize); 7834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flac == NULL) { 7854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber LOGE("malformed base64 encoded data."); 7864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return; 7874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7884595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber LOGV("got flac of size %d", flacSize); 7904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7914595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t picType; 7924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t typeLen; 7934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t descLen; 7944595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t dataLen; 7954595be952e3b1d6776a023e3f447c057797f1505Andreas Huber char type[128]; 7964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 8) { 7984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 7994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber picType = U32_AT(flac); 8024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (picType != 3) { 8044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber // This is not a front cover. 8054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 8064595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber typeLen = U32_AT(&flac[4]); 8094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (typeLen + 1 > sizeof(type)) { 8104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 8114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 8 + typeLen) { 8144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 8154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber memcpy(type, &flac[8], typeLen); 8184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber type[typeLen] = '\0'; 8194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber LOGV("picType = %d, type = '%s'", picType, type); 8214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (!strcmp(type, "-->")) { 8234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber // This is not inline cover art, but an external url instead. 8244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 8254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber descLen = U32_AT(&flac[8 + typeLen]); 8284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 32 + typeLen + descLen) { 8304595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 8314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]); 8344595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 32 + typeLen + descLen + dataLen) { 8364595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 8374595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 8384595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8394595be952e3b1d6776a023e3f447c057797f1505Andreas Huber LOGV("got image data, %d trailing bytes", 8404595be952e3b1d6776a023e3f447c057797f1505Andreas Huber flacSize - 32 - typeLen - descLen - dataLen); 8414595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 842856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setData( 8434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen); 8444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 845856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setCString(kKeyAlbumArtMIME, type); 8464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 8474595be952e3b1d6776a023e3f447c057797f1505Andreas Huberexit: 8484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber free(flac); 8494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber flac = NULL; 8504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 8514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 852ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 853ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 854ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source) 855ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mDataSource(source), 856ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mInitCheck(NO_INIT), 857ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl(NULL) { 858ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl = new MyVorbisExtractor(mDataSource); 8595a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber mInitCheck = mImpl->seekToOffset(0); 860ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 8615a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (mInitCheck == OK) { 8625a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber mInitCheck = mImpl->init(); 8635a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 864ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 865ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 866ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::~OggExtractor() { 867ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber delete mImpl; 868ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl = NULL; 869ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 870ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 871ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersize_t OggExtractor::countTracks() { 872ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mInitCheck != OK ? 0 : 1; 873ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 874ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 875ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MediaSource> OggExtractor::getTrack(size_t index) { 876ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (index >= 1) { 877ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return NULL; 878ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 879ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 880ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return new OggSource(this); 881ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 882ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 883ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData( 884ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t index, uint32_t flags) { 885ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (index >= 1) { 886ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return NULL; 887ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 888ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 889ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mImpl->getFormat(); 890ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 891ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 892ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getMetaData() { 8934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return mImpl->getFileMetaData(); 894ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 895ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 896ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberbool SniffOgg( 8975a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 8985a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 899ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char tmp[4]; 900ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) { 901ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return false; 902ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 903ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 904ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG); 905ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *confidence = 0.2f; 906ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 907ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return true; 908ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 909ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 910ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} // namespace android 911