OggExtractor.cpp revision 1f7fba1ffbf5922d999ab52130efb73a35e72077
1388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber/* 2388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * Copyright (C) 2010 The Android Open Source Project 3388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * 4388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * you may not use this file except in compliance with the License. 6388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * You may obtain a copy of the License at 7388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * 8388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * 10388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * Unless required by applicable law or agreed to in writing, software 11388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * See the License for the specific language governing permissions and 14388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber * limitations under the License. 15388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber */ 16388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 17388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber//#define LOG_NDEBUG 0 18388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#define LOG_TAG "OggExtractor" 19388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <utils/Log.h> 20388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 21388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include "include/OggExtractor.h" 22388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 23388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <cutils/properties.h> 24388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/DataSource.h> 25388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MediaBuffer.h> 26388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MediaBufferGroup.h> 27388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MediaDebug.h> 28388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MediaDefs.h> 29388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MediaErrors.h> 30388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MediaSource.h> 31388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/MetaData.h> 32388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <media/stagefright/Utils.h> 33388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#include <utils/String8.h> 34388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 35388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberextern "C" { 36388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber #include <Tremolo/codec_internal.h> 37388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 38388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb); 39388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb); 40388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb); 41388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 42388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 43388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubernamespace android { 44388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 45388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstruct OggSource : public MediaSource { 46388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber OggSource(const sp<OggExtractor> &extractor); 47388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 48388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber virtual sp<MetaData> getFormat(); 49388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 50388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber virtual status_t start(MetaData *params = NULL); 51388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber virtual status_t stop(); 52388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 53388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber virtual status_t read( 54388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer **buffer, const ReadOptions *options = NULL); 55388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 56388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberprotected: 57388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber virtual ~OggSource(); 58388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 59388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberprivate: 60388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber sp<OggExtractor> mExtractor; 61388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber bool mStarted; 62388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 63388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber OggSource(const OggSource &); 64388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber OggSource &operator=(const OggSource &); 65388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}; 66388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 67388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstruct MyVorbisExtractor { 68388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MyVorbisExtractor(const sp<DataSource> &source); 69388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber virtual ~MyVorbisExtractor(); 70388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 71388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber sp<MetaData> getFormat() const; 72388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 73388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // Returns an approximate bitrate in bits per second. 74388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint64_t approxBitrate(); 75388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 76388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber status_t seekToOffset(off_t offset); 77388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber status_t readNextPacket(MediaBuffer **buffer); 78388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 79eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber status_t init(); 80388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 81c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber sp<MetaData> getFileMetaData() { return mFileMeta; } 82c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 83388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberprivate: 84388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber struct Page { 85388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint64_t mGranulePosition; 86388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint32_t mSerialNo; 87388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint32_t mPageNo; 88388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint8_t mFlags; 89388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint8_t mNumSegments; 90388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint8_t mLace[255]; 91388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber }; 92388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 93388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber sp<DataSource> mSource; 94388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber off_t mOffset; 95388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber Page mCurrentPage; 96388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t mCurrentPageSize; 97388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t mNextLaceIndex; 98388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 9934c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber off_t mFirstDataOffset; 10034c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber 101388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber vorbis_info mVi; 102388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber vorbis_comment mVc; 103388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 104388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber sp<MetaData> mMeta; 105c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber sp<MetaData> mFileMeta; 106388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 107388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ssize_t readPage(off_t offset, Page *page); 108388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber status_t findNextPage(off_t startOffset, off_t *pageOffset); 109388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 110eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber status_t verifyHeader( 111388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer *buffer, uint8_t type); 112388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 113c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber void parseFileMetaData(); 114c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber void extractAlbumArt(const void *data, size_t size); 115c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 116388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MyVorbisExtractor(const MyVorbisExtractor &); 117388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MyVorbisExtractor &operator=(const MyVorbisExtractor &); 118388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}; 119388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 120388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber//////////////////////////////////////////////////////////////////////////////// 121388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 122388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor) 123388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber : mExtractor(extractor), 124388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mStarted(false) { 125388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 126388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 127388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberOggSource::~OggSource() { 128388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mStarted) { 129388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber stop(); 130388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 131388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 132388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 133388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MetaData> OggSource::getFormat() { 134388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return mExtractor->mImpl->getFormat(); 135388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 136388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 137388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t OggSource::start(MetaData *params) { 138388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mStarted) { 139388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return INVALID_OPERATION; 140388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 141388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 142388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mStarted = true; 143388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 144388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 145388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 146388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 147388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t OggSource::stop() { 148388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mStarted = false; 149388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 150388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 151388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 152388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 153388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t OggSource::read( 154388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer **out, const ReadOptions *options) { 155388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *out = NULL; 156388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 157388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber int64_t seekTimeUs; 1586624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber ReadOptions::SeekMode mode; 1596624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 160388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber off_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll; 161388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGI("seeking to offset %ld", pos); 162388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 163388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mExtractor->mImpl->seekToOffset(pos) != OK) { 164388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_END_OF_STREAM; 165388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 166388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 167388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 168388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer *packet; 169388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber status_t err = mExtractor->mImpl->readNextPacket(&packet); 170388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 171388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (err != OK) { 172388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return err; 173388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 174388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 175388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#if 0 176388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber int64_t timeUs; 177388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) { 178388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGI("found time = %lld us", timeUs); 179388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } else { 180388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGI("NO time"); 181388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 182388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#endif 183388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 184388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *out = packet; 185388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 186388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 187388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 188388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 189388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber//////////////////////////////////////////////////////////////////////////////// 190388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 191388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberMyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source) 192388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber : mSource(source), 193388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mOffset(0), 194388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mCurrentPageSize(0), 19534c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber mNextLaceIndex(0), 19634c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber mFirstDataOffset(-1) { 197388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mCurrentPage.mNumSegments = 0; 198c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 199c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber vorbis_info_init(&mVi); 200c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber vorbis_comment_init(&mVc); 201388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 202388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 203388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberMyVorbisExtractor::~MyVorbisExtractor() { 204c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber vorbis_comment_clear(&mVc); 205c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber vorbis_info_clear(&mVi); 206388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 207388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 208388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MetaData> MyVorbisExtractor::getFormat() const { 209388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return mMeta; 210388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 211388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 212388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t MyVorbisExtractor::findNextPage( 213388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber off_t startOffset, off_t *pageOffset) { 214388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *pageOffset = startOffset; 215388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 216388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (;;) { 217388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber char signature[4]; 218388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ssize_t n = mSource->readAt(*pageOffset, &signature, 4); 219388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 220388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (n < 4) { 221388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *pageOffset = 0; 222388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 223388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM; 224388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 225388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 226388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (!memcmp(signature, "OggS", 4)) { 227388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (*pageOffset > startOffset) { 228388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("skipped %ld bytes of junk to reach next frame", 229388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *pageOffset - startOffset); 230388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 231388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 232388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 233388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 234388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 235388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ++*pageOffset; 236388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 237388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 238388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 239388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t MyVorbisExtractor::seekToOffset(off_t offset) { 24034c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) { 24134c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber // Once we know where the actual audio data starts (past the headers) 24234c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber // don't ever seek to anywhere before that. 24334c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber offset = mFirstDataOffset; 24434c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber } 24534c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber 246388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber off_t pageOffset; 247388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber status_t err = findNextPage(offset, &pageOffset); 248388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 249388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (err != OK) { 250388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return err; 251388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 252388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 253388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mOffset = pageOffset; 254388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 255388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mCurrentPageSize = 0; 256388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mCurrentPage.mNumSegments = 0; 257388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mNextLaceIndex = 0; 258388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 259388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // XXX what if new page continues packet from last??? 260388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 261388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 262388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 263388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 264388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) { 265388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint8_t header[27]; 266388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mSource->readAt(offset, header, sizeof(header)) 267388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber < (ssize_t)sizeof(header)) { 268388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGE("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset); 269388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 270388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_IO; 271388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 272388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 273388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (memcmp(header, "OggS", 4)) { 274388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_MALFORMED; 275388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 276388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 277388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (header[4] != 0) { 278388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // Wrong version. 279388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 280388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_UNSUPPORTED; 281388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 282388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 283388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber page->mFlags = header[5]; 284388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 285388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (page->mFlags & ~7) { 286388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // Only bits 0-2 are defined in version 0. 287388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_MALFORMED; 288388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 289388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 290388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber page->mGranulePosition = U64LE_AT(&header[6]); 291388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 292388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#if 0 293388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber printf("granulePosition = %llu (0x%llx)\n", 294388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber page->mGranulePosition, page->mGranulePosition); 295388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#endif 296388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 297388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber page->mSerialNo = U32LE_AT(&header[14]); 298388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber page->mPageNo = U32LE_AT(&header[18]); 299388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 300388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber page->mNumSegments = header[26]; 301388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mSource->readAt( 302388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber offset + sizeof(header), page->mLace, page->mNumSegments) 303388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber < (ssize_t)page->mNumSegments) { 304388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_IO; 305388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 306388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 307388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t totalSize = 0;; 308388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 309388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber totalSize += page->mLace[i]; 310388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 311388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 312eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber#if 0 313388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber String8 tmp; 314388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 315388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber char x[32]; 316388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]); 317388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 318388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber tmp.append(x); 319388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 320388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 321eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string()); 322eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber#endif 323388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 324388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return sizeof(header) + page->mNumSegments + totalSize; 325388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 326388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 327388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { 328388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *out = NULL; 329388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 330388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer *buffer = NULL; 331388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber int64_t timeUs = -1; 332388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 333388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (;;) { 334388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t i; 335388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t packetSize = 0; 336388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber bool gotFullPacket = false; 337388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) { 338388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint8_t lace = mCurrentPage.mLace[i]; 339388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 340388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packetSize += lace; 341388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 342388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (lace < 255) { 343388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber gotFullPacket = true; 344388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ++i; 345388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber break; 346388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 347388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 348388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 349388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mNextLaceIndex < mCurrentPage.mNumSegments) { 350388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber off_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments; 351388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (size_t j = 0; j < mNextLaceIndex; ++j) { 352388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber dataOffset += mCurrentPage.mLace[j]; 353388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 354388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 355388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t fullSize = packetSize; 356388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (buffer != NULL) { 357388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber fullSize += buffer->range_length(); 358388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 359388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer *tmp = new MediaBuffer(fullSize); 360388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (buffer != NULL) { 361388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber memcpy(tmp->data(), buffer->data(), buffer->range_length()); 362388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber tmp->set_range(0, buffer->range_length()); 363388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer->release(); 3641f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber } else { 365388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // XXX Not only is this not technically the correct time for 366388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // this packet, we also stamp every packet in this page 367388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // with the same time. This needs fixing later. 3681f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber 3691f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber if (mVi.rate) { 3701f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber // Rate may not have been initialized yet if we're currently 3711f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber // reading the configuration packets... 3721f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber // Fortunately, the timestamp doesn't matter for those. 3731f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate; 3741f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber } 375388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber tmp->set_range(0, 0); 376388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 377388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer = tmp; 378388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 379388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ssize_t n = mSource->readAt( 380388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber dataOffset, 381388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber (uint8_t *)buffer->data() + buffer->range_length(), 382388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packetSize); 383388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 384388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (n < (ssize_t)packetSize) { 385388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGE("failed to read %d bytes at 0x%08lx", packetSize, dataOffset); 386388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_IO; 387388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 388388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 389388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer->set_range(0, fullSize); 390388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 391388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mNextLaceIndex = i; 392388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 393388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (gotFullPacket) { 394388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // We've just read the entire packet. 395388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 396388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (timeUs >= 0) { 397388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 398388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 399388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 400388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *out = buffer; 401388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 402388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 403388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 404388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 405388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // fall through, the buffer now contains the start of the packet. 406388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 407388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 408388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments); 409388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 410388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mOffset += mCurrentPageSize; 411388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ssize_t n = readPage(mOffset, &mCurrentPage); 412388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 413388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (n <= 0) { 414388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (buffer) { 415388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer->release(); 416388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer = NULL; 417388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 418388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 419388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGE("readPage returned %ld", n); 420388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 421388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; 422388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 423388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 424388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mCurrentPageSize = n; 425388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mNextLaceIndex = 0; 426388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 427388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (buffer != NULL) { 428388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if ((mCurrentPage.mFlags & 1) == 0) { 429388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // This page does not continue the packet, i.e. the packet 430388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // is already complete. 431388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 432388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (timeUs >= 0) { 433388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 434388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 435388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 436388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *out = buffer; 437388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 438388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 439388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 440388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 441388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 442388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 443388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 444eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huberstatus_t MyVorbisExtractor::init() { 445388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta = new MetaData; 446388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 447388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 448388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer *packet; 449eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber status_t err; 450eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if ((err = readNextPacket(&packet)) != OK) { 451eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return err; 452eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 453388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("read packet of size %d\n", packet->range_length()); 454eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber err = verifyHeader(packet, 1); 455388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packet->release(); 456388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packet = NULL; 457eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (err != OK) { 458eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return err; 459eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 460388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 461eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if ((err = readNextPacket(&packet)) != OK) { 462eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return err; 463eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 464388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("read packet of size %d\n", packet->range_length()); 465eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber err = verifyHeader(packet, 3); 466388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packet->release(); 467388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packet = NULL; 468eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (err != OK) { 469eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return err; 470eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 471388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 472eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if ((err = readNextPacket(&packet)) != OK) { 473eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return err; 474eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 475388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("read packet of size %d\n", packet->range_length()); 476eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber err = verifyHeader(packet, 5); 477388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packet->release(); 478388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packet = NULL; 479eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (err != OK) { 480eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return err; 481eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 48234c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber 48334c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber mFirstDataOffset = mOffset + mCurrentPageSize; 484eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber 485eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return OK; 486388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 487388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 488eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huberstatus_t MyVorbisExtractor::verifyHeader( 489388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer *buffer, uint8_t type) { 490388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber const uint8_t *data = 491388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 492388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 493388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t size = buffer->range_length(); 494388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 495eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { 496eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return ERROR_MALFORMED; 497eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 498388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 499388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ogg_buffer buf; 500388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buf.data = (uint8_t *)data; 501388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buf.size = size; 502388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buf.refcount = 1; 503388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buf.ptr.owner = NULL; 504388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 505388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ogg_reference ref; 506388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ref.buffer = &buf; 507388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ref.begin = 0; 508388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ref.length = size; 509388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ref.next = NULL; 510388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 511388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber oggpack_buffer bits; 512388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber oggpack_readinit(&bits, &ref); 513388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 514388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber CHECK_EQ(oggpack_read(&bits, 8), type); 515388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (size_t i = 0; i < 6; ++i) { 516388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber oggpack_read(&bits, 8); // skip 'vorbis' 517388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 518388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 519388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber switch (type) { 520388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber case 1: 521388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber { 522388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits)); 523388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 524388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta->setData(kKeyVorbisInfo, 0, data, size); 525388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta->setInt32(kKeySampleRate, mVi.rate); 526388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta->setInt32(kKeyChannelCount, mVi.channels); 527388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 528388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("lower-bitrate = %ld", mVi.bitrate_lower); 529388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("upper-bitrate = %ld", mVi.bitrate_upper); 530388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); 531388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("window-bitrate = %ld", mVi.bitrate_window); 532388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 533388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber off_t size; 534388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mSource->getSize(&size) == OK) { 535388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint64_t bps = approxBitrate(); 536388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 537388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta->setInt64(kKeyDuration, size * 8000000ll / bps); 538388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 539388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber break; 540388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 541388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 542388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber case 3: 543388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber { 544eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (0 != _vorbis_unpack_comment(&mVc, &bits)) { 545eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return ERROR_MALFORMED; 546eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 547c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 548c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber parseFileMetaData(); 549388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber break; 550388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 551388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 552388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber case 5: 553388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber { 554eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (0 != _vorbis_unpack_books(&mVi, &bits)) { 555eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return ERROR_MALFORMED; 556eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 557388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 558388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta->setData(kKeyVorbisBooks, 0, data, size); 559388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber break; 560388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 561388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 562eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber 563eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return OK; 564388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 565388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 566388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberuint64_t MyVorbisExtractor::approxBitrate() { 567388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mVi.bitrate_nominal != 0) { 568388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return mVi.bitrate_nominal; 569388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 570388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 571388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return (mVi.bitrate_lower + mVi.bitrate_upper) / 2; 572388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 573388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 574c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Hubervoid MyVorbisExtractor::parseFileMetaData() { 575c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber mFileMeta = new MetaData; 576c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); 577c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 578c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber struct { 579c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber const char *const mTag; 580c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint32_t mKey; 581c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } kMap[] = { 582c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "TITLE", kKeyTitle }, 583c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "ARTIST", kKeyArtist }, 584c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "ALBUM", kKeyAlbum }, 585c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "COMPOSER", kKeyComposer }, 586c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "GENRE", kKeyGenre }, 587c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "AUTHOR", kKeyAuthor }, 588c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "TRACKNUMBER", kKeyCDTrackNumber }, 589c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "DISCNUMBER", kKeyDiscNumber }, 590c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "DATE", kKeyDate }, 591c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "LYRICIST", kKeyWriter }, 592c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, 593c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber }; 594c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 595c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber for (int i = 0; i < mVc.comments; ++i) { 596c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber const char *comment = mVc.user_comments[i]; 597c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 598c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { 599c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber size_t tagLen = strlen(kMap[j].mTag); 600c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (!strncasecmp(kMap[j].mTag, comment, tagLen) 601c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber && comment[tagLen] == '=') { 602c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (kMap[j].mKey == kKeyAlbumArt) { 603c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber extractAlbumArt( 604c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber &comment[tagLen + 1], 605c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber mVc.comment_lengths[i] - tagLen - 1); 606c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else { 607c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber mFileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); 608c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 609c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 610c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 611c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 612c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 613c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 614c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber#if 0 615c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber for (int i = 0; i < mVc.comments; ++i) { 616c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber LOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); 617c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 618c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber#endif 619c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber} 620c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 621c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber// The returned buffer should be free()d. 622c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huberstatic uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) { 623c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber *outSize = 0; 624c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 625c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if ((size % 4) != 0) { 626c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber return NULL; 627c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 628c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 629c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber size_t n = size; 630c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber size_t padding = 0; 631c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (n >= 1 && s[n - 1] == '=') { 632c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber padding = 1; 633c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 634c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (n >= 2 && s[n - 2] == '=') { 635c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber padding = 2; 636c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 637c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 638c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 639c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber size_t outLen = 3 * size / 4 - padding; 640c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 641c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber *outSize = outLen; 642c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 643c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber void *buffer = malloc(outLen); 644c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 645c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint8_t *out = (uint8_t *)buffer; 646c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber size_t j = 0; 647c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint32_t accum = 0; 648c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber for (size_t i = 0; i < n; ++i) { 649c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber char c = s[i]; 650c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber unsigned value; 651c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (c >= 'A' && c <= 'Z') { 652c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber value = c - 'A'; 653c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else if (c >= 'a' && c <= 'z') { 654c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber value = 26 + c - 'a'; 655c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else if (c >= '0' && c <= '9') { 656c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber value = 52 + c - '0'; 657c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else if (c == '+') { 658c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber value = 62; 659c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else if (c == '/') { 660c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber value = 63; 661c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else if (c != '=') { 662c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber return NULL; 663c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else { 664c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (i < n - padding) { 665c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber return NULL; 666c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 667c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 668c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber value = 0; 669c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 670c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 671c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber accum = (accum << 6) | value; 672c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 673c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (((i + 1) % 4) == 0) { 674c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber out[j++] = (accum >> 16); 675c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 676c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } 677c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (j < outLen) { out[j++] = accum & 0xff; } 678c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 679c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber accum = 0; 680c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 681c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 682c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 683c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber return (uint8_t *)buffer; 684c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber} 685c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 686c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Hubervoid MyVorbisExtractor::extractAlbumArt(const void *data, size_t size) { 687c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber LOGV("extractAlbumArt from '%s'", (const char *)data); 688c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 689c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber size_t flacSize; 690c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize); 691c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 692c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (flac == NULL) { 693c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber LOGE("malformed base64 encoded data."); 694c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber return; 695c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 696c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 697c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber LOGV("got flac of size %d", flacSize); 698c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 699c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint32_t picType; 700c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint32_t typeLen; 701c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint32_t descLen; 702c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint32_t dataLen; 703c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber char type[128]; 704c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 705c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (flacSize < 8) { 706c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 707c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 708c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 709c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber picType = U32_AT(flac); 710c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 711c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (picType != 3) { 712c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber // This is not a front cover. 713c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 714c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 715c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 716c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber typeLen = U32_AT(&flac[4]); 717c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (typeLen + 1 > sizeof(type)) { 718c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 719c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 720c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 721c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (flacSize < 8 + typeLen) { 722c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 723c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 724c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 725c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber memcpy(type, &flac[8], typeLen); 726c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber type[typeLen] = '\0'; 727c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 728c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber LOGV("picType = %d, type = '%s'", picType, type); 729c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 730c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (!strcmp(type, "-->")) { 731c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber // This is not inline cover art, but an external url instead. 732c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 733c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 734c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 735c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber descLen = U32_AT(&flac[8 + typeLen]); 736c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 737c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (flacSize < 32 + typeLen + descLen) { 738c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 739c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 740c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 741c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]); 742c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 743c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (flacSize < 32 + typeLen + descLen + dataLen) { 744c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 745c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 746c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 747c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber LOGV("got image data, %d trailing bytes", 748c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber flacSize - 32 - typeLen - descLen - dataLen); 749c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 750c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber mFileMeta->setData( 751c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen); 752c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 753c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber mFileMeta->setCString(kKeyAlbumArtMIME, type); 754c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 755c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huberexit: 756c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber free(flac); 757c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber flac = NULL; 758c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber} 759c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 760388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber//////////////////////////////////////////////////////////////////////////////// 761388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 762388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source) 763388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber : mDataSource(source), 764388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mInitCheck(NO_INIT), 765388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mImpl(NULL) { 766388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mImpl = new MyVorbisExtractor(mDataSource); 767eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber mInitCheck = mImpl->seekToOffset(0); 768388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 769eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (mInitCheck == OK) { 770eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber mInitCheck = mImpl->init(); 771eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 772388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 773388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 774388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberOggExtractor::~OggExtractor() { 775388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber delete mImpl; 776388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mImpl = NULL; 777388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 778388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 779388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersize_t OggExtractor::countTracks() { 780388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return mInitCheck != OK ? 0 : 1; 781388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 782388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 783388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MediaSource> OggExtractor::getTrack(size_t index) { 784388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (index >= 1) { 785388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return NULL; 786388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 787388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 788388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return new OggSource(this); 789388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 790388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 791388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData( 792388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t index, uint32_t flags) { 793388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (index >= 1) { 794388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return NULL; 795388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 796388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 797388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return mImpl->getFormat(); 798388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 799388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 800388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MetaData> OggExtractor::getMetaData() { 801c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber return mImpl->getFileMetaData(); 802388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 803388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 804388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberbool SniffOgg( 805388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence) { 806388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber char tmp[4]; 807388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) { 808388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return false; 809388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 810388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 811388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG); 812388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *confidence = 0.2f; 813388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 814388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return true; 815388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 816388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 817388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} // namespace android 818