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> 2659acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik 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 { 182894aa94e101f9ff9a074f2bcc4d1fb989cf9ea04Chad Brubaker if (granulePos > INT64_MAX / 1000000ll) { 183894aa94e101f9ff9a074f2bcc4d1fb989cf9ea04Chad Brubaker return INT64_MAX; 184894aa94e101f9ff9a074f2bcc4d1fb989cf9ea04Chad Brubaker } 1858c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return granulePos * 1000000ll / mVi.rate; 1868c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 1878c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1888c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type); 1898c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih}; 1908c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstruct MyOpusExtractor : public MyOggExtractor { 1928c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih static const int32_t kOpusSampleRate = 48000; 1938c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih static const int64_t kOpusSeekPreRollUs = 80000; // 80 ms 1948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 1958c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih MyOpusExtractor(const sp<DataSource> &source) 1968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih : MyOggExtractor(source, MEDIA_MIMETYPE_AUDIO_OPUS, /*numHeaders*/ 2, kOpusSeekPreRollUs), 1978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mChannelCount(0), 198819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih mCodecDelay(0), 199819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih mStartGranulePosition(-1) { 2008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 2018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual uint64_t approxBitrate() const { 2038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return 0; 2048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 2058c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual status_t readNextPacket(MediaBuffer **buffer); 2078c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihprotected: 2098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const; 2108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type); 2118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihprivate: 2138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih status_t verifyOpusHeader(MediaBuffer *buffer); 2148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih status_t verifyOpusComments(MediaBuffer *buffer); 2158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint32_t getNumSamplesInPacket(MediaBuffer *buffer) const; 2168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint8_t mChannelCount; 2188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint16_t mCodecDelay; 219819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih int64_t mStartGranulePosition; 220ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber}; 221ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 222856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt( 223856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const sp<MetaData> &fileMeta, const void *data, size_t size); 224856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten 225ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 226ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 227ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor) 228ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mExtractor(extractor), 229ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted(false) { 230ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 231ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 232ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggSource::~OggSource() { 233ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mStarted) { 234ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber stop(); 235ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 236ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 237ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 238ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggSource::getFormat() { 239ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mExtractor->mImpl->getFormat(); 240ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 241ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 24284333e0475bc911adc16417f4ca327c975cf6c36Andreas Huberstatus_t OggSource::start(MetaData * /* params */) { 243ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mStarted) { 244ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return INVALID_OPERATION; 245ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 246ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 247ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted = true; 248ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 249ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 250ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 251ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 252ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::stop() { 253ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mStarted = false; 254ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 255ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 256ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 257ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 258ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberstatus_t OggSource::read( 259ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer **out, const ReadOptions *options) { 260ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = NULL; 261ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 262ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t seekTimeUs; 263abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber ReadOptions::SeekMode mode; 264abd1f4f870925d6776dbe4b930b759a1ab6595caAndreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 2658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih status_t err = mExtractor->mImpl->seekToTime(seekTimeUs); 2668c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (err != OK) { 2678c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return err; 268ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 269ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 270ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 271ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *packet; 2728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih status_t err = mExtractor->mImpl->readNextPacket(&packet); 273ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 274ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (err != OK) { 275ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return err; 276ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 277ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 278ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0 279ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t timeUs; 280ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) { 281df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("found time = %lld us", timeUs); 282ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } else { 283df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block ALOGI("NO time"); 284ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 285ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif 286ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 2878bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber packet->meta_data()->setInt32(kKeyIsSyncFrame, 1); 2888bf59e735760af0b6a85747fd90bf8cf1e5388d7Andreas Huber 289ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = packet; 290ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 291ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 292ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 293ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 294ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 295ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 2968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert ShihMyOggExtractor::MyOggExtractor( 2978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const sp<DataSource> &source, 2988c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const char *mimeType, 2998c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih size_t numHeaders, 3008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int64_t seekPreRollUs) 301ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mSource(source), 302ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset(0), 3038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mCurGranulePosition(0), 304db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mPrevGranulePosition(0), 305ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize(0), 306db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage(true), 307db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPageSamples(0), 30896f52cde23982f668592418a9548045237d5e327Andreas Huber mNextLaceIndex(0), 3098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMimeType(mimeType), 3108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mNumHeaders(numHeaders), 3118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mSeekPreRollUs(seekPreRollUs), 31296f52cde23982f668592418a9548045237d5e327Andreas Huber mFirstDataOffset(-1) { 313ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPage.mNumSegments = 0; 3144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 3154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_info_init(&mVi); 3164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_comment_init(&mVc); 317ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 318ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 3198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert ShihMyOggExtractor::~MyOggExtractor() { 3204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_comment_clear(&mVc); 3214595be952e3b1d6776a023e3f447c057797f1505Andreas Huber vorbis_info_clear(&mVi); 322ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 323ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 3248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihsp<MetaData> MyOggExtractor::getFormat() const { 325ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mMeta; 326ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 327ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 3288c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::findNextPage( 329c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t startOffset, off64_t *pageOffset) { 330ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset = startOffset; 331ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 332ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (;;) { 333ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char signature[4]; 334ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = mSource->readAt(*pageOffset, &signature, 4); 335ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 336ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n < 4) { 337ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *pageOffset = 0; 338ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 339ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM; 340ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 341ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 342ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (!memcmp(signature, "OggS", 4)) { 343ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (*pageOffset > startOffset) { 3443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("skipped %lld bytes of junk to reach next frame", 345ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar (long long)(*pageOffset - startOffset)); 346ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 347ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 348ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 349ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 350ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 351ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ++*pageOffset; 352ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 353ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 354ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 355db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// Given the offset of the "current" page, find the page immediately preceding 356db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// it (if any) and return its granule position. 357db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// To do this we back up from the "current" page's offset until we find any 358db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber// page preceding it and then scan forward to just before the current page. 3598c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::findPrevGranulePosition( 3603fd91baee812919f53a85c5c05f32606313f8334Andreas Huber off64_t pageOffset, uint64_t *granulePos) { 3613fd91baee812919f53a85c5c05f32606313f8334Andreas Huber *granulePos = 0; 3623fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 363c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t prevPageOffset = 0; 364c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t prevGuess = pageOffset; 365db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber for (;;) { 366db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevGuess >= 5000) { 367db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber prevGuess -= 5000; 368db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } else { 369db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber prevGuess = 0; 370db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 371db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 372ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar ALOGV("backing up %lld bytes", (long long)(pageOffset - prevGuess)); 373db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 3743fd91baee812919f53a85c5c05f32606313f8334Andreas Huber status_t err = findNextPage(prevGuess, &prevPageOffset); 3758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (err == ERROR_END_OF_STREAM) { 3768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // We are at the last page and didn't back off enough; 3778c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // back off 5000 bytes more and try again. 3788c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih continue; 3798c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } else if (err != OK) { 3803fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return err; 3813fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 382db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 383db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevPageOffset < pageOffset || prevGuess == 0) { 384db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber break; 385db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 386db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 387db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 388db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevPageOffset == pageOffset) { 389db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // We did not find a page preceding this one. 3903fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return UNKNOWN_ERROR; 391db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 392db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 3933856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("prevPageOffset at %lld, pageOffset at %lld", 394ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar (long long)prevPageOffset, (long long)pageOffset); 395db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 396db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber for (;;) { 397db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber Page prevPage; 398db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber ssize_t n = readPage(prevPageOffset, &prevPage); 399db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 400db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (n <= 0) { 4013fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return (status_t)n; 402db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 403db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 404db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber prevPageOffset += n; 405db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 406db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (prevPageOffset == pageOffset) { 4073fd91baee812919f53a85c5c05f32606313f8334Andreas Huber *granulePos = prevPage.mGranulePosition; 4083fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return OK; 409db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 410db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 411db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber} 412db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 4138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::seekToTime(int64_t timeUs) { 4148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih timeUs -= mSeekPreRollUs; 4158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (timeUs < 0) { 4168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih timeUs = 0; 4178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 4188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 4193fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (mTableOfContents.isEmpty()) { 4203fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // Perform approximate seeking based on avg. bitrate. 4218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint64_t bps = approxBitrate(); 4228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (bps <= 0) { 4238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return INVALID_OPERATION; 4248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 4253fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 4268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih off64_t pos = timeUs * bps / 8000000ll; 4273fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 428ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar ALOGV("seeking to offset %lld", (long long)pos); 4293fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return seekToOffset(pos); 4303fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 4313fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 4323fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t left = 0; 433225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar size_t right_plus_one = mTableOfContents.size(); 434225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar while (left < right_plus_one) { 435225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar size_t center = left + (right_plus_one - left) / 2; 4363fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 4373fd91baee812919f53a85c5c05f32606313f8334Andreas Huber const TOCEntry &entry = mTableOfContents.itemAt(center); 4383fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 4393fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (timeUs < entry.mTimeUs) { 440225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar right_plus_one = center; 4413fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } else if (timeUs > entry.mTimeUs) { 4423fd91baee812919f53a85c5c05f32606313f8334Andreas Huber left = center + 1; 4433fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } else { 444225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar left = center; 4453fd91baee812919f53a85c5c05f32606313f8334Andreas Huber break; 4463fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 4473fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 4483fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 449225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar if (left == mTableOfContents.size()) { 450225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar --left; 451225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar } 452225d5b20409fd400bfa4ed5e9bc1d5babb498471Lajos Molnar 4533fd91baee812919f53a85c5c05f32606313f8334Andreas Huber const TOCEntry &entry = mTableOfContents.itemAt(left); 4543fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 455a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("seeking to entry %zu / %zu at offset %lld", 456ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar left, mTableOfContents.size(), (long long)entry.mPageOffset); 4573fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 4583fd91baee812919f53a85c5c05f32606313f8334Andreas Huber return seekToOffset(entry.mPageOffset); 4593fd91baee812919f53a85c5c05f32606313f8334Andreas Huber} 4603fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 4618c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::seekToOffset(off64_t offset) { 46296f52cde23982f668592418a9548045237d5e327Andreas Huber if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) { 46396f52cde23982f668592418a9548045237d5e327Andreas Huber // Once we know where the actual audio data starts (past the headers) 46496f52cde23982f668592418a9548045237d5e327Andreas Huber // don't ever seek to anywhere before that. 46596f52cde23982f668592418a9548045237d5e327Andreas Huber offset = mFirstDataOffset; 46696f52cde23982f668592418a9548045237d5e327Andreas Huber } 46796f52cde23982f668592418a9548045237d5e327Andreas Huber 468c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t pageOffset; 469ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber status_t err = findNextPage(offset, &pageOffset); 470ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 471ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (err != OK) { 472ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return err; 473ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 474ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 475db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // We found the page we wanted to seek to, but we'll also need 476db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // the page preceding it to determine how many valid samples are on 477db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber // this page. 4783fd91baee812919f53a85c5c05f32606313f8334Andreas Huber findPrevGranulePosition(pageOffset, &mPrevGranulePosition); 479db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 480ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset = pageOffset; 481ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 482ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize = 0; 483db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = true; 484db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mCurrentPageSamples = 0; 485ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPage.mNumSegments = 0; 4867a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen mCurrentPage.mPrevPacketSize = -1; 487ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = 0; 488ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 489ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // XXX what if new page continues packet from last??? 490ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 491ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 492ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 493ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 4948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihssize_t MyOggExtractor::readPage(off64_t offset, Page *page) { 495ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t header[27]; 496df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber ssize_t n; 497df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber if ((n = mSource->readAt(offset, header, sizeof(header))) 498ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber < (ssize_t)sizeof(header)) { 499ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar ALOGV("failed to read %zu bytes at offset %#016llx, got %zd bytes", 500ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar sizeof(header), (long long)offset, n); 501ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 502df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber if (n < 0) { 503df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber return n; 504df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber } else if (n == 0) { 505df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber return ERROR_END_OF_STREAM; 506df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber } else { 507df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber return ERROR_IO; 508df659ac173b247b4ad440fb2979ff51ff45e0aa4Andreas Huber } 509ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 510ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 511ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (memcmp(header, "OggS", 4)) { 512ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_MALFORMED; 513ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 514ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 515ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (header[4] != 0) { 516ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // Wrong version. 517ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 518ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_UNSUPPORTED; 519ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 520ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 521ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mFlags = header[5]; 522ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 523ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (page->mFlags & ~7) { 524ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // Only bits 0-2 are defined in version 0. 525ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_MALFORMED; 526ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 527ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 528ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mGranulePosition = U64LE_AT(&header[6]); 529ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 530ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#if 0 531ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber printf("granulePosition = %llu (0x%llx)\n", 532ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mGranulePosition, page->mGranulePosition); 533ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber#endif 534ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 535ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mSerialNo = U32LE_AT(&header[14]); 536ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mPageNo = U32LE_AT(&header[18]); 537ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 538ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber page->mNumSegments = header[26]; 539ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mSource->readAt( 540ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber offset + sizeof(header), page->mLace, page->mNumSegments) 541ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber < (ssize_t)page->mNumSegments) { 542ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_IO; 543ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 544ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 545ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t totalSize = 0;; 546ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 547ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber totalSize += page->mLace[i]; 548ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 549ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5505a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#if 0 551ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber String8 tmp; 552ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 553ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char x[32]; 554ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]); 555ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 556ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp.append(x); 557ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 558ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5593856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string()); 5605a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber#endif 561ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 562ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return sizeof(header) + page->mNumSegments + totalSize; 563ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 564ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 5658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::readNextPacket(MediaBuffer **out) { 566819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih if (mOffset <= mFirstDataOffset && mStartGranulePosition < 0) { 567819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih // The first sample might not start at time 0; find out where by subtracting 568819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih // the number of samples on the first page from the granule position 569819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih // (position of last complete sample) of the first page. This happens 570819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih // the first time before we attempt to read a packet from the first page. 571819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih MediaBuffer *mBuf; 572819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih uint32_t numSamples = 0; 573819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih uint64_t curGranulePosition = 0; 574819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih while (true) { 575819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih status_t err = _readNextPacket(&mBuf, /* calcVorbisTimestamp = */false); 576819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih if (err != OK && err != ERROR_END_OF_STREAM) { 577819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih return err; 578819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } 579819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih // First two pages are header pages. 580819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih if (err == ERROR_END_OF_STREAM || mCurrentPage.mPageNo > 2) { 581d9b32c160663d04afc5cf91fe2ed893c45074765Dongwon Kang if (mBuf != NULL) { 582d9b32c160663d04afc5cf91fe2ed893c45074765Dongwon Kang mBuf->release(); 583d9b32c160663d04afc5cf91fe2ed893c45074765Dongwon Kang mBuf = NULL; 584d9b32c160663d04afc5cf91fe2ed893c45074765Dongwon Kang } 585819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih break; 586819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } 587819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih curGranulePosition = mCurrentPage.mGranulePosition; 588819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih numSamples += getNumSamplesInPacket(mBuf); 589819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih mBuf->release(); 590819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih mBuf = NULL; 591819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } 592819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih 593819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih if (curGranulePosition > numSamples) { 594819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih mStartGranulePosition = curGranulePosition - numSamples; 595819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } else { 596819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih mStartGranulePosition = 0; 597819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } 598819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih seekToOffset(0); 599819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } 600819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih 6018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih status_t err = _readNextPacket(out, /* calcVorbisTimestamp = */false); 6028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (err != OK) { 6038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return err; 6048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 6058c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t currentPageSamples; 6078c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // Calculate timestamps by accumulating durations starting from the first sample of a page; 6088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // We assume that we only seek to page boundaries. 6098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if ((*out)->meta_data()->findInt32(kKeyValidSamples, ¤tPageSamples)) { 6108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // first packet in page 611819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih if (mOffset == mFirstDataOffset) { 612819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih currentPageSamples -= mStartGranulePosition; 613819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih (*out)->meta_data()->setInt32(kKeyValidSamples, currentPageSamples); 614819bcef03907c8df8fc0fa78c0d43db98279ffa9Robert Shih } 6158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mCurGranulePosition = mCurrentPage.mGranulePosition - currentPageSamples; 6168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 6178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int64_t timeUs = getTimeUsOfGranule(mCurGranulePosition); 6198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih (*out)->meta_data()->setInt64(kKeyTime, timeUs); 6208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint32_t frames = getNumSamplesInPacket(*out); 6228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mCurGranulePosition += frames; 6238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return OK; 6248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih} 6258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihuint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBuffer *buffer) const { 6278c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (buffer == NULL || buffer->range_length() < 1) { 6288c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return 0; 6298c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 6308c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint8_t *data = (uint8_t *)buffer->data() + buffer->range_offset(); 6328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint8_t toc = data[0]; 6338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint8_t config = (toc >> 3) & 0x1f; 6348c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint32_t frameSizesUs[] = { 6358c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10000, 20000, 40000, 60000, // 0...3 6368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10000, 20000, 40000, 60000, // 4...7 6378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10000, 20000, 40000, 60000, // 8...11 6388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10000, 20000, // 12...13 6398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10000, 20000, // 14...15 6408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2500, 5000, 10000, 20000, // 16...19 6418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2500, 5000, 10000, 20000, // 20...23 6428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2500, 5000, 10000, 20000, // 24...27 6438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 2500, 5000, 10000, 20000 // 28...31 6448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih }; 6458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint32_t frameSizeUs = frameSizesUs[config]; 6468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint32_t numFrames; 6488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint8_t c = toc & 3; 6498c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih switch (c) { 6508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih case 0: 6518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih numFrames = 1; 6528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih break; 6538c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih case 1: 6548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih case 2: 6558c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih numFrames = 2; 6568c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih break; 6578c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih case 3: 6588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (buffer->range_length() < 3) { 6598c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih numFrames = 0; 6608c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } else { 6618c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih numFrames = data[2] & 0x3f; 6628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 6638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih break; 6648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih default: 6658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih TRESPASS(); 6668c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 6678c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6688c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint32_t numSamples = frameSizeUs * numFrames * kOpusSampleRate / 1000000; 6698c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return numSamples; 6708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih} 6718c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 6728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::_readNextPacket(MediaBuffer **out, bool calcVorbisTimestamp) { 673ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = NULL; 674ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 675ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer = NULL; 676ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber int64_t timeUs = -1; 677ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 678ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (;;) { 679ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t i; 680ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t packetSize = 0; 681ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber bool gotFullPacket = false; 682ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) { 683ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint8_t lace = mCurrentPage.mLace[i]; 684ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 685ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packetSize += lace; 686ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 687ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (lace < 255) { 688ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber gotFullPacket = true; 689ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ++i; 690ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 691ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 692ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 693ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 694ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mNextLaceIndex < mCurrentPage.mNumSegments) { 695c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments; 696ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t j = 0; j < mNextLaceIndex; ++j) { 697ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber dataOffset += mCurrentPage.mLace[j]; 698ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 699ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 700ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t fullSize = packetSize; 701ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 702ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber fullSize += buffer->range_length(); 703ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 7041f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen if (fullSize > 16 * 1024 * 1024) { // arbitrary limit of 16 MB packet size 7051f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen if (buffer != NULL) { 7061f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen buffer->release(); 7071f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen } 7081f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen ALOGE("b/36592202"); 7091f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen return ERROR_MALFORMED; 7101f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen } 7111f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen MediaBuffer *tmp = new (std::nothrow) MediaBuffer(fullSize); 7121f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen if (tmp == NULL) { 7131f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen if (buffer != NULL) { 7141f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen buffer->release(); 7151f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen } 7161f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen ALOGE("b/36592202"); 7171f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen return ERROR_MALFORMED; 7181f418f10f4319fc829360b7efee7fca4b3880867Marco Nelissen } 719ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 720ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber memcpy(tmp->data(), buffer->data(), buffer->range_length()); 721ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp->set_range(0, buffer->range_length()); 722ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->release(); 723ecaccb9f82dd07b29aa32ce36e8d15862dfdf547Andreas Huber } else { 724ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber tmp->set_range(0, 0); 725ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 726ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer = tmp; 727ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 728ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = mSource->readAt( 729ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber dataOffset, 730ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber (uint8_t *)buffer->data() + buffer->range_length(), 731ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber packetSize); 732ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 733ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n < (ssize_t)packetSize) { 734a6f2946f15be11db7c2b013fbe69126a799cbf97Wei Jia buffer->release(); 735ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar ALOGV("failed to read %zu bytes at %#016llx, got %zd bytes", 736ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar packetSize, (long long)dataOffset, n); 737ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return ERROR_IO; 738ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 739ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 740ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->set_range(0, fullSize); 741ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 742ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = i; 743ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 744ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (gotFullPacket) { 745ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // We've just read the entire packet. 746ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 747db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber if (mFirstPacketInPage) { 748db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber buffer->meta_data()->setInt32( 749db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber kKeyValidSamples, mCurrentPageSamples); 750db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = false; 751db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber } 752db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 7538c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (calcVorbisTimestamp) { 7548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t curBlockSize = getPacketBlockSize(buffer); 7557a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen if (mCurrentPage.mPrevPacketSize < 0) { 7567a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen mCurrentPage.mPrevPacketSize = curBlockSize; 7577a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen mCurrentPage.mPrevPacketPos = 7587a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen mCurrentPage.mGranulePosition - mCurrentPageSamples; 7597a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate; 7607a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen } else { 7617a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen // The effective block size is the average of the two overlapped blocks 7627a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen int32_t actualBlockSize = 7637a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen (curBlockSize + mCurrentPage.mPrevPacketSize) / 2; 7647a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate; 7657a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen // The actual size output by the decoder will be half the effective 7667a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen // size, due to the overlap 7677a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen mCurrentPage.mPrevPacketPos += actualBlockSize / 2; 7687a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen mCurrentPage.mPrevPacketSize = curBlockSize; 7697a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen } 7707a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen buffer->meta_data()->setInt64(kKeyTime, timeUs); 7717a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen } 772ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = buffer; 773ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 774ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 775ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 776ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 777ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // fall through, the buffer now contains the start of the packet. 778ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 779ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 780ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments); 781ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 782ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mOffset += mCurrentPageSize; 783ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ssize_t n = readPage(mOffset, &mCurrentPage); 784ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 785ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (n <= 0) { 786ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer) { 787ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->release(); 788ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer = NULL; 789ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 790ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 791a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("readPage returned %zd", n); 792ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 793ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; 794ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 795ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 7962369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker // Prevent a harmless unsigned integer overflow by clamping to 0 7972369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker if (mCurrentPage.mGranulePosition >= mPrevGranulePosition) { 7982369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker mCurrentPageSamples = 7992369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker mCurrentPage.mGranulePosition - mPrevGranulePosition; 8002369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker } else { 8012369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker mCurrentPageSamples = 0; 8022369bda581ddd379296b57098e119afb0cfa0952Chad Brubaker } 803db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = true; 804db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 805db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mPrevGranulePosition = mCurrentPage.mGranulePosition; 806db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 807ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mCurrentPageSize = n; 808ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mNextLaceIndex = 0; 809ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 810ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (buffer != NULL) { 811ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if ((mCurrentPage.mFlags & 1) == 0) { 812ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // This page does not continue the packet, i.e. the packet 813ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber // is already complete. 814ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 815ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (timeUs >= 0) { 816ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 817ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 818ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 819db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber buffer->meta_data()->setInt32( 820db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber kKeyValidSamples, mCurrentPageSamples); 821db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber mFirstPacketInPage = false; 822db6222212528637d8f2afa7f49fc3c8c915bafbeAndreas Huber 823ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *out = buffer; 824ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 825ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return OK; 826ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 827ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 828ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 829ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 830ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 8318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOggExtractor::init() { 832ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta = new MetaData; 8338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMeta->setCString(kKeyMIMEType, mMimeType); 834ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 8355a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber status_t err; 8368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih MediaBuffer *packet; 8378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih for (size_t i = 0; i < mNumHeaders; ++i) { 8388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // ignore timestamp for configuration packets 8398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != OK) { 8408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return err; 8418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 8428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ALOGV("read packet of size %zu\n", packet->range_length()); 8438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih err = verifyHeader(packet, /* type = */ i * 2 + 1); 8448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih packet->release(); 8458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih packet = NULL; 8468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (err != OK) { 8478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return err; 8488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 8495a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 85096f52cde23982f668592418a9548045237d5e327Andreas Huber 85196f52cde23982f668592418a9548045237d5e327Andreas Huber mFirstDataOffset = mOffset + mCurrentPageSize; 8525a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber 8533fd91baee812919f53a85c5c05f32606313f8334Andreas Huber off64_t size; 8543fd91baee812919f53a85c5c05f32606313f8334Andreas Huber uint64_t lastGranulePosition; 8553fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (!(mSource->flags() & DataSource::kIsCachingDataSource) 8563fd91baee812919f53a85c5c05f32606313f8334Andreas Huber && mSource->getSize(&size) == OK 8573fd91baee812919f53a85c5c05f32606313f8334Andreas Huber && findPrevGranulePosition(size, &lastGranulePosition) == OK) { 8583fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // Let's assume it's cheap to seek to the end. 8593fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // The granule position of the final page in the stream will 8603fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // give us the exact duration of the content, something that 8613fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // we can only approximate using avg. bitrate if seeking to 8623fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // the end is too expensive or impossible (live streaming). 8633fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int64_t durationUs = getTimeUsOfGranule(lastGranulePosition); 8653fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8663fd91baee812919f53a85c5c05f32606313f8334Andreas Huber mMeta->setInt64(kKeyDuration, durationUs); 8673fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8683fd91baee812919f53a85c5c05f32606313f8334Andreas Huber buildTableOfContents(); 8693fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 8703fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8715a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return OK; 872ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 873ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 8748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihvoid MyOggExtractor::buildTableOfContents() { 8753fd91baee812919f53a85c5c05f32606313f8334Andreas Huber off64_t offset = mFirstDataOffset; 8763fd91baee812919f53a85c5c05f32606313f8334Andreas Huber Page page; 8773fd91baee812919f53a85c5c05f32606313f8334Andreas Huber ssize_t pageSize; 8783fd91baee812919f53a85c5c05f32606313f8334Andreas Huber while ((pageSize = readPage(offset, &page)) > 0) { 8793fd91baee812919f53a85c5c05f32606313f8334Andreas Huber mTableOfContents.push(); 8803fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8813fd91baee812919f53a85c5c05f32606313f8334Andreas Huber TOCEntry &entry = 8823fd91baee812919f53a85c5c05f32606313f8334Andreas Huber mTableOfContents.editItemAt(mTableOfContents.size() - 1); 8833fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8843fd91baee812919f53a85c5c05f32606313f8334Andreas Huber entry.mPageOffset = offset; 8858c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih entry.mTimeUs = getTimeUsOfGranule(page.mGranulePosition); 8863fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8873fd91baee812919f53a85c5c05f32606313f8334Andreas Huber offset += (size_t)pageSize; 8883fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 8893fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8903fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // Limit the maximum amount of RAM we spend on the table of contents, 8913fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // if necessary thin out the table evenly to trim it down to maximum 8923fd91baee812919f53a85c5c05f32606313f8334Andreas Huber // size. 8933fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8943fd91baee812919f53a85c5c05f32606313f8334Andreas Huber static const size_t kMaxTOCSize = 8192; 8953fd91baee812919f53a85c5c05f32606313f8334Andreas Huber static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry); 8963fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8973fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t numerator = mTableOfContents.size(); 8983fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 8993fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (numerator > kMaxNumTOCEntries) { 9003fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t denom = numerator - kMaxNumTOCEntries; 9013fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 9023fd91baee812919f53a85c5c05f32606313f8334Andreas Huber size_t accum = 0; 9033fd91baee812919f53a85c5c05f32606313f8334Andreas Huber for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) { 9043fd91baee812919f53a85c5c05f32606313f8334Andreas Huber accum += denom; 9053fd91baee812919f53a85c5c05f32606313f8334Andreas Huber if (accum >= numerator) { 9063fd91baee812919f53a85c5c05f32606313f8334Andreas Huber mTableOfContents.removeAt(i); 9073fd91baee812919f53a85c5c05f32606313f8334Andreas Huber accum -= numerator; 9083fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 9093fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 9103fd91baee812919f53a85c5c05f32606313f8334Andreas Huber } 9113fd91baee812919f53a85c5c05f32606313f8334Andreas Huber} 9123fd91baee812919f53a85c5c05f32606313f8334Andreas Huber 9138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihint32_t MyOggExtractor::getPacketBlockSize(MediaBuffer *buffer) { 9147a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen const uint8_t *data = 9157a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen (const uint8_t *)buffer->data() + buffer->range_offset(); 9167a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 9177a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen size_t size = buffer->range_length(); 9187a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 9197a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ogg_buffer buf; 9207a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen buf.data = (uint8_t *)data; 9217a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen buf.size = size; 9227a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen buf.refcount = 1; 9237a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen buf.ptr.owner = NULL; 9247a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 9257a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ogg_reference ref; 9267a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ref.buffer = &buf; 9277a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ref.begin = 0; 9287a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ref.length = size; 9297a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ref.next = NULL; 9307a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 9317a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ogg_packet pack; 9327a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen pack.packet = &ref; 9337a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen pack.bytes = ref.length; 9347a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen pack.b_o_s = 0; 9357a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen pack.e_o_s = 0; 9367a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen pack.granulepos = 0; 9377a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen pack.packetno = 0; 9387a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 9397a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen return vorbis_packet_blocksize(&mVi, &pack); 9407a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen} 9417a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen 9428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihint64_t MyOpusExtractor::getTimeUsOfGranule(uint64_t granulePos) const { 9438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint64_t pcmSamplePosition = 0; 9448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (granulePos > mCodecDelay) { 9458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih pcmSamplePosition = granulePos - mCodecDelay; 9468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 947894aa94e101f9ff9a074f2bcc4d1fb989cf9ea04Chad Brubaker if (pcmSamplePosition > INT64_MAX / 1000000ll) { 948894aa94e101f9ff9a074f2bcc4d1fb989cf9ea04Chad Brubaker return INT64_MAX; 949894aa94e101f9ff9a074f2bcc4d1fb989cf9ea04Chad Brubaker } 9508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return pcmSamplePosition * 1000000ll / kOpusSampleRate; 9518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih} 9528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9538c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::verifyHeader(MediaBuffer *buffer, uint8_t type) { 9548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih switch (type) { 9558c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean 9568c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // header and comments such that we can share code with MyVorbisExtractor. 9578c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih case 1: 9588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return verifyOpusHeader(buffer); 9598c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih case 3: 9608c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return verifyOpusComments(buffer); 9618c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih default: 9628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return INVALID_OPERATION; 9638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 9648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih} 9658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9668c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::verifyOpusHeader(MediaBuffer *buffer) { 9678c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const size_t kOpusHeaderSize = 19; 9688c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const uint8_t *data = 9698c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih (const uint8_t *)buffer->data() + buffer->range_offset(); 9708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9718c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih size_t size = buffer->range_length(); 9728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9738c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (size < kOpusHeaderSize 9748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih || memcmp(data, "OpusHead", 8) 9758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih || /* version = */ data[8] != 1) { 9768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 9778c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 9788c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9798c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mChannelCount = data[9]; 9808c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mCodecDelay = U16LE_AT(&data[10]); 9818c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9828c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMeta->setData(kKeyOpusHeader, 0, data, size); 9838c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMeta->setInt32(kKeySampleRate, kOpusSampleRate); 9848c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMeta->setInt32(kKeyChannelCount, mChannelCount); 9858c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMeta->setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/); 9868c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mMeta->setInt64(kKeyOpusCodecDelay /* ns */, 9872d93abfb06455176b7f2fcde0d9fd4dfe7a0973cChad Brubaker mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate); 9888c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9898c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return OK; 9908c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih} 9918c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 9928c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihstatus_t MyOpusExtractor::verifyOpusComments(MediaBuffer *buffer) { 9938c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // add artificial framing bit so we can reuse _vorbis_unpack_comment 9948c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t commentSize = buffer->range_length() + 1; 9958c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih sp<ABuffer> aBuf = new ABuffer(commentSize); 9968c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (aBuf->capacity() <= buffer->range_length()) { 9978c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 9988c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 9998c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10008c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih uint8_t* commentData = aBuf->data(); 10018c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih memcpy(commentData, 10028c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih (uint8_t *)buffer->data() + buffer->range_offset(), 10038c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buffer->range_length()); 10048c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10058c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ogg_buffer buf; 10068c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.data = commentData; 10078c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.size = commentSize; 10088c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.refcount = 1; 10098c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.ptr.owner = NULL; 10108c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10118c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ogg_reference ref; 10128c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.buffer = &buf; 10138c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.begin = 0; 10148c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.length = commentSize; 10158c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.next = NULL; 10168c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10178c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih oggpack_buffer bits; 10188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih oggpack_readinit(&bits, &ref); 10198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // skip 'OpusTags' 10218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const char *OpusTags = "OpusTags"; 10228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih const int32_t headerLen = strlen(OpusTags); 10238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t framingBitOffset = headerLen; 10248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih for (int i = 0; i < headerLen; ++i) { 10258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih char chr = oggpack_read(&bits, 8); 10268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (chr != OpusTags[i]) { 10278c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 10288c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10298c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10308c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t vendorLen = oggpack_read(&bits, 32); 10328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih framingBitOffset += 4; 10338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (vendorLen < 0 || vendorLen > commentSize - 8) { 10348c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 10358c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10368c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih // skip vendor string 10378c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih framingBitOffset += vendorLen; 10388c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih for (int i = 0; i < vendorLen; ++i) { 10398c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih oggpack_read(&bits, 8); 10408c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10418c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10428c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t n = oggpack_read(&bits, 32); 10438c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih framingBitOffset += 4; 10448c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) { 10458c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 10468c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10478c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih for (int i = 0; i < n; ++i) { 10488c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int32_t len = oggpack_read(&bits, 32); 10498c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih framingBitOffset += 4; 10508c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (len < 0 || len > (commentSize - oggpack_bytes(&bits))) { 10518c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 10528c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10538c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih framingBitOffset += len; 10548c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih for (int j = 0; j < len; ++j) { 10558c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih oggpack_read(&bits, 8); 10568c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10578c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10588c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (framingBitOffset < 0 || framingBitOffset >= commentSize) { 10598c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 10608c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10618c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih commentData[framingBitOffset] = 1; 10628c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10638c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.data = commentData + headerLen; 10648c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.size = commentSize - headerLen; 10658c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.refcount = 1; 10668c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih buf.ptr.owner = NULL; 10678c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10688c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.buffer = &buf; 10698c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.begin = 0; 10708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.length = commentSize - headerLen; 10718c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih ref.next = NULL; 10728c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10738c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih oggpack_readinit(&bits, &ref); 10748c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih int err = _vorbis_unpack_comment(&mVc, &bits); 10758c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (0 != err) { 10768c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return ERROR_MALFORMED; 10778c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 10788c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10798c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih parseFileMetaData(); 10808c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih return OK; 10818c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih} 10828c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih 10835a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huberstatus_t MyVorbisExtractor::verifyHeader( 1084ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber MediaBuffer *buffer, uint8_t type) { 1085ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber const uint8_t *data = 1086ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 1087ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1088ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber size_t size = buffer->range_length(); 1089ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 10905a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { 10915a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return ERROR_MALFORMED; 10925a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 1093ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1094ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ogg_buffer buf; 1095ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.data = (uint8_t *)data; 1096ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.size = size; 1097ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.refcount = 1; 1098ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber buf.ptr.owner = NULL; 1099ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1100ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ogg_reference ref; 1101ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.buffer = &buf; 1102ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.begin = 0; 1103ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.length = size; 1104ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber ref.next = NULL; 1105ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1106ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_buffer bits; 1107ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_readinit(&bits, &ref); 1108ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1109fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen if (oggpack_read(&bits, 8) != type) { 1110fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen return ERROR_MALFORMED; 1111fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen } 1112ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber for (size_t i = 0; i < 6; ++i) { 1113ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber oggpack_read(&bits, 8); // skip 'vorbis' 1114ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1115ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1116ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber switch (type) { 1117ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 1: 1118ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 1119fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen if (0 != _vorbis_unpack_info(&mVi, &bits)) { 1120fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen return ERROR_MALFORMED; 1121fe7186bb1567b5725eb8ce61e3267a1733e90c53Marco Nelissen } 1122ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1123ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setData(kKeyVorbisInfo, 0, data, size); 1124ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setInt32(kKeySampleRate, mVi.rate); 1125ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setInt32(kKeyChannelCount, mVi.channels); 1126ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 11273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("lower-bitrate = %ld", mVi.bitrate_lower); 11283856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("upper-bitrate = %ld", mVi.bitrate_upper); 11293856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); 11303856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("window-bitrate = %ld", mVi.bitrate_window); 11317a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ALOGV("blocksizes: %d/%d", 11327a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen vorbis_info_blocksize(&mVi, 0), 11337a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen vorbis_info_blocksize(&mVi, 1) 11347a493d8578bb00cf10190053a4caf1d07f4e24f7Marco Nelissen ); 1135ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1136c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong off64_t size; 1137ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mSource->getSize(&size) == OK) { 1138ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber uint64_t bps = approxBitrate(); 1139f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang if (bps != 0) { 1140f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang mMeta->setInt64(kKeyDuration, size * 8000000ll / bps); 1141f9fb13966a8e6ba039e88a46d096cd1cce2eb283Dongwon Kang } 1142ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1143ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 1144ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1145ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1146ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 3: 1147ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 11485a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (0 != _vorbis_unpack_comment(&mVc, &bits)) { 11495a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return ERROR_MALFORMED; 11505a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 11514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 11524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber parseFileMetaData(); 1153ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 1154ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1155ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1156ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber case 5: 1157ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber { 11585a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber if (0 != _vorbis_unpack_books(&mVi, &bits)) { 11595a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return ERROR_MALFORMED; 11605a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 1161ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1162ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mMeta->setData(kKeyVorbisBooks, 0, data, size); 1163ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber break; 1164ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1165ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 11665a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber 11675a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber return OK; 1168ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1169ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 11708c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihuint64_t MyVorbisExtractor::approxBitrate() const { 1171ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (mVi.bitrate_nominal != 0) { 1172ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mVi.bitrate_nominal; 1173ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1174ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1175ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return (mVi.bitrate_lower + mVi.bitrate_upper) / 2; 1176ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1177ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 11788c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shihvoid MyOggExtractor::parseFileMetaData() { 11794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta = new MetaData; 11804595be952e3b1d6776a023e3f447c057797f1505Andreas Huber mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); 11814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1182856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten for (int i = 0; i < mVc.comments; ++i) { 1183856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const char *comment = mVc.user_comments[i]; 1184856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten size_t commentLength = mVc.comment_lengths[i]; 1185856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten parseVorbisComment(mFileMeta, comment, commentLength); 1186df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); 1187856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten } 1188856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten} 1189856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten 1190856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenvoid parseVorbisComment( 1191856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const sp<MetaData> &fileMeta, const char *comment, size_t commentLength) 1192856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten{ 11934595be952e3b1d6776a023e3f447c057797f1505Andreas Huber struct { 11944595be952e3b1d6776a023e3f447c057797f1505Andreas Huber const char *const mTag; 11954595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t mKey; 11964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } kMap[] = { 11974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "TITLE", kKeyTitle }, 11984595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "ARTIST", kKeyArtist }, 119911f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { "ALBUMARTIST", kKeyAlbumArtist }, 120011f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { "ALBUM ARTIST", kKeyAlbumArtist }, 120111f8109ad8646d3acd9a0987613229cde59d52c1Marco Nelissen { "COMPILATION", kKeyCompilation }, 12024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "ALBUM", kKeyAlbum }, 12034595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "COMPOSER", kKeyComposer }, 12044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "GENRE", kKeyGenre }, 12054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "AUTHOR", kKeyAuthor }, 12064595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "TRACKNUMBER", kKeyCDTrackNumber }, 12074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "DISCNUMBER", kKeyDiscNumber }, 12084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "DATE", kKeyDate }, 120975c6d4267db3cca1d06292cae09a40e2d1fcedbdAndreas Lillvik { "YEAR", kKeyYear }, 12104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "LYRICIST", kKeyWriter }, 12114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, 12128ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber { "ANDROID_LOOP", kKeyAutoLoop }, 12134595be952e3b1d6776a023e3f447c057797f1505Andreas Huber }; 12144595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12154595be952e3b1d6776a023e3f447c057797f1505Andreas Huber for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { 12164595be952e3b1d6776a023e3f447c057797f1505Andreas Huber size_t tagLen = strlen(kMap[j].mTag); 12174595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (!strncasecmp(kMap[j].mTag, comment, tagLen) 12184595be952e3b1d6776a023e3f447c057797f1505Andreas Huber && comment[tagLen] == '=') { 12194595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (kMap[j].mKey == kKeyAlbumArt) { 12204595be952e3b1d6776a023e3f447c057797f1505Andreas Huber extractAlbumArt( 1221856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta, 12224595be952e3b1d6776a023e3f447c057797f1505Andreas Huber &comment[tagLen + 1], 1223856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten commentLength - tagLen - 1); 12248ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber } else if (kMap[j].mKey == kKeyAutoLoop) { 12258ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber if (!strcasecmp(&comment[tagLen + 1], "true")) { 1226856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setInt32(kKeyAutoLoop, true); 12278ae49d87b98d57d6758b0c51b95e28a6581a79f1Andreas Huber } 12284595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } else { 1229856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); 12304595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12314595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12324595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12334595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12344595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 12354595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1236856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kastenstatic void extractAlbumArt( 1237856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten const sp<MetaData> &fileMeta, const void *data, size_t size) { 12383856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("extractAlbumArt from '%s'", (const char *)data); 12394595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 124059acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim sp<ABuffer> flacBuffer = decodeBase64(AString((const char *)data, size)); 124159acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim if (flacBuffer == NULL) { 124229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block ALOGE("malformed base64 encoded data."); 12434595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return; 12444595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12454595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 124659acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim size_t flacSize = flacBuffer->size(); 124759acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim uint8_t *flac = flacBuffer->data(); 1248a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("got flac of size %zu", flacSize); 12494595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12504595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t picType; 12514595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t typeLen; 12524595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t descLen; 12534595be952e3b1d6776a023e3f447c057797f1505Andreas Huber uint32_t dataLen; 12544595be952e3b1d6776a023e3f447c057797f1505Andreas Huber char type[128]; 12554595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12564595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (flacSize < 8) { 125759acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim return; 12584595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12594595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12604595be952e3b1d6776a023e3f447c057797f1505Andreas Huber picType = U32_AT(flac); 12614595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12624595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (picType != 3) { 12634595be952e3b1d6776a023e3f447c057797f1505Andreas Huber // This is not a front cover. 126459acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim return; 12654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12664595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12674595be952e3b1d6776a023e3f447c057797f1505Andreas Huber typeLen = U32_AT(&flac[4]); 1268c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen if (typeLen > sizeof(type) - 1) { 126959acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim return; 12704595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12714595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1272c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen // we've already checked above that flacSize >= 8 1273c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen if (flacSize - 8 < typeLen) { 127459acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim return; 12754595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12764595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12774595be952e3b1d6776a023e3f447c057797f1505Andreas Huber memcpy(type, &flac[8], typeLen); 12784595be952e3b1d6776a023e3f447c057797f1505Andreas Huber type[typeLen] = '\0'; 12794595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12803856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("picType = %d, type = '%s'", picType, type); 12814595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12824595be952e3b1d6776a023e3f447c057797f1505Andreas Huber if (!strcmp(type, "-->")) { 12834595be952e3b1d6776a023e3f447c057797f1505Andreas Huber // This is not inline cover art, but an external url instead. 128459acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim return; 12854595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12864595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1287a86fef32894a90811c2e175152763bc3994c769fWonsik Kim if (flacSize < 32 || flacSize - 32 < typeLen) { 128859acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim return; 1289a86fef32894a90811c2e175152763bc3994c769fWonsik Kim } 12904595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1291a86fef32894a90811c2e175152763bc3994c769fWonsik Kim descLen = U32_AT(&flac[8 + typeLen]); 1292a86fef32894a90811c2e175152763bc3994c769fWonsik Kim if (flacSize - 32 - typeLen < descLen) { 129359acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim return; 12944595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 12954595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 12964595be952e3b1d6776a023e3f447c057797f1505Andreas Huber dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]); 12974595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1298c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0 1299c63cc509404b9328aedd1be3adc4e87cd07b4eb1Marco Nelissen if (flacSize - 32 - typeLen - descLen < dataLen) { 130059acbe2b82b2678d5614c7bfdd8684521bed23fcWonsik Kim return; 13014595be952e3b1d6776a023e3f447c057797f1505Andreas Huber } 13024595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1303a5750e0dad9e90f2195ce36f2c4457fa04b2b83eMark Salyzyn ALOGV("got image data, %zu trailing bytes", 13044595be952e3b1d6776a023e3f447c057797f1505Andreas Huber flacSize - 32 - typeLen - descLen - dataLen); 13054595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1306856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setData( 13074595be952e3b1d6776a023e3f447c057797f1505Andreas Huber kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen); 13084595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1309856990b491d84b7ed4fefe337485c8997ba9dd02Glenn Kasten fileMeta->setCString(kKeyAlbumArtMIME, type); 13104595be952e3b1d6776a023e3f447c057797f1505Andreas Huber} 13114595be952e3b1d6776a023e3f447c057797f1505Andreas Huber 1312ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber//////////////////////////////////////////////////////////////////////////////// 1313ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1314ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source) 1315ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber : mDataSource(source), 1316ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mInitCheck(NO_INIT), 1317ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl(NULL) { 13188c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih for (int i = 0; i < 2; ++i) { 13198c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (mImpl != NULL) { 13208c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih delete mImpl; 13218c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 13228c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (i == 0) { 13238c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mImpl = new MyVorbisExtractor(mDataSource); 13248c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } else { 13258c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mImpl = new MyOpusExtractor(mDataSource); 13268c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 13278c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mInitCheck = mImpl->seekToOffset(0); 1328ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 13298c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (mInitCheck == OK) { 13308c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih mInitCheck = mImpl->init(); 13318c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih if (mInitCheck == OK) { 13328c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih break; 13338c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 13348c10a80cf1af68f15eb39552ca116ec6f04fc173Robert Shih } 13355a4001ddb2536d65d966970fc0579bf6bd11b5a0Andreas Huber } 1336ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1337ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1338ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas HuberOggExtractor::~OggExtractor() { 1339ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber delete mImpl; 1340ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mImpl = NULL; 1341ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1342ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1343ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersize_t OggExtractor::countTracks() { 1344ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mInitCheck != OK ? 0 : 1; 1345ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1346ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1347b2487f03f12dcafdb801fc0007c8df8412397f44Marco Nelissensp<IMediaSource> OggExtractor::getTrack(size_t index) { 1348ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (index >= 1) { 1349ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return NULL; 1350ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1351ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1352ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return new OggSource(this); 1353ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1354ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1355ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData( 135684333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber size_t index, uint32_t /* flags */) { 1357ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (index >= 1) { 1358ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return NULL; 1359ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1360ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1361ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return mImpl->getFormat(); 1362ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1363ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1364ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Hubersp<MetaData> OggExtractor::getMetaData() { 13654595be952e3b1d6776a023e3f447c057797f1505Andreas Huber return mImpl->getFileMetaData(); 1366ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1367ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1368ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huberbool SniffOgg( 13695a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 13705a1c3529e4fa2f8a11054181294e0ce79fff8dd3Andreas Huber sp<AMessage> *) { 1371ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber char tmp[4]; 1372ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) { 1373ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return false; 1374ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber } 1375ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1376ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG); 1377ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber *confidence = 0.2f; 1378ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1379ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber return true; 1380ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} 1381ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber 1382ee7ff20e69498ebd53dd9717a0f984188341a75eAndreas Huber} // namespace android 1383