OggExtractor.cpp revision 4595be952e3b1d6776a023e3f447c057797f1505
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 76ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t seekToOffset(off_t offset); 77ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t readNextPacket(MediaBuffer **buffer); 78ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 79ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber void 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; 94ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber off_t mOffset; 95ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber Page mCurrentPage; 96ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t mCurrentPageSize; 97ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t mNextLaceIndex; 98ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 9996f52cde23982f668592418a9548045237d5e327Andreas Huber off_t mFirstDataOffset; 10096f52cde23982f668592418a9548045237d5e327Andreas Huber 101ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber vorbis_info mVi; 102ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber vorbis_comment mVc; 103ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 104ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sp<MetaData> mMeta; 1054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber sp<MetaData> mFileMeta; 106ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 107ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t readPage(off_t offset, Page *page); 108ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t findNextPage(off_t startOffset, off_t *pageOffset); 109ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 110ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber void verifyHeader( 111ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer, uint8_t type); 112ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber void parseFileMetaData(); 1144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber void extractAlbumArt(const void *data, size_t size); 1154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 116ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MyVorbisExtractor(const MyVorbisExtractor &); 117ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MyVorbisExtractor &operator=(const MyVorbisExtractor &); 118ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}; 119ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 120ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 121ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 122ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor) 123ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mExtractor(extractor), 124ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted(false) { 125ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 126ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 127ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::~OggSource() { 128ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mStarted) { 129ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber stop(); 130ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 131ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 132ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 133ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggSource::getFormat() { 134ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mExtractor->mImpl->getFormat(); 135ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 136ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 137ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::start(MetaData *params) { 138ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mStarted) { 139ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return INVALID_OPERATION; 140ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 141ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 142ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted = true; 143ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 144ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 145ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 146ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 147ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::stop() { 148ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted = false; 149ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 150ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 151ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 152ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 153ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::read( 154ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer **out, const ReadOptions *options) { 155ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = NULL; 156ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 157ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t seekTimeUs; 158ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (options && options->getSeekTo(&seekTimeUs)) { 159ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber off_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll; 160ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGI("seeking to offset %ld", pos); 161ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 162ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mExtractor->mImpl->seekToOffset(pos) != OK) { 163ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_END_OF_STREAM; 164ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 165ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 166ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 167ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *packet; 168ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t err = mExtractor->mImpl->readNextPacket(&packet); 169ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 170ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (err != OK) { 171ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return err; 172ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 173ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 174ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0 175ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t timeUs; 176ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) { 177ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGI("found time = %lld us", timeUs); 178ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } else { 179ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGI("NO time"); 180ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 181ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif 182ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 183ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = packet; 184ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 185ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 186ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 187ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 188ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 189ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 190ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberMyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source) 191ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mSource(source), 192ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset(0), 193ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize(0), 19496f52cde23982f668592418a9548045237d5e327Andreas Huber mNextLaceIndex(0), 19596f52cde23982f668592418a9548045237d5e327Andreas Huber mFirstDataOffset(-1) { 196ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPage.mNumSegments = 0; 1974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_info_init(&mVi); 1994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_comment_init(&mVc); 200ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 201ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 202ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberMyVorbisExtractor::~MyVorbisExtractor() { 2034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_comment_clear(&mVc); 2044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_info_clear(&mVi); 205ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 206ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 207ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> MyVorbisExtractor::getFormat() const { 208ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mMeta; 209ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 210ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 211ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::findNextPage( 212ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber off_t startOffset, off_t *pageOffset) { 213ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset = startOffset; 214ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 215ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (;;) { 216ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char signature[4]; 217ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = mSource->readAt(*pageOffset, &signature, 4); 218ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 219ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n < 4) { 220ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset = 0; 221ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 222ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM; 223ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 224ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 225ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (!memcmp(signature, "OggS", 4)) { 226ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (*pageOffset > startOffset) { 227ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("skipped %ld bytes of junk to reach next frame", 228ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset - startOffset); 229ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 230ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 231ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 232ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 233ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 234ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ++*pageOffset; 235ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 236ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 237ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 238ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::seekToOffset(off_t offset) { 23996f52cde23982f668592418a9548045237d5e327Andreas Huber if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) { 24096f52cde23982f668592418a9548045237d5e327Andreas Huber // Once we know where the actual audio data starts (past the headers) 24196f52cde23982f668592418a9548045237d5e327Andreas Huber // don't ever seek to anywhere before that. 24296f52cde23982f668592418a9548045237d5e327Andreas Huber offset = mFirstDataOffset; 24396f52cde23982f668592418a9548045237d5e327Andreas Huber } 24496f52cde23982f668592418a9548045237d5e327Andreas Huber 245ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber off_t pageOffset; 246ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t err = findNextPage(offset, &pageOffset); 247ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 248ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (err != OK) { 249ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return err; 250ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 251ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 252ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset = pageOffset; 253ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 254ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize = 0; 255ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPage.mNumSegments = 0; 256ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = 0; 257ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 258ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // XXX what if new page continues packet from last??? 259ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 260ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 261ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 262ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 263ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) { 264ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t header[27]; 265ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mSource->readAt(offset, header, sizeof(header)) 266ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber < (ssize_t)sizeof(header)) { 267ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGE("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset); 268ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 269ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_IO; 270ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 271ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 272ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (memcmp(header, "OggS", 4)) { 273ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_MALFORMED; 274ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 275ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 276ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (header[4] != 0) { 277ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // Wrong version. 278ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 279ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_UNSUPPORTED; 280ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 281ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 282ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mFlags = header[5]; 283ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 284ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (page->mFlags & ~7) { 285ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // Only bits 0-2 are defined in version 0. 286ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_MALFORMED; 287ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 288ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 289ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mGranulePosition = U64LE_AT(&header[6]); 290ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 291ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0 292ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber printf("granulePosition = %llu (0x%llx)\n", 293ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mGranulePosition, page->mGranulePosition); 294ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif 295ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 296ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mSerialNo = U32LE_AT(&header[14]); 297ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mPageNo = U32LE_AT(&header[18]); 298ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 299ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mNumSegments = header[26]; 300ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mSource->readAt( 301ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber offset + sizeof(header), page->mLace, page->mNumSegments) 302ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber < (ssize_t)page->mNumSegments) { 303ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_IO; 304ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 305ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 306ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t totalSize = 0;; 307ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 308ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber totalSize += page->mLace[i]; 309ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 310ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 311ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber String8 tmp; 312ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 313ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char x[32]; 314ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]); 315ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 316ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp.append(x); 317ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 318ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 3194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber // LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string()); 320ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 321ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return sizeof(header) + page->mNumSegments + totalSize; 322ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 323ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 324ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { 325ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = NULL; 326ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 327ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer = NULL; 328ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t timeUs = -1; 329ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 330ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (;;) { 331ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t i; 332ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t packetSize = 0; 333ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber bool gotFullPacket = false; 334ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) { 335ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t lace = mCurrentPage.mLace[i]; 336ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 337ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packetSize += lace; 338ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 339ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (lace < 255) { 340ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber gotFullPacket = true; 341ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ++i; 342ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 343ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 344ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 345ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 346ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mNextLaceIndex < mCurrentPage.mNumSegments) { 347ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber off_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments; 348ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t j = 0; j < mNextLaceIndex; ++j) { 349ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber dataOffset += mCurrentPage.mLace[j]; 350ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 351ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 352ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t fullSize = packetSize; 353ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 354ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber fullSize += buffer->range_length(); 355ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 356ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *tmp = new MediaBuffer(fullSize); 357ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 358ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber memcpy(tmp->data(), buffer->data(), buffer->range_length()); 359ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp->set_range(0, buffer->range_length()); 360ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->release(); 361ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } else { 362ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // XXX Not only is this not technically the correct time for 363ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // this packet, we also stamp every packet in this page 364ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // with the same time. This needs fixing later. 365ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate; 366ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp->set_range(0, 0); 367ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 368ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer = tmp; 369ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 370ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = mSource->readAt( 371ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber dataOffset, 372ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber (uint8_t *)buffer->data() + buffer->range_length(), 373ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packetSize); 374ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 375ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n < (ssize_t)packetSize) { 376ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGE("failed to read %d bytes at 0x%08lx", packetSize, dataOffset); 377ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_IO; 378ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 379ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 380ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->set_range(0, fullSize); 381ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 382ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = i; 383ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 384ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (gotFullPacket) { 385ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // We've just read the entire packet. 386ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 387ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (timeUs >= 0) { 388ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 389ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 390ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 391ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = buffer; 392ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 393ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 394ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 395ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 396ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // fall through, the buffer now contains the start of the packet. 397ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 398ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 399ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments); 400ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 401ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset += mCurrentPageSize; 402ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = readPage(mOffset, &mCurrentPage); 403ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 404ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n <= 0) { 405ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer) { 406ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->release(); 407ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer = NULL; 408ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 409ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 410ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGE("readPage returned %ld", n); 411ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 412ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; 413ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 414ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 415ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize = n; 416ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = 0; 417ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 418ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 419ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if ((mCurrentPage.mFlags & 1) == 0) { 420ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // This page does not continue the packet, i.e. the packet 421ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // is already complete. 422ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 423ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (timeUs >= 0) { 424ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 425ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 426ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 427ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = buffer; 428ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 429ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 430ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 431ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 432ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 433ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 434ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 435ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubervoid MyVorbisExtractor::init() { 436ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta = new MetaData; 437ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 438ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 439ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *packet; 440ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(readNextPacket(&packet), OK); 441ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("read packet of size %d\n", packet->range_length()); 442ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber verifyHeader(packet, 1); 443ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet->release(); 444ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet = NULL; 445ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 446ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(readNextPacket(&packet), OK); 447ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("read packet of size %d\n", packet->range_length()); 448ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber verifyHeader(packet, 3); 449ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet->release(); 450ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet = NULL; 451ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 452ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(readNextPacket(&packet), OK); 453ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("read packet of size %d\n", packet->range_length()); 454ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber verifyHeader(packet, 5); 455ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet->release(); 456ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packet = NULL; 45796f52cde23982f668592418a9548045237d5e327Andreas Huber 45896f52cde23982f668592418a9548045237d5e327Andreas Huber mFirstDataOffset = mOffset + mCurrentPageSize; 459ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 460ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 461ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubervoid MyVorbisExtractor::verifyHeader( 462ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer, uint8_t type) { 463ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber const uint8_t *data = 464ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 465ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 466ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t size = buffer->range_length(); 467ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 468ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK(size >= 7); 469ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 470ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(data[0], type); 471ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK(!memcmp(&data[1], "vorbis", 6)); 472ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 473ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ogg_buffer buf; 474ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.data = (uint8_t *)data; 475ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.size = size; 476ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.refcount = 1; 477ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.ptr.owner = NULL; 478ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 479ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ogg_reference ref; 480ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.buffer = &buf; 481ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.begin = 0; 482ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.length = size; 483ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.next = NULL; 484ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 485ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_buffer bits; 486ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_readinit(&bits, &ref); 487ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 488ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(oggpack_read(&bits, 8), type); 489ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < 6; ++i) { 490ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_read(&bits, 8); // skip 'vorbis' 491ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 492ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 493ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber switch (type) { 494ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 1: 495ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 496ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits)); 497ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 498ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setData(kKeyVorbisInfo, 0, data, size); 499ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setInt32(kKeySampleRate, mVi.rate); 500ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setInt32(kKeyChannelCount, mVi.channels); 501ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 502ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("lower-bitrate = %ld", mVi.bitrate_lower); 503ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("upper-bitrate = %ld", mVi.bitrate_upper); 504ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); 505ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber LOGV("window-bitrate = %ld", mVi.bitrate_window); 506ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 507ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber off_t size; 508ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mSource->getSize(&size) == OK) { 509ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint64_t bps = approxBitrate(); 510ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 511ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setInt64(kKeyDuration, size * 8000000ll / bps); 512ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 513ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 514ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 515ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 516ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 3: 517ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 518ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(0, _vorbis_unpack_comment(&mVc, &bits)); 5194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 5204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber parseFileMetaData(); 521ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 522ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 523ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 524ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 5: 525ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 526ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(0, _vorbis_unpack_books(&mVi, &bits)); 527ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 528ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setData(kKeyVorbisBooks, 0, data, size); 529ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 530ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 531ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 532ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 533ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 534ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberuint64_t MyVorbisExtractor::approxBitrate() { 535ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mVi.bitrate_nominal != 0) { 536ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mVi.bitrate_nominal; 537ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 538ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 539ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return (mVi.bitrate_lower + mVi.bitrate_upper) / 2; 540ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 541ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5424595be952e3b1d6776a023e3f447c057797f1505Andreas Hubervoid MyVorbisExtractor::parseFileMetaData() { 5434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta = new MetaData; 5444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); 5454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 5464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber struct { 5474595be952e3b1d6776a023e3f447c057797f1505Andreas Huber const char *const mTag; 5484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t mKey; 5494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } kMap[] = { 5504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "TITLE", kKeyTitle }, 5514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "ARTIST", kKeyArtist }, 5524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "ALBUM", kKeyAlbum }, 5534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "COMPOSER", kKeyComposer }, 5544595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "GENRE", kKeyGenre }, 5554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "AUTHOR", kKeyAuthor }, 5564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "TRACKNUMBER", kKeyCDTrackNumber }, 5574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "DISCNUMBER", kKeyDiscNumber }, 5584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "DATE", kKeyDate }, 5594595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "LYRICIST", kKeyWriter }, 5604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, 5614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber }; 5624595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 5634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber for (int i = 0; i < mVc.comments; ++i) { 5644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber const char *comment = mVc.user_comments[i]; 5654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 5664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { 5674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t tagLen = strlen(kMap[j].mTag); 5684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (!strncasecmp(kMap[j].mTag, comment, tagLen) 5694595be952e3b1d6776a023e3f447c057797f1505Andreas Huber && comment[tagLen] == '=') { 5704595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (kMap[j].mKey == kKeyAlbumArt) { 5714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber extractAlbumArt( 5724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber &comment[tagLen + 1], 5734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mVc.comment_lengths[i] - tagLen - 1); 5744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else { 5754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); 5764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 5774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 5784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 5794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 5804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 5814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 5824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber#if 0 5834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber for (int i = 0; i < mVc.comments; ++i) { 5844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber LOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); 5854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 5864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber#endif 5874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 5884595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 5894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber// The returned buffer should be free()d. 5904595be952e3b1d6776a023e3f447c057797f1505Andreas Huberstatic uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) { 5914595be952e3b1d6776a023e3f447c057797f1505Andreas Huber *outSize = 0; 5924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 5934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if ((size % 4) != 0) { 5944595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return NULL; 5954595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 5964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 5974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t n = size; 5984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t padding = 0; 5994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (n >= 1 && s[n - 1] == '=') { 6004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber padding = 1; 6014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (n >= 2 && s[n - 2] == '=') { 6034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber padding = 2; 6044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 6054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 6064595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t outLen = 3 * size / 4 - padding; 6084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber *outSize = outLen; 6104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber void *buffer = malloc(outLen); 6124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint8_t *out = (uint8_t *)buffer; 6144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t j = 0; 6154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t accum = 0; 6164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber for (size_t i = 0; i < n; ++i) { 6174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber char c = s[i]; 6184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber unsigned value; 6194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (c >= 'A' && c <= 'Z') { 6204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = c - 'A'; 6214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c >= 'a' && c <= 'z') { 6224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 26 + c - 'a'; 6234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c >= '0' && c <= '9') { 6244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 52 + c - '0'; 6254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c == '+') { 6264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 62; 6274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c == '/') { 6284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 63; 6294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else if (c != '=') { 6304595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return NULL; 6314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else { 6324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (i < n - padding) { 6334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return NULL; 6344595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 6354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6364595be952e3b1d6776a023e3f447c057797f1505Andreas Huber value = 0; 6374595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 6384595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6394595be952e3b1d6776a023e3f447c057797f1505Andreas Huber accum = (accum << 6) | value; 6404595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6414595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (((i + 1) % 4) == 0) { 6424595be952e3b1d6776a023e3f447c057797f1505Andreas Huber out[j++] = (accum >> 16); 6434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } 6454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (j < outLen) { out[j++] = accum & 0xff; } 6464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6474595be952e3b1d6776a023e3f447c057797f1505Andreas Huber accum = 0; 6484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 6494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 6504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return (uint8_t *)buffer; 6524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 6534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6544595be952e3b1d6776a023e3f447c057797f1505Andreas Hubervoid MyVorbisExtractor::extractAlbumArt(const void *data, size_t size) { 6554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber LOGV("extractAlbumArt from '%s'", (const char *)data); 6564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t flacSize; 6584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize); 6594595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flac == NULL) { 6614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber LOGE("malformed base64 encoded data."); 6624595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return; 6634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 6644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber LOGV("got flac of size %d", flacSize); 6664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t picType; 6684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t typeLen; 6694595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t descLen; 6704595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t dataLen; 6714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber char type[128]; 6724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 8) { 6744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 6754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 6764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber picType = U32_AT(flac); 6784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (picType != 3) { 6804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber // This is not a front cover. 6814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 6824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 6834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber typeLen = U32_AT(&flac[4]); 6854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (typeLen + 1 > sizeof(type)) { 6864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 6874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 6884595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 8 + typeLen) { 6904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 6914595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 6924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber memcpy(type, &flac[8], typeLen); 6944595be952e3b1d6776a023e3f447c057797f1505Andreas Huber type[typeLen] = '\0'; 6954595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber LOGV("picType = %d, type = '%s'", picType, type); 6974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 6984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (!strcmp(type, "-->")) { 6994595be952e3b1d6776a023e3f447c057797f1505Andreas Huber // This is not inline cover art, but an external url instead. 7004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 7014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber descLen = U32_AT(&flac[8 + typeLen]); 7044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 32 + typeLen + descLen) { 7064595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 7074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]); 7104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 32 + typeLen + descLen + dataLen) { 7124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber goto exit; 7134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 7144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber LOGV("got image data, %d trailing bytes", 7164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber flacSize - 32 - typeLen - descLen - dataLen); 7174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta->setData( 7194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen); 7204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta->setCString(kKeyAlbumArtMIME, type); 7224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 7234595be952e3b1d6776a023e3f447c057797f1505Andreas Huberexit: 7244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber free(flac); 7254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber flac = NULL; 7264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 7274595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 728ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 729ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 730ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source) 731ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mDataSource(source), 732ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mInitCheck(NO_INIT), 733ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl(NULL) { 734ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl = new MyVorbisExtractor(mDataSource); 735ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(mImpl->seekToOffset(0), OK); 736ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl->init(); 737ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 738ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mInitCheck = OK; 739ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 740ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 741ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::~OggExtractor() { 742ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber delete mImpl; 743ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl = NULL; 744ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 745ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 746ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersize_t OggExtractor::countTracks() { 747ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mInitCheck != OK ? 0 : 1; 748ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 749ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 750ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MediaSource> OggExtractor::getTrack(size_t index) { 751ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (index >= 1) { 752ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return NULL; 753ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 754ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 755ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return new OggSource(this); 756ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 757ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 758ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData( 759ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t index, uint32_t flags) { 760ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (index >= 1) { 761ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return NULL; 762ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 763ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 764ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mImpl->getFormat(); 765ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 766ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 767ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getMetaData() { 7684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return mImpl->getFileMetaData(); 769ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 770ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 771ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberbool SniffOgg( 772ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 773ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char tmp[4]; 774ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) { 775ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return false; 776ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 777ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 778ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG); 779ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *confidence = 0.2f; 780ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 781ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return true; 782ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 783ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 784ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} // namespace android 785