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> 248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih#include <media/stagefright/foundation/ABuffer.h> 25f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h> 2674814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim#include <media/stagefright/foundation/base64.h> 27ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/DataSource.h> 28ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaBuffer.h> 29ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaBufferGroup.h> 30ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaDefs.h> 31ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaErrors.h> 32ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MediaSource.h> 33ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/MetaData.h> 34ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <media/stagefright/Utils.h> 35ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#include <utils/String8.h> 36ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 37ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberextern "C" { 38ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber #include <Tremolo/codec_internal.h> 39ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 40ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb); 41ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb); 42ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb); 437a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op); 44ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 45ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 46ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubernamespace android { 47ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 48ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstruct OggSource : public MediaSource { 49ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber OggSource(const sp<OggExtractor> &extractor); 50ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 51ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber virtual sp<MetaData> getFormat(); 52ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 53ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber virtual status_t start(MetaData *params = NULL); 54ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber virtual status_t stop(); 55ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 56ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber virtual status_t read( 57ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 58ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 59ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberprotected: 60ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber virtual ~OggSource(); 61ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 62ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberprivate: 63ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sp<OggExtractor> mExtractor; 64ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber bool mStarted; 65ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 66ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber OggSource(const OggSource &); 67ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber OggSource &operator=(const OggSource &); 68ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}; 69ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstruct MyOggExtractor { 718c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih MyOggExtractor( 728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const sp<DataSource> &source, 738c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const char *mimeType, 748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih size_t numHeaders, 758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int64_t seekPreRollUs); 768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual ~MyOggExtractor(); 77ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 78ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sp<MetaData> getFormat() const; 79ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 80ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // Returns an approximate bitrate in bits per second. 818c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual uint64_t approxBitrate() const = 0; 82ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 833fd91baee812919f53a85c5c05f32606313f8334Andreas Huber status_t seekToTime(int64_t timeUs); 84c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong status_t seekToOffset(off64_t offset); 858c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual status_t readNextPacket(MediaBuffer **buffer) = 0; 86ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 875a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber status_t init(); 88ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber sp<MetaData> getFileMetaData() { return mFileMeta; } 904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihprotected: 92ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber struct Page { 93ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint64_t mGranulePosition; 947a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen int32_t mPrevPacketSize; 957a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen uint64_t mPrevPacketPos; 96ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint32_t mSerialNo; 97ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint32_t mPageNo; 98ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t mFlags; 99ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t mNumSegments; 100ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t mLace[255]; 101ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber }; 102ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1033fd91baee812919f53a85c5c05f32606313f8334Andreas Huber struct TOCEntry { 1043fd91baee812919f53a85c5c05f32606313f8334Andreas Huber off64_t mPageOffset; 1053fd91baee812919f53a85c5c05f32606313f8334Andreas Huber int64_t mTimeUs; 1063fd91baee812919f53a85c5c05f32606313f8334Andreas Huber }; 1073fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 108ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sp<DataSource> mSource; 109c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t mOffset; 110ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber Page mCurrentPage; 1118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint64_t mCurGranulePosition; 112db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber uint64_t mPrevGranulePosition; 113ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t mCurrentPageSize; 114db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber bool mFirstPacketInPage; 115db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber uint64_t mCurrentPageSamples; 116ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t mNextLaceIndex; 117ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const char *mMimeType; 1198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih size_t mNumHeaders; 1208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int64_t mSeekPreRollUs; 1218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 122c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t mFirstDataOffset; 12396f52cde23982f668592418a9548045237d5e327Andreas Huber 124ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber vorbis_info mVi; 125ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber vorbis_comment mVc; 126ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 127ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sp<MetaData> mMeta; 1284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber sp<MetaData> mFileMeta; 129ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1303fd91baee812919f53a85c5c05f32606313f8334Andreas Huber Vector<TOCEntry> mTableOfContents; 1313fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 132c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong ssize_t readPage(off64_t offset, Page *page); 133c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong status_t findNextPage(off64_t startOffset, off64_t *pageOffset); 134ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1358c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const = 0; 1368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // Extract codec format, metadata tags, and various codec specific data; 1388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // the format and CSD's are required to setup the decoders for the enclosed media content. 1398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // 1408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // Valid values for `type` are: 1418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // 1 - bitstream identification header 1428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // 3 - comment header 1438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // 5 - codec setup header (Vorbis only) 1448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type) = 0; 1458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // Read the next ogg packet from the underlying data source; optionally 1478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // calculate the timestamp for the output packet whilst pretending 1488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // that we are parsing an Ogg Vorbis stream. 1498c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // 1508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // *buffer is NULL'ed out immediately upon entry, and if successful a new buffer is allocated; 1518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // clients are responsible for releasing the original buffer. 1528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih status_t _readNextPacket(MediaBuffer **buffer, bool calcVorbisTimestamp); 153ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t getPacketBlockSize(MediaBuffer *buffer); 1557a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 1564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber void parseFileMetaData(); 1574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1583fd91baee812919f53a85c5c05f32606313f8334Andreas Huber status_t findPrevGranulePosition(off64_t pageOffset, uint64_t *granulePos); 1593fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 1603fd91baee812919f53a85c5c05f32606313f8334Andreas Huber void buildTableOfContents(); 161db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 1628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih MyOggExtractor(const MyOggExtractor &); 1638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih MyOggExtractor &operator=(const MyOggExtractor &); 1648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}; 1658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1668c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstruct MyVorbisExtractor : public MyOggExtractor { 1678c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih MyVorbisExtractor(const sp<DataSource> &source) 1688c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih : MyOggExtractor(source, 1698c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih MEDIA_MIMETYPE_AUDIO_VORBIS, 1708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih /* numHeaders */ 3, 1718c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih /* seekPreRollUs */ 0) { 1728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 1738c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual uint64_t approxBitrate() const; 1758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual status_t readNextPacket(MediaBuffer **buffer) { 1778c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return _readNextPacket(buffer, /* calcVorbisTimestamp = */ true); 1788c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 1798c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1808c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihprotected: 1818c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const { 1828c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return granulePos * 1000000ll / mVi.rate; 1838c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 1848c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1858c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type); 1868c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}; 1878c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1888c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstruct MyOpusExtractor : public MyOggExtractor { 1898c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih static const int32_t kOpusSampleRate = 48000; 1908c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih static const int64_t kOpusSeekPreRollUs = 80000; // 80 ms 1918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1928c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih MyOpusExtractor(const sp<DataSource> &source) 1938c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih : MyOggExtractor(source, MEDIA_MIMETYPE_AUDIO_OPUS, /*numHeaders*/ 2, kOpusSeekPreRollUs), 1948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mChannelCount(0), 195819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih mCodecDelay(0), 196819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih mStartGranulePosition(-1) { 1978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 1988c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1998c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual uint64_t approxBitrate() const { 2008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return 0; 2018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 2028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual status_t readNextPacket(MediaBuffer **buffer); 2048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2058c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihprotected: 2068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const; 2078c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type); 2088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihprivate: 2108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih status_t verifyOpusHeader(MediaBuffer *buffer); 2118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih status_t verifyOpusComments(MediaBuffer *buffer); 2128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint32_t getNumSamplesInPacket(MediaBuffer *buffer) const; 2138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint8_t mChannelCount; 2158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint16_t mCodecDelay; 216819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih int64_t mStartGranulePosition; 217ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}; 218ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 219856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt( 220856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const sp<MetaData> &fileMeta, const void *data, size_t size); 221856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten 222ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 223ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 224ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor) 225ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mExtractor(extractor), 226ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted(false) { 227ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 228ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 229ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::~OggSource() { 230ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mStarted) { 231ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber stop(); 232ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 233ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 234ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 235ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggSource::getFormat() { 236ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mExtractor->mImpl->getFormat(); 237ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 238ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 23984333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t OggSource::start(MetaData * /* params */) { 240ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mStarted) { 241ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return INVALID_OPERATION; 242ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 243ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 244ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted = true; 245ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 246ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 247ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 248ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 249ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::stop() { 250ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted = false; 251ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 252ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 253ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 254ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 255ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::read( 256ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer **out, const ReadOptions *options) { 257ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = NULL; 258ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 259ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t seekTimeUs; 260abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 261abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 2628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih status_t err = mExtractor->mImpl->seekToTime(seekTimeUs); 2638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (err != OK) { 2648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return err; 265ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 266ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 267ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 268ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *packet; 2698c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih status_t err = mExtractor->mImpl->readNextPacket(&packet); 270ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 271ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (err != OK) { 272ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return err; 273ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 274ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 275ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0 276ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t timeUs; 277ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) { 278df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("found time = %lld us", timeUs); 279ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } else { 280df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("NO time"); 281ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 282ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif 283ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 2848bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber packet->meta_data()->setInt32(kKeyIsSyncFrame, 1); 2858bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 286ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = packet; 287ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 288ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 289ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 290ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 291ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 292ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 2938c10a80cf1af68f15eb39552ca116ec6f04fc173Robert ShihMyOggExtractor::MyOggExtractor( 2948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const sp<DataSource> &source, 2958c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const char *mimeType, 2968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih size_t numHeaders, 2978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int64_t seekPreRollUs) 298ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mSource(source), 299ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset(0), 3008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mCurGranulePosition(0), 301db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mPrevGranulePosition(0), 302ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize(0), 303db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage(true), 304db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPageSamples(0), 30596f52cde23982f668592418a9548045237d5e327Andreas Huber mNextLaceIndex(0), 3068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMimeType(mimeType), 3078c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mNumHeaders(numHeaders), 3088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mSeekPreRollUs(seekPreRollUs), 30996f52cde23982f668592418a9548045237d5e327Andreas Huber mFirstDataOffset(-1) { 310ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPage.mNumSegments = 0; 3114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 3124595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_info_init(&mVi); 3134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_comment_init(&mVc); 314ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 315ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 3168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert ShihMyOggExtractor::~MyOggExtractor() { 3174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_comment_clear(&mVc); 3184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_info_clear(&mVi); 319ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 320ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 3218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihsp<MetaData> MyOggExtractor::getFormat() const { 322ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mMeta; 323ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 324ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 3258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::findNextPage( 326c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t startOffset, off64_t *pageOffset) { 327ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset = startOffset; 328ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 329ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (;;) { 330ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char signature[4]; 331ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = mSource->readAt(*pageOffset, &signature, 4); 332ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 333ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n < 4) { 334ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset = 0; 335ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 336ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM; 337ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 338ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 339ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (!memcmp(signature, "OggS", 4)) { 340ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (*pageOffset > startOffset) { 3413856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("skipped %lld bytes of junk to reach next frame", 342ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar (long long)(*pageOffset - startOffset)); 343ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 344ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 345ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 346ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 347ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 348ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ++*pageOffset; 349ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 350ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 351ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 352db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// Given the offset of the "current" page, find the page immediately preceding 353db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// it (if any) and return its granule position. 354db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// To do this we back up from the "current" page's offset until we find any 355db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// page preceding it and then scan forward to just before the current page. 3568c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::findPrevGranulePosition( 3573fd91baee812919f53a85c5c05f32606313f8334Andreas Huber off64_t pageOffset, uint64_t *granulePos) { 3583fd91baee812919f53a85c5c05f32606313f8334Andreas Huber *granulePos = 0; 3593fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 360c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t prevPageOffset = 0; 361c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t prevGuess = pageOffset; 362db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber for (;;) { 363db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevGuess >= 5000) { 364db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber prevGuess -= 5000; 365db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } else { 366db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber prevGuess = 0; 367db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 368db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 369ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar ALOGV("backing up %lld bytes", (long long)(pageOffset - prevGuess)); 370db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 3713fd91baee812919f53a85c5c05f32606313f8334Andreas Huber status_t err = findNextPage(prevGuess, &prevPageOffset); 3728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (err == ERROR_END_OF_STREAM) { 3738c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // We are at the last page and didn't back off enough; 3748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // back off 5000 bytes more and try again. 3758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih continue; 3768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } else if (err != OK) { 3773fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return err; 3783fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 379db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 380db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevPageOffset < pageOffset || prevGuess == 0) { 381db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber break; 382db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 383db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 384db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 385db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevPageOffset == pageOffset) { 386db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // We did not find a page preceding this one. 3873fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return UNKNOWN_ERROR; 388db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 389db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 3903856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("prevPageOffset at %lld, pageOffset at %lld", 391ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar (long long)prevPageOffset, (long long)pageOffset); 392db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 393db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber for (;;) { 394db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber Page prevPage; 395db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber ssize_t n = readPage(prevPageOffset, &prevPage); 396db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 397db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (n <= 0) { 3983fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return (status_t)n; 399db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 400db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 401db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber prevPageOffset += n; 402db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 403db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevPageOffset == pageOffset) { 4043fd91baee812919f53a85c5c05f32606313f8334Andreas Huber *granulePos = prevPage.mGranulePosition; 4053fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return OK; 406db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 407db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 408db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber} 409db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 4108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::seekToTime(int64_t timeUs) { 4118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih timeUs -= mSeekPreRollUs; 4128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (timeUs < 0) { 4138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih timeUs = 0; 4148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 4158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 4163fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (mTableOfContents.isEmpty()) { 4173fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // Perform approximate seeking based on avg. bitrate. 4188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint64_t bps = approxBitrate(); 4198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (bps <= 0) { 4208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return INVALID_OPERATION; 4218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 4223fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 4238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih off64_t pos = timeUs * bps / 8000000ll; 4243fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 425ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar ALOGV("seeking to offset %lld", (long long)pos); 4263fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return seekToOffset(pos); 4273fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 4283fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 4293fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t left = 0; 430225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar size_t right_plus_one = mTableOfContents.size(); 431225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar while (left < right_plus_one) { 432225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar size_t center = left + (right_plus_one - left) / 2; 4333fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 4343fd91baee812919f53a85c5c05f32606313f8334Andreas Huber const TOCEntry &entry = mTableOfContents.itemAt(center); 4353fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 4363fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (timeUs < entry.mTimeUs) { 437225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar right_plus_one = center; 4383fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } else if (timeUs > entry.mTimeUs) { 4393fd91baee812919f53a85c5c05f32606313f8334Andreas Huber left = center + 1; 4403fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } else { 441225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar left = center; 4423fd91baee812919f53a85c5c05f32606313f8334Andreas Huber break; 4433fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 4443fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 4453fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 446225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar if (left == mTableOfContents.size()) { 447225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar --left; 448225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar } 449225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar 4503fd91baee812919f53a85c5c05f32606313f8334Andreas Huber const TOCEntry &entry = mTableOfContents.itemAt(left); 4513fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 452a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("seeking to entry %zu / %zu at offset %lld", 453ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar left, mTableOfContents.size(), (long long)entry.mPageOffset); 4543fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 4553fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return seekToOffset(entry.mPageOffset); 4563fd91baee812919f53a85c5c05f32606313f8334Andreas Huber} 4573fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 4588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::seekToOffset(off64_t offset) { 45996f52cde23982f668592418a9548045237d5e327Andreas Huber if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) { 46096f52cde23982f668592418a9548045237d5e327Andreas Huber // Once we know where the actual audio data starts (past the headers) 46196f52cde23982f668592418a9548045237d5e327Andreas Huber // don't ever seek to anywhere before that. 46296f52cde23982f668592418a9548045237d5e327Andreas Huber offset = mFirstDataOffset; 46396f52cde23982f668592418a9548045237d5e327Andreas Huber } 46496f52cde23982f668592418a9548045237d5e327Andreas Huber 465c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t pageOffset; 466ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t err = findNextPage(offset, &pageOffset); 467ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 468ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (err != OK) { 469ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return err; 470ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 471ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 472db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // We found the page we wanted to seek to, but we'll also need 473db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // the page preceding it to determine how many valid samples are on 474db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // this page. 4753fd91baee812919f53a85c5c05f32606313f8334Andreas Huber findPrevGranulePosition(pageOffset, &mPrevGranulePosition); 476db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 477ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset = pageOffset; 478ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 479ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize = 0; 480db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = true; 481db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPageSamples = 0; 482ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPage.mNumSegments = 0; 4837a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen mCurrentPage.mPrevPacketSize = -1; 484ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = 0; 485ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 486ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // XXX what if new page continues packet from last??? 487ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 488ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 489ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 490ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 4918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihssize_t MyOggExtractor::readPage(off64_t offset, Page *page) { 492ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t header[27]; 493df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber ssize_t n; 494df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber if ((n = mSource->readAt(offset, header, sizeof(header))) 495ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber < (ssize_t)sizeof(header)) { 496ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar ALOGV("failed to read %zu bytes at offset %#016llx, got %zd bytes", 497ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar sizeof(header), (long long)offset, n); 498ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 499df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber if (n < 0) { 500df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber return n; 501df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber } else if (n == 0) { 502df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber return ERROR_END_OF_STREAM; 503df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber } else { 504df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber return ERROR_IO; 505df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber } 506ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 507ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 508ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (memcmp(header, "OggS", 4)) { 509ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_MALFORMED; 510ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 511ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 512ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (header[4] != 0) { 513ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // Wrong version. 514ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 515ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_UNSUPPORTED; 516ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 517ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 518ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mFlags = header[5]; 519ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 520ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (page->mFlags & ~7) { 521ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // Only bits 0-2 are defined in version 0. 522ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_MALFORMED; 523ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 524ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 525ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mGranulePosition = U64LE_AT(&header[6]); 526ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 527ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0 528ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber printf("granulePosition = %llu (0x%llx)\n", 529ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mGranulePosition, page->mGranulePosition); 530ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif 531ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 532ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mSerialNo = U32LE_AT(&header[14]); 533ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mPageNo = U32LE_AT(&header[18]); 534ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 535ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mNumSegments = header[26]; 536ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mSource->readAt( 537ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber offset + sizeof(header), page->mLace, page->mNumSegments) 538ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber < (ssize_t)page->mNumSegments) { 539ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_IO; 540ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 541ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 542ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t totalSize = 0;; 543ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 544ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber totalSize += page->mLace[i]; 545ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 546ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5475a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#if 0 548ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber String8 tmp; 549ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 550ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char x[32]; 551ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]); 552ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 553ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp.append(x); 554ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 555ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5563856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string()); 5575a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#endif 558ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 559ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return sizeof(header) + page->mNumSegments + totalSize; 560ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 561ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::readNextPacket(MediaBuffer **out) { 563819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih if (mOffset <= mFirstDataOffset && mStartGranulePosition < 0) { 564819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih // The first sample might not start at time 0; find out where by subtracting 565819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih // the number of samples on the first page from the granule position 566819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih // (position of last complete sample) of the first page. This happens 567819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih // the first time before we attempt to read a packet from the first page. 568819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih MediaBuffer *mBuf; 569819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih uint32_t numSamples = 0; 570819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih uint64_t curGranulePosition = 0; 571819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih while (true) { 572819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih status_t err = _readNextPacket(&mBuf, /* calcVorbisTimestamp = */false); 573819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih if (err != OK && err != ERROR_END_OF_STREAM) { 574819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih return err; 575819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } 576819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih // First two pages are header pages. 577819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih if (err == ERROR_END_OF_STREAM || mCurrentPage.mPageNo > 2) { 578819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih break; 579819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } 580819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih curGranulePosition = mCurrentPage.mGranulePosition; 581819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih numSamples += getNumSamplesInPacket(mBuf); 582819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih mBuf->release(); 583819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih mBuf = NULL; 584819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } 585819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih 586819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih if (curGranulePosition > numSamples) { 587819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih mStartGranulePosition = curGranulePosition - numSamples; 588819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } else { 589819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih mStartGranulePosition = 0; 590819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } 591819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih seekToOffset(0); 592819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } 593819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih 5948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih status_t err = _readNextPacket(out, /* calcVorbisTimestamp = */false); 5958c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (err != OK) { 5968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return err; 5978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 5988c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 5998c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t currentPageSamples; 6008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // Calculate timestamps by accumulating durations starting from the first sample of a page; 6018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // We assume that we only seek to page boundaries. 6028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if ((*out)->meta_data()->findInt32(kKeyValidSamples, ¤tPageSamples)) { 6038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // first packet in page 604819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih if (mOffset == mFirstDataOffset) { 605819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih currentPageSamples -= mStartGranulePosition; 606819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih (*out)->meta_data()->setInt32(kKeyValidSamples, currentPageSamples); 607819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } 6088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mCurGranulePosition = mCurrentPage.mGranulePosition - currentPageSamples; 6098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 6108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int64_t timeUs = getTimeUsOfGranule(mCurGranulePosition); 6128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih (*out)->meta_data()->setInt64(kKeyTime, timeUs); 6138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint32_t frames = getNumSamplesInPacket(*out); 6158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mCurGranulePosition += frames; 6168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return OK; 6178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih} 6188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihuint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBuffer *buffer) const { 6208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (buffer == NULL || buffer->range_length() < 1) { 6218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return 0; 6228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 6238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint8_t *data = (uint8_t *)buffer->data() + buffer->range_offset(); 6258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint8_t toc = data[0]; 6268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint8_t config = (toc >> 3) & 0x1f; 6278c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint32_t frameSizesUs[] = { 6288c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10000, 20000, 40000, 60000, // 0...3 6298c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10000, 20000, 40000, 60000, // 4...7 6308c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10000, 20000, 40000, 60000, // 8...11 6318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10000, 20000, // 12...13 6328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10000, 20000, // 14...15 6338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2500, 5000, 10000, 20000, // 16...19 6348c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2500, 5000, 10000, 20000, // 20...23 6358c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2500, 5000, 10000, 20000, // 24...27 6368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2500, 5000, 10000, 20000 // 28...31 6378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih }; 6388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint32_t frameSizeUs = frameSizesUs[config]; 6398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint32_t numFrames; 6418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint8_t c = toc & 3; 6428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih switch (c) { 6438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih case 0: 6448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih numFrames = 1; 6458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih break; 6468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih case 1: 6478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih case 2: 6488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih numFrames = 2; 6498c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih break; 6508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih case 3: 6518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (buffer->range_length() < 3) { 6528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih numFrames = 0; 6538c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } else { 6548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih numFrames = data[2] & 0x3f; 6558c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 6568c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih break; 6578c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih default: 6588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih TRESPASS(); 6598c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 6608c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6618c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint32_t numSamples = frameSizeUs * numFrames * kOpusSampleRate / 1000000; 6628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return numSamples; 6638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih} 6648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::_readNextPacket(MediaBuffer **out, bool calcVorbisTimestamp) { 666ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = NULL; 667ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 668ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer = NULL; 669ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t timeUs = -1; 670ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 671ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (;;) { 672ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t i; 673ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t packetSize = 0; 674ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber bool gotFullPacket = false; 675ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) { 676ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t lace = mCurrentPage.mLace[i]; 677ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 678ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packetSize += lace; 679ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 680ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (lace < 255) { 681ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber gotFullPacket = true; 682ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ++i; 683ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 684ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 685ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 686ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 687ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mNextLaceIndex < mCurrentPage.mNumSegments) { 688c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments; 689ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t j = 0; j < mNextLaceIndex; ++j) { 690ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber dataOffset += mCurrentPage.mLace[j]; 691ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 692ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 693ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t fullSize = packetSize; 694ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 695ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber fullSize += buffer->range_length(); 696ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 697ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *tmp = new MediaBuffer(fullSize); 698ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 699ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber memcpy(tmp->data(), buffer->data(), buffer->range_length()); 700ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp->set_range(0, buffer->range_length()); 701ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->release(); 702ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber } else { 703ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp->set_range(0, 0); 704ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 705ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer = tmp; 706ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 707ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = mSource->readAt( 708ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber dataOffset, 709ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber (uint8_t *)buffer->data() + buffer->range_length(), 710ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packetSize); 711ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 712ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n < (ssize_t)packetSize) { 713ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar ALOGV("failed to read %zu bytes at %#016llx, got %zd bytes", 714ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar packetSize, (long long)dataOffset, n); 715ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_IO; 716ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 717ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 718ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->set_range(0, fullSize); 719ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 720ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = i; 721ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 722ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (gotFullPacket) { 723ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // We've just read the entire packet. 724ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 725db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (mFirstPacketInPage) { 726db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber buffer->meta_data()->setInt32( 727db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber kKeyValidSamples, mCurrentPageSamples); 728db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = false; 729db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 730db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 7318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (calcVorbisTimestamp) { 7328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t curBlockSize = getPacketBlockSize(buffer); 7337a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen if (mCurrentPage.mPrevPacketSize < 0) { 7347a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen mCurrentPage.mPrevPacketSize = curBlockSize; 7357a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen mCurrentPage.mPrevPacketPos = 7367a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen mCurrentPage.mGranulePosition - mCurrentPageSamples; 7377a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate; 7387a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen } else { 7397a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen // The effective block size is the average of the two overlapped blocks 7407a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen int32_t actualBlockSize = 7417a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen (curBlockSize + mCurrentPage.mPrevPacketSize) / 2; 7427a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate; 7437a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen // The actual size output by the decoder will be half the effective 7447a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen // size, due to the overlap 7457a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen mCurrentPage.mPrevPacketPos += actualBlockSize / 2; 7467a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen mCurrentPage.mPrevPacketSize = curBlockSize; 7477a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen } 7487a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen buffer->meta_data()->setInt64(kKeyTime, timeUs); 7497a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen } 750ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = buffer; 751ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 752ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 753ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 754ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 755ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // fall through, the buffer now contains the start of the packet. 756ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 757ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 758ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments); 759ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 760ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset += mCurrentPageSize; 761ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = readPage(mOffset, &mCurrentPage); 762ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 763ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n <= 0) { 764ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer) { 765ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->release(); 766ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer = NULL; 767ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 768ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 769a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("readPage returned %zd", n); 770ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 771ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; 772ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 773ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 774db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPageSamples = 775db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPage.mGranulePosition - mPrevGranulePosition; 776db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = true; 777db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 778db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mPrevGranulePosition = mCurrentPage.mGranulePosition; 779db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 780ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize = n; 781ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = 0; 782ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 783ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 784ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if ((mCurrentPage.mFlags & 1) == 0) { 785ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // This page does not continue the packet, i.e. the packet 786ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // is already complete. 787ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 788ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (timeUs >= 0) { 789ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 790ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 791ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 792db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber buffer->meta_data()->setInt32( 793db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber kKeyValidSamples, mCurrentPageSamples); 794db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = false; 795db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 796ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = buffer; 797ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 798ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 799ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 800ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 801ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 802ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 803ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 8048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::init() { 805ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta = new MetaData; 8068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMeta->setCString(kKeyMIMEType, mMimeType); 807ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 8085a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber status_t err; 8098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih MediaBuffer *packet; 8108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih for (size_t i = 0; i < mNumHeaders; ++i) { 8118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // ignore timestamp for configuration packets 8128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != OK) { 8138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return err; 8148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 8158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ALOGV("read packet of size %zu\n", packet->range_length()); 8168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih err = verifyHeader(packet, /* type = */ i * 2 + 1); 8178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih packet->release(); 8188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih packet = NULL; 8198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (err != OK) { 8208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return err; 8218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 8225a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 82396f52cde23982f668592418a9548045237d5e327Andreas Huber 82496f52cde23982f668592418a9548045237d5e327Andreas Huber mFirstDataOffset = mOffset + mCurrentPageSize; 8255a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber 8263fd91baee812919f53a85c5c05f32606313f8334Andreas Huber off64_t size; 8273fd91baee812919f53a85c5c05f32606313f8334Andreas Huber uint64_t lastGranulePosition; 8283fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (!(mSource->flags() & DataSource::kIsCachingDataSource) 8293fd91baee812919f53a85c5c05f32606313f8334Andreas Huber && mSource->getSize(&size) == OK 8303fd91baee812919f53a85c5c05f32606313f8334Andreas Huber && findPrevGranulePosition(size, &lastGranulePosition) == OK) { 8313fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // Let's assume it's cheap to seek to the end. 8323fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // The granule position of the final page in the stream will 8333fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // give us the exact duration of the content, something that 8343fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // we can only approximate using avg. bitrate if seeking to 8353fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // the end is too expensive or impossible (live streaming). 8363fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int64_t durationUs = getTimeUsOfGranule(lastGranulePosition); 8383fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8393fd91baee812919f53a85c5c05f32606313f8334Andreas Huber mMeta->setInt64(kKeyDuration, durationUs); 8403fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8413fd91baee812919f53a85c5c05f32606313f8334Andreas Huber buildTableOfContents(); 8423fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 8433fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8445a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return OK; 845ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 846ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 8478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihvoid MyOggExtractor::buildTableOfContents() { 8483fd91baee812919f53a85c5c05f32606313f8334Andreas Huber off64_t offset = mFirstDataOffset; 8493fd91baee812919f53a85c5c05f32606313f8334Andreas Huber Page page; 8503fd91baee812919f53a85c5c05f32606313f8334Andreas Huber ssize_t pageSize; 8513fd91baee812919f53a85c5c05f32606313f8334Andreas Huber while ((pageSize = readPage(offset, &page)) > 0) { 8523fd91baee812919f53a85c5c05f32606313f8334Andreas Huber mTableOfContents.push(); 8533fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8543fd91baee812919f53a85c5c05f32606313f8334Andreas Huber TOCEntry &entry = 8553fd91baee812919f53a85c5c05f32606313f8334Andreas Huber mTableOfContents.editItemAt(mTableOfContents.size() - 1); 8563fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8573fd91baee812919f53a85c5c05f32606313f8334Andreas Huber entry.mPageOffset = offset; 8588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih entry.mTimeUs = getTimeUsOfGranule(page.mGranulePosition); 8593fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8603fd91baee812919f53a85c5c05f32606313f8334Andreas Huber offset += (size_t)pageSize; 8613fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 8623fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8633fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // Limit the maximum amount of RAM we spend on the table of contents, 8643fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // if necessary thin out the table evenly to trim it down to maximum 8653fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // size. 8663fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8673fd91baee812919f53a85c5c05f32606313f8334Andreas Huber static const size_t kMaxTOCSize = 8192; 8683fd91baee812919f53a85c5c05f32606313f8334Andreas Huber static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry); 8693fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8703fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t numerator = mTableOfContents.size(); 8713fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8723fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (numerator > kMaxNumTOCEntries) { 8733fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t denom = numerator - kMaxNumTOCEntries; 8743fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8753fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t accum = 0; 8763fd91baee812919f53a85c5c05f32606313f8334Andreas Huber for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) { 8773fd91baee812919f53a85c5c05f32606313f8334Andreas Huber accum += denom; 8783fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (accum >= numerator) { 8793fd91baee812919f53a85c5c05f32606313f8334Andreas Huber mTableOfContents.removeAt(i); 8803fd91baee812919f53a85c5c05f32606313f8334Andreas Huber accum -= numerator; 8813fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 8823fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 8833fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 8843fd91baee812919f53a85c5c05f32606313f8334Andreas Huber} 8853fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8868c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihint32_t MyOggExtractor::getPacketBlockSize(MediaBuffer *buffer) { 8877a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen const uint8_t *data = 8887a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen (const uint8_t *)buffer->data() + buffer->range_offset(); 8897a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 8907a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen size_t size = buffer->range_length(); 8917a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 8927a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ogg_buffer buf; 8937a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen buf.data = (uint8_t *)data; 8947a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen buf.size = size; 8957a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen buf.refcount = 1; 8967a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen buf.ptr.owner = NULL; 8977a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 8987a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ogg_reference ref; 8997a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ref.buffer = &buf; 9007a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ref.begin = 0; 9017a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ref.length = size; 9027a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ref.next = NULL; 9037a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 9047a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ogg_packet pack; 9057a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen pack.packet = &ref; 9067a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen pack.bytes = ref.length; 9077a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen pack.b_o_s = 0; 9087a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen pack.e_o_s = 0; 9097a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen pack.granulepos = 0; 9107a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen pack.packetno = 0; 9117a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 9127a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen return vorbis_packet_blocksize(&mVi, &pack); 9137a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen} 9147a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 9158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihint64_t MyOpusExtractor::getTimeUsOfGranule(uint64_t granulePos) const { 9168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint64_t pcmSamplePosition = 0; 9178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (granulePos > mCodecDelay) { 9188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih pcmSamplePosition = granulePos - mCodecDelay; 9198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 9208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return pcmSamplePosition * 1000000ll / kOpusSampleRate; 9218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih} 9228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::verifyHeader(MediaBuffer *buffer, uint8_t type) { 9248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih switch (type) { 9258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean 9268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // header and comments such that we can share code with MyVorbisExtractor. 9278c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih case 1: 9288c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return verifyOpusHeader(buffer); 9298c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih case 3: 9308c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return verifyOpusComments(buffer); 9318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih default: 9328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return INVALID_OPERATION; 9338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 9348c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih} 9358c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::verifyOpusHeader(MediaBuffer *buffer) { 9378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const size_t kOpusHeaderSize = 19; 9388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const uint8_t *data = 9398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih (const uint8_t *)buffer->data() + buffer->range_offset(); 9408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih size_t size = buffer->range_length(); 9428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (size < kOpusHeaderSize 9448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih || memcmp(data, "OpusHead", 8) 9458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih || /* version = */ data[8] != 1) { 9468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 9478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 9488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9498c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mChannelCount = data[9]; 9508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mCodecDelay = U16LE_AT(&data[10]); 9518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMeta->setData(kKeyOpusHeader, 0, data, size); 9538c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMeta->setInt32(kKeySampleRate, kOpusSampleRate); 9548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMeta->setInt32(kKeyChannelCount, mChannelCount); 9558c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMeta->setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/); 9568c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMeta->setInt64(kKeyOpusCodecDelay /* ns */, 9578c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mCodecDelay /* sample/s */ * 1000000000 / kOpusSampleRate); 9588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9598c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return OK; 9608c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih} 9618c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::verifyOpusComments(MediaBuffer *buffer) { 9638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // add artificial framing bit so we can reuse _vorbis_unpack_comment 9648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t commentSize = buffer->range_length() + 1; 9658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih sp<ABuffer> aBuf = new ABuffer(commentSize); 9668c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (aBuf->capacity() <= buffer->range_length()) { 9678c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 9688c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 9698c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint8_t* commentData = aBuf->data(); 9718c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih memcpy(commentData, 9728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih (uint8_t *)buffer->data() + buffer->range_offset(), 9738c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buffer->range_length()); 9748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ogg_buffer buf; 9768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.data = commentData; 9778c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.size = commentSize; 9788c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.refcount = 1; 9798c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.ptr.owner = NULL; 9808c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9818c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ogg_reference ref; 9828c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.buffer = &buf; 9838c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.begin = 0; 9848c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.length = commentSize; 9858c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.next = NULL; 9868c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9878c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih oggpack_buffer bits; 9888c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih oggpack_readinit(&bits, &ref); 9898c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9908c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // skip 'OpusTags' 9918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const char *OpusTags = "OpusTags"; 9928c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const int32_t headerLen = strlen(OpusTags); 9938c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t framingBitOffset = headerLen; 9948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih for (int i = 0; i < headerLen; ++i) { 9958c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih char chr = oggpack_read(&bits, 8); 9968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (chr != OpusTags[i]) { 9978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 9988c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 9998c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t vendorLen = oggpack_read(&bits, 32); 10028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih framingBitOffset += 4; 10038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (vendorLen < 0 || vendorLen > commentSize - 8) { 10048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 10058c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // skip vendor string 10078c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih framingBitOffset += vendorLen; 10088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih for (int i = 0; i < vendorLen; ++i) { 10098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih oggpack_read(&bits, 8); 10108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t n = oggpack_read(&bits, 32); 10138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih framingBitOffset += 4; 10148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) { 10158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 10168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih for (int i = 0; i < n; ++i) { 10188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t len = oggpack_read(&bits, 32); 10198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih framingBitOffset += 4; 10208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (len < 0 || len > (commentSize - oggpack_bytes(&bits))) { 10218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 10228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih framingBitOffset += len; 10248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih for (int j = 0; j < len; ++j) { 10258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih oggpack_read(&bits, 8); 10268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10278c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10288c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (framingBitOffset < 0 || framingBitOffset >= commentSize) { 10298c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 10308c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih commentData[framingBitOffset] = 1; 10328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.data = commentData + headerLen; 10348c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.size = commentSize - headerLen; 10358c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.refcount = 1; 10368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.ptr.owner = NULL; 10378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.buffer = &buf; 10398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.begin = 0; 10408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.length = commentSize - headerLen; 10418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.next = NULL; 10428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih oggpack_readinit(&bits, &ref); 10448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int err = _vorbis_unpack_comment(&mVc, &bits); 10458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (0 != err) { 10468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 10478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10498c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih parseFileMetaData(); 10508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return OK; 10518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih} 10528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10535a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huberstatus_t MyVorbisExtractor::verifyHeader( 1054ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer, uint8_t type) { 1055ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber const uint8_t *data = 1056ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 1057ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1058ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t size = buffer->range_length(); 1059ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 10605a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { 10615a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return ERROR_MALFORMED; 10625a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 1063ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1064ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ogg_buffer buf; 1065ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.data = (uint8_t *)data; 1066ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.size = size; 1067ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.refcount = 1; 1068ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.ptr.owner = NULL; 1069ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1070ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ogg_reference ref; 1071ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.buffer = &buf; 1072ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.begin = 0; 1073ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.length = size; 1074ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.next = NULL; 1075ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1076ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_buffer bits; 1077ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_readinit(&bits, &ref); 1078ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1079fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen if (oggpack_read(&bits, 8) != type) { 1080fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen return ERROR_MALFORMED; 1081fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen } 1082ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < 6; ++i) { 1083ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_read(&bits, 8); // skip 'vorbis' 1084ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1085ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1086ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber switch (type) { 1087ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 1: 1088ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 1089fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen if (0 != _vorbis_unpack_info(&mVi, &bits)) { 1090fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen return ERROR_MALFORMED; 1091fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen } 1092ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1093ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setData(kKeyVorbisInfo, 0, data, size); 1094ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setInt32(kKeySampleRate, mVi.rate); 1095ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setInt32(kKeyChannelCount, mVi.channels); 1096ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 10973856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("lower-bitrate = %ld", mVi.bitrate_lower); 10983856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("upper-bitrate = %ld", mVi.bitrate_upper); 10993856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); 11003856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("window-bitrate = %ld", mVi.bitrate_window); 11017a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ALOGV("blocksizes: %d/%d", 11027a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen vorbis_info_blocksize(&mVi, 0), 11037a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen vorbis_info_blocksize(&mVi, 1) 11047a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ); 1105ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1106c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t size; 1107ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mSource->getSize(&size) == OK) { 1108ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint64_t bps = approxBitrate(); 1109f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang if (bps != 0) { 1110f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang mMeta->setInt64(kKeyDuration, size * 8000000ll / bps); 1111f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang } 1112ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1113ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 1114ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1115ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1116ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 3: 1117ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 11185a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (0 != _vorbis_unpack_comment(&mVc, &bits)) { 11195a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return ERROR_MALFORMED; 11205a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 11214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 11224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber parseFileMetaData(); 1123ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 1124ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1125ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1126ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 5: 1127ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 11285a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (0 != _vorbis_unpack_books(&mVi, &bits)) { 11295a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return ERROR_MALFORMED; 11305a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 1131ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1132ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setData(kKeyVorbisBooks, 0, data, size); 1133ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 1134ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1135ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 11365a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber 11375a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return OK; 1138ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1139ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 11408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihuint64_t MyVorbisExtractor::approxBitrate() const { 1141ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mVi.bitrate_nominal != 0) { 1142ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mVi.bitrate_nominal; 1143ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1144ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1145ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return (mVi.bitrate_lower + mVi.bitrate_upper) / 2; 1146ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1147ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 11488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihvoid MyOggExtractor::parseFileMetaData() { 11494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta = new MetaData; 11504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); 11514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1152856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten for (int i = 0; i < mVc.comments; ++i) { 1153856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const char *comment = mVc.user_comments[i]; 1154856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten size_t commentLength = mVc.comment_lengths[i]; 1155856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten parseVorbisComment(mFileMeta, comment, commentLength); 1156df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); 1157856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten } 1158856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten} 1159856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten 1160856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenvoid parseVorbisComment( 1161856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const sp<MetaData> &fileMeta, const char *comment, size_t commentLength) 1162856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten{ 11634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber struct { 11644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber const char *const mTag; 11654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t mKey; 11664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } kMap[] = { 11674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "TITLE", kKeyTitle }, 11684595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "ARTIST", kKeyArtist }, 116911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { "ALBUMARTIST", kKeyAlbumArtist }, 117011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { "ALBUM ARTIST", kKeyAlbumArtist }, 117111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { "COMPILATION", kKeyCompilation }, 11724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "ALBUM", kKeyAlbum }, 11734595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "COMPOSER", kKeyComposer }, 11744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "GENRE", kKeyGenre }, 11754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "AUTHOR", kKeyAuthor }, 11764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "TRACKNUMBER", kKeyCDTrackNumber }, 11774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "DISCNUMBER", kKeyDiscNumber }, 11784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "DATE", kKeyDate }, 117975c6d4267db3cca1d06292cae09a40e2d1fcedbdAndreas Lillvik { "YEAR", kKeyYear }, 11804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "LYRICIST", kKeyWriter }, 11814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, 11828ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber { "ANDROID_LOOP", kKeyAutoLoop }, 11834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber }; 11844595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 11854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { 11864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t tagLen = strlen(kMap[j].mTag); 11874595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (!strncasecmp(kMap[j].mTag, comment, tagLen) 11884595be952e3b1d6776a023e3f447c057797f1505Andreas Huber && comment[tagLen] == '=') { 11894595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (kMap[j].mKey == kKeyAlbumArt) { 11904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber extractAlbumArt( 1191856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta, 11924595be952e3b1d6776a023e3f447c057797f1505Andreas Huber &comment[tagLen + 1], 1193856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten commentLength - tagLen - 1); 11948ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber } else if (kMap[j].mKey == kKeyAutoLoop) { 11958ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber if (!strcasecmp(&comment[tagLen + 1], "true")) { 1196856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setInt32(kKeyAutoLoop, true); 11978ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber } 11984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else { 1199856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); 12004595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 12054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1206856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt( 1207856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const sp<MetaData> &fileMeta, const void *data, size_t size) { 12083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("extractAlbumArt from '%s'", (const char *)data); 12094595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 121074814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size)); 121174814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim if (flacBuffer == NULL) { 121229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("malformed base64 encoded data."); 12134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return; 12144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 121674814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim size_t flacSize = flacBuffer->size(); 121774814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim uint8_t *flac = flacBuffer->data(); 1218a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("got flac of size %zu", flacSize); 12194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t picType; 12214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t typeLen; 12224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t descLen; 12234595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t dataLen; 12244595be952e3b1d6776a023e3f447c057797f1505Andreas Huber char type[128]; 12254595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12264595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 8) { 122774814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim return; 12284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12294595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12304595be952e3b1d6776a023e3f447c057797f1505Andreas Huber picType = U32_AT(flac); 12314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (picType != 3) { 12334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber // This is not a front cover. 123474814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim return; 12354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12364595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12374595be952e3b1d6776a023e3f447c057797f1505Andreas Huber typeLen = U32_AT(&flac[4]); 1238c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen if (typeLen > sizeof(type) - 1) { 123974814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim return; 12404595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12414595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1242c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen // we've already checked above that flacSize >= 8 1243c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen if (flacSize - 8 < typeLen) { 124474814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim return; 12454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12464595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12474595be952e3b1d6776a023e3f447c057797f1505Andreas Huber memcpy(type, &flac[8], typeLen); 12484595be952e3b1d6776a023e3f447c057797f1505Andreas Huber type[typeLen] = '\0'; 12494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12503856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("picType = %d, type = '%s'", picType, type); 12514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (!strcmp(type, "-->")) { 12534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber // This is not inline cover art, but an external url instead. 125474814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim return; 12554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12574595be952e3b1d6776a023e3f447c057797f1505Andreas Huber descLen = U32_AT(&flac[8 + typeLen]); 12584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1259c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen if (flacSize < 32 || 1260c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen flacSize - 32 < typeLen || 1261c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen flacSize - 32 - typeLen < descLen) { 126274814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim return; 12634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12644595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]); 12664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1267c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen 1268c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0 1269c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen if (flacSize - 32 - typeLen - descLen < dataLen) { 127074814b70482b3b9eb7f5d979b1d8f76a6eb56667Wonsik Kim return; 12714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12724595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1273a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("got image data, %zu trailing bytes", 12744595be952e3b1d6776a023e3f447c057797f1505Andreas Huber flacSize - 32 - typeLen - descLen - dataLen); 12754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1276856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setData( 12774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen); 12784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1279856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setCString(kKeyAlbumArtMIME, type); 12804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 12814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1282ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 1283ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1284ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source) 1285ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mDataSource(source), 1286ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mInitCheck(NO_INIT), 1287ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl(NULL) { 12888c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih for (int i = 0; i < 2; ++i) { 12898c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (mImpl != NULL) { 12908c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih delete mImpl; 12918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 12928c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (i == 0) { 12938c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mImpl = new MyVorbisExtractor(mDataSource); 12948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } else { 12958c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mImpl = new MyOpusExtractor(mDataSource); 12968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 12978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mInitCheck = mImpl->seekToOffset(0); 1298ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 12998c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (mInitCheck == OK) { 13008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mInitCheck = mImpl->init(); 13018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (mInitCheck == OK) { 13028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih break; 13038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 13048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 13055a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 1306ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1307ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1308ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::~OggExtractor() { 1309ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber delete mImpl; 1310ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl = NULL; 1311ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1312ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1313ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersize_t OggExtractor::countTracks() { 1314ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mInitCheck != OK ? 0 : 1; 1315ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1316ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1317ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MediaSource> OggExtractor::getTrack(size_t index) { 1318ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (index >= 1) { 1319ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return NULL; 1320ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1321ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1322ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return new OggSource(this); 1323ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1324ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1325ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData( 132684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber size_t index, uint32_t /* flags */) { 1327ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (index >= 1) { 1328ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return NULL; 1329ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1330ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1331ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mImpl->getFormat(); 1332ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1333ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1334ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getMetaData() { 13354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return mImpl->getFileMetaData(); 1336ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1337ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1338ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberbool SniffOgg( 13395a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 13405a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 1341ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char tmp[4]; 1342ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) { 1343ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return false; 1344ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1345ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1346ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG); 1347ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *confidence = 0.2f; 1348ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1349ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return true; 1350ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1351ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1352ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} // namespace android 1353