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; 9638ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber uint64_t mPrevGranulePosition; 97388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t mCurrentPageSize; 9838ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber bool mFirstPacketInPage; 9938ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber uint64_t mCurrentPageSamples; 100388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t mNextLaceIndex; 101388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 10234c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber off_t mFirstDataOffset; 10334c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber 104388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber vorbis_info mVi; 105388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber vorbis_comment mVc; 106388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 107388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber sp<MetaData> mMeta; 108c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber sp<MetaData> mFileMeta; 109388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 110388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ssize_t readPage(off_t offset, Page *page); 111388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber status_t findNextPage(off_t startOffset, off_t *pageOffset); 112388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 113eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber status_t verifyHeader( 114388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer *buffer, uint8_t type); 115388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 116c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber void parseFileMetaData(); 117c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber void extractAlbumArt(const void *data, size_t size); 118c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 11938ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber uint64_t findPrevGranulePosition(off_t pageOffset); 12038ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 121388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MyVorbisExtractor(const MyVorbisExtractor &); 122388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MyVorbisExtractor &operator=(const MyVorbisExtractor &); 123388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber}; 124388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 125388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber//////////////////////////////////////////////////////////////////////////////// 126388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 127388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberOggSource::OggSource(const sp<OggExtractor> &extractor) 128388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber : mExtractor(extractor), 129388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mStarted(false) { 130388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 131388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 132388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberOggSource::~OggSource() { 133388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mStarted) { 134388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber stop(); 135388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 136388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 137388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 138388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MetaData> OggSource::getFormat() { 139388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return mExtractor->mImpl->getFormat(); 140388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 141388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 142388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t OggSource::start(MetaData *params) { 143388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mStarted) { 144388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return INVALID_OPERATION; 145388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 146388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 147388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mStarted = true; 148388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 149388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 150388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 151388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 152388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t OggSource::stop() { 153388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mStarted = false; 154388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 155388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 156388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 157388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 158388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t OggSource::read( 159388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer **out, const ReadOptions *options) { 160388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *out = NULL; 161388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 162388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber int64_t seekTimeUs; 1636624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber ReadOptions::SeekMode mode; 1646624c9fd0bc5e3858a22a04c05b5059445c1c367Andreas Huber if (options && options->getSeekTo(&seekTimeUs, &mode)) { 165388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber off_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll; 1663386c38d59fa837f4876a24af821fb9b35314712Andreas Huber LOGV("seeking to offset %ld", pos); 167388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 168388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mExtractor->mImpl->seekToOffset(pos) != OK) { 169388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_END_OF_STREAM; 170388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 171388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 172388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 173388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer *packet; 174388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber status_t err = mExtractor->mImpl->readNextPacket(&packet); 175388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 176388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (err != OK) { 177388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return err; 178388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 179388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 180388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#if 0 181388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber int64_t timeUs; 182388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) { 183388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGI("found time = %lld us", timeUs); 184388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } else { 185388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGI("NO time"); 186388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 187388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#endif 188388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 189ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber packet->meta_data()->setInt32(kKeyIsSyncFrame, 1); 190ad98d383a04fce08a147b200e23b12f12b2681a3Andreas Huber 191388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *out = packet; 192388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 193388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 194388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 195388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 196388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber//////////////////////////////////////////////////////////////////////////////// 197388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 198388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberMyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source) 199388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber : mSource(source), 200388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mOffset(0), 20138ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber mPrevGranulePosition(0), 202388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mCurrentPageSize(0), 20338ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber mFirstPacketInPage(true), 20438ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber mCurrentPageSamples(0), 20534c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber mNextLaceIndex(0), 20634c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber mFirstDataOffset(-1) { 207388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mCurrentPage.mNumSegments = 0; 208c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 209c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber vorbis_info_init(&mVi); 210c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber vorbis_comment_init(&mVc); 211388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 212388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 213388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberMyVorbisExtractor::~MyVorbisExtractor() { 214c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber vorbis_comment_clear(&mVc); 215c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber vorbis_info_clear(&mVi); 216388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 217388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 218388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MetaData> MyVorbisExtractor::getFormat() const { 219388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return mMeta; 220388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 221388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 222388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t MyVorbisExtractor::findNextPage( 223388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber off_t startOffset, off_t *pageOffset) { 224388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *pageOffset = startOffset; 225388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 226388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (;;) { 227388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber char signature[4]; 228388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ssize_t n = mSource->readAt(*pageOffset, &signature, 4); 229388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 230388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (n < 4) { 231388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *pageOffset = 0; 232388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 233388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM; 234388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 235388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 236388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (!memcmp(signature, "OggS", 4)) { 237388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (*pageOffset > startOffset) { 238388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("skipped %ld bytes of junk to reach next frame", 239388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *pageOffset - startOffset); 240388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 241388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 242388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 243388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 244388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 245388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ++*pageOffset; 246388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 247388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 248388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 24938ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber// Given the offset of the "current" page, find the page immediately preceding 25038ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber// it (if any) and return its granule position. 25138ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber// To do this we back up from the "current" page's offset until we find any 25238ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber// page preceding it and then scan forward to just before the current page. 25338ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huberuint64_t MyVorbisExtractor::findPrevGranulePosition(off_t pageOffset) { 25438ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber off_t prevPageOffset = 0; 25538ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber off_t prevGuess = pageOffset; 25638ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber for (;;) { 25738ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber if (prevGuess >= 5000) { 25838ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber prevGuess -= 5000; 25938ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber } else { 26038ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber prevGuess = 0; 26138ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber } 26238ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 26338ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber LOGV("backing up %ld bytes", pageOffset - prevGuess); 26438ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 26538ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber CHECK_EQ(findNextPage(prevGuess, &prevPageOffset), (status_t)OK); 26638ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 26738ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber if (prevPageOffset < pageOffset || prevGuess == 0) { 26838ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber break; 26938ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber } 27038ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber } 27138ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 27238ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber if (prevPageOffset == pageOffset) { 27338ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber // We did not find a page preceding this one. 27438ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber return 0; 27538ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber } 27638ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 27738ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber LOGV("prevPageOffset at %ld, pageOffset at %ld", prevPageOffset, pageOffset); 27838ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 27938ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber for (;;) { 28038ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber Page prevPage; 28138ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber ssize_t n = readPage(prevPageOffset, &prevPage); 28238ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 28338ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber if (n <= 0) { 28438ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber return 0; 28538ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber } 28638ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 28738ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber prevPageOffset += n; 28838ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 28938ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber if (prevPageOffset == pageOffset) { 29038ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber return prevPage.mGranulePosition; 29138ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber } 29238ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber } 29338ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber} 29438ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 295388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t MyVorbisExtractor::seekToOffset(off_t offset) { 29634c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) { 29734c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber // Once we know where the actual audio data starts (past the headers) 29834c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber // don't ever seek to anywhere before that. 29934c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber offset = mFirstDataOffset; 30034c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber } 30134c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber 302388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber off_t pageOffset; 303388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber status_t err = findNextPage(offset, &pageOffset); 304388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 305388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (err != OK) { 306388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return err; 307388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 308388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 30938ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber // We found the page we wanted to seek to, but we'll also need 31038ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber // the page preceding it to determine how many valid samples are on 31138ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber // this page. 31238ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber mPrevGranulePosition = findPrevGranulePosition(pageOffset); 31338ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 314388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mOffset = pageOffset; 315388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 316388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mCurrentPageSize = 0; 31738ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber mFirstPacketInPage = true; 31838ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber mCurrentPageSamples = 0; 319388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mCurrentPage.mNumSegments = 0; 320388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mNextLaceIndex = 0; 321388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 322388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // XXX what if new page continues packet from last??? 323388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 324388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 325388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 326388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 327388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) { 328388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint8_t header[27]; 329388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mSource->readAt(offset, header, sizeof(header)) 330388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber < (ssize_t)sizeof(header)) { 3313386c38d59fa837f4876a24af821fb9b35314712Andreas Huber LOGV("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset); 332388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 333388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_IO; 334388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 335388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 336388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (memcmp(header, "OggS", 4)) { 337388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_MALFORMED; 338388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 339388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 340388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (header[4] != 0) { 341388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // Wrong version. 342388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 343388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_UNSUPPORTED; 344388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 345388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 346388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber page->mFlags = header[5]; 347388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 348388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (page->mFlags & ~7) { 349388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // Only bits 0-2 are defined in version 0. 350388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_MALFORMED; 351388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 352388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 353388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber page->mGranulePosition = U64LE_AT(&header[6]); 354388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 355388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#if 0 356388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber printf("granulePosition = %llu (0x%llx)\n", 357388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber page->mGranulePosition, page->mGranulePosition); 358388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber#endif 359388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 360388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber page->mSerialNo = U32LE_AT(&header[14]); 361388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber page->mPageNo = U32LE_AT(&header[18]); 362388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 363388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber page->mNumSegments = header[26]; 364388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mSource->readAt( 365388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber offset + sizeof(header), page->mLace, page->mNumSegments) 366388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber < (ssize_t)page->mNumSegments) { 367388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_IO; 368388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 369388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 370388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t totalSize = 0;; 371388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 372388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber totalSize += page->mLace[i]; 373388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 374388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 375eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber#if 0 376388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber String8 tmp; 377388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (size_t i = 0; i < page->mNumSegments; ++i) { 378388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber char x[32]; 379388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]); 380388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 381388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber tmp.append(x); 382388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 383388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 384eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string()); 385eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber#endif 386388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 387388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return sizeof(header) + page->mNumSegments + totalSize; 388388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 389388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 390388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberstatus_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { 391388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *out = NULL; 392388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 393388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer *buffer = NULL; 394388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber int64_t timeUs = -1; 395388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 396388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (;;) { 397388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t i; 398388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t packetSize = 0; 399388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber bool gotFullPacket = false; 400388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) { 401388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint8_t lace = mCurrentPage.mLace[i]; 402388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 403388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packetSize += lace; 404388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 405388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (lace < 255) { 406388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber gotFullPacket = true; 407388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ++i; 408388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber break; 409388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 410388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 411388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 412388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mNextLaceIndex < mCurrentPage.mNumSegments) { 413388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber off_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments; 414388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (size_t j = 0; j < mNextLaceIndex; ++j) { 415388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber dataOffset += mCurrentPage.mLace[j]; 416388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 417388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 418388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t fullSize = packetSize; 419388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (buffer != NULL) { 420388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber fullSize += buffer->range_length(); 421388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 422388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer *tmp = new MediaBuffer(fullSize); 423388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (buffer != NULL) { 424388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber memcpy(tmp->data(), buffer->data(), buffer->range_length()); 425388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber tmp->set_range(0, buffer->range_length()); 426388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer->release(); 4271f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber } else { 428388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // XXX Not only is this not technically the correct time for 429388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // this packet, we also stamp every packet in this page 430388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // with the same time. This needs fixing later. 4311f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber 4321f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber if (mVi.rate) { 4331f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber // Rate may not have been initialized yet if we're currently 4341f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber // reading the configuration packets... 4351f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber // Fortunately, the timestamp doesn't matter for those. 4361f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate; 4371f7fba1ffbf5922d999ab52130efb73a35e72077Andreas Huber } 438388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber tmp->set_range(0, 0); 439388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 440388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer = tmp; 441388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 442388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ssize_t n = mSource->readAt( 443388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber dataOffset, 444388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber (uint8_t *)buffer->data() + buffer->range_length(), 445388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packetSize); 446388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 447388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (n < (ssize_t)packetSize) { 4483386c38d59fa837f4876a24af821fb9b35314712Andreas Huber LOGV("failed to read %d bytes at 0x%08lx", packetSize, dataOffset); 449388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return ERROR_IO; 450388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 451388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 452388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer->set_range(0, fullSize); 453388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 454388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mNextLaceIndex = i; 455388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 456388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (gotFullPacket) { 457388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // We've just read the entire packet. 458388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 459388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (timeUs >= 0) { 460388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 461388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 462388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 46338ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber if (mFirstPacketInPage) { 46438ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber buffer->meta_data()->setInt32( 46538ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber kKeyValidSamples, mCurrentPageSamples); 46638ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber mFirstPacketInPage = false; 46738ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber } 46838ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 469388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *out = buffer; 470388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 471388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 472388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 473388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 474388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // fall through, the buffer now contains the start of the packet. 475388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 476388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 477388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments); 478388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 479388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mOffset += mCurrentPageSize; 480388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ssize_t n = readPage(mOffset, &mCurrentPage); 481388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 482388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (n <= 0) { 483388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (buffer) { 484388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer->release(); 485388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer = NULL; 486388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 487388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 4883386c38d59fa837f4876a24af821fb9b35314712Andreas Huber LOGV("readPage returned %ld", n); 489388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 490388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; 491388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 492388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 49338ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber mCurrentPageSamples = 49438ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber mCurrentPage.mGranulePosition - mPrevGranulePosition; 49538ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber mFirstPacketInPage = true; 49638ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 49738ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber mPrevGranulePosition = mCurrentPage.mGranulePosition; 49838ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 499388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mCurrentPageSize = n; 500388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mNextLaceIndex = 0; 501388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 502388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (buffer != NULL) { 503388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if ((mCurrentPage.mFlags & 1) == 0) { 504388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // This page does not continue the packet, i.e. the packet 505388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber // is already complete. 506388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 507388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (timeUs >= 0) { 508388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buffer->meta_data()->setInt64(kKeyTime, timeUs); 509388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 510388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 51138ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber buffer->meta_data()->setInt32( 51238ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber kKeyValidSamples, mCurrentPageSamples); 51338ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber mFirstPacketInPage = false; 51438ae220bb7c06e3cc82f96dada769c6b12a79d09Andreas Huber 515388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *out = buffer; 516388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 517388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return OK; 518388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 519388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 520388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 521388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 522388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 523eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huberstatus_t MyVorbisExtractor::init() { 524388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta = new MetaData; 525388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 526388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 527388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer *packet; 528eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber status_t err; 529eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if ((err = readNextPacket(&packet)) != OK) { 530eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return err; 531eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 532388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("read packet of size %d\n", packet->range_length()); 533eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber err = verifyHeader(packet, 1); 534388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packet->release(); 535388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packet = NULL; 536eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (err != OK) { 537eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return err; 538eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 539388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 540eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if ((err = readNextPacket(&packet)) != OK) { 541eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return err; 542eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 543388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("read packet of size %d\n", packet->range_length()); 544eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber err = verifyHeader(packet, 3); 545388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packet->release(); 546388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packet = NULL; 547eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (err != OK) { 548eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return err; 549eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 550388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 551eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if ((err = readNextPacket(&packet)) != OK) { 552eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return err; 553eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 554388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("read packet of size %d\n", packet->range_length()); 555eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber err = verifyHeader(packet, 5); 556388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packet->release(); 557388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber packet = NULL; 558eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (err != OK) { 559eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return err; 560eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 56134c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber 56234c70709a69fbf29dbde2c106d9db5f522f25268Andreas Huber mFirstDataOffset = mOffset + mCurrentPageSize; 563eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber 564eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return OK; 565388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 566388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 567eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huberstatus_t MyVorbisExtractor::verifyHeader( 568388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber MediaBuffer *buffer, uint8_t type) { 569388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber const uint8_t *data = 570388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber (const uint8_t *)buffer->data() + buffer->range_offset(); 571388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 572388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t size = buffer->range_length(); 573388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 574eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { 575eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return ERROR_MALFORMED; 576eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 577388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 578388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ogg_buffer buf; 579388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buf.data = (uint8_t *)data; 580388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buf.size = size; 581388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buf.refcount = 1; 582388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber buf.ptr.owner = NULL; 583388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 584388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ogg_reference ref; 585388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ref.buffer = &buf; 586388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ref.begin = 0; 587388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ref.length = size; 588388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber ref.next = NULL; 589388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 590388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber oggpack_buffer bits; 591388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber oggpack_readinit(&bits, &ref); 592388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 593388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber CHECK_EQ(oggpack_read(&bits, 8), type); 594388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber for (size_t i = 0; i < 6; ++i) { 595388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber oggpack_read(&bits, 8); // skip 'vorbis' 596388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 597388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 598388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber switch (type) { 599388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber case 1: 600388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber { 601388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits)); 602388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 603388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta->setData(kKeyVorbisInfo, 0, data, size); 604388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta->setInt32(kKeySampleRate, mVi.rate); 605388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta->setInt32(kKeyChannelCount, mVi.channels); 606388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 607388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("lower-bitrate = %ld", mVi.bitrate_lower); 608388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("upper-bitrate = %ld", mVi.bitrate_upper); 609388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); 610388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber LOGV("window-bitrate = %ld", mVi.bitrate_window); 611388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 612388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber off_t size; 613388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mSource->getSize(&size) == OK) { 614388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber uint64_t bps = approxBitrate(); 615388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 616388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta->setInt64(kKeyDuration, size * 8000000ll / bps); 617388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 618388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber break; 619388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 620388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 621388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber case 3: 622388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber { 623eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (0 != _vorbis_unpack_comment(&mVc, &bits)) { 624eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return ERROR_MALFORMED; 625eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 626c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 627c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber parseFileMetaData(); 628388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber break; 629388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 630388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 631388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber case 5: 632388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber { 633eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (0 != _vorbis_unpack_books(&mVi, &bits)) { 634eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return ERROR_MALFORMED; 635eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 636388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 637388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mMeta->setData(kKeyVorbisBooks, 0, data, size); 638388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber break; 639388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 640388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 641eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber 642eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber return OK; 643388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 644388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 645388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberuint64_t MyVorbisExtractor::approxBitrate() { 646388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (mVi.bitrate_nominal != 0) { 647388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return mVi.bitrate_nominal; 648388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 649388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 650388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return (mVi.bitrate_lower + mVi.bitrate_upper) / 2; 651388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 652388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 653c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Hubervoid MyVorbisExtractor::parseFileMetaData() { 654c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber mFileMeta = new MetaData; 655c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); 656c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 657c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber struct { 658c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber const char *const mTag; 659c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint32_t mKey; 660c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } kMap[] = { 661c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "TITLE", kKeyTitle }, 662c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "ARTIST", kKeyArtist }, 663ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen { "ALBUMARTIST", kKeyAlbumArtist }, 664ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen { "ALBUM ARTIST", kKeyAlbumArtist }, 665ba77a3f9cb1d68b2ed4813aaae856444578e3a75Marco Nelissen { "COMPILATION", kKeyCompilation }, 666c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "ALBUM", kKeyAlbum }, 667c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "COMPOSER", kKeyComposer }, 668c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "GENRE", kKeyGenre }, 669c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "AUTHOR", kKeyAuthor }, 670c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "TRACKNUMBER", kKeyCDTrackNumber }, 671c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "DISCNUMBER", kKeyDiscNumber }, 672c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "DATE", kKeyDate }, 673c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "LYRICIST", kKeyWriter }, 674c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, 6759fee0b2a02daa6fcf286ed930e45400dd3ba8dbaAndreas Huber { "ANDROID_LOOP", kKeyAutoLoop }, 676c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber }; 677c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 678c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber for (int i = 0; i < mVc.comments; ++i) { 679c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber const char *comment = mVc.user_comments[i]; 680c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 681c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { 682c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber size_t tagLen = strlen(kMap[j].mTag); 683c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (!strncasecmp(kMap[j].mTag, comment, tagLen) 684c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber && comment[tagLen] == '=') { 685c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (kMap[j].mKey == kKeyAlbumArt) { 686c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber extractAlbumArt( 687c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber &comment[tagLen + 1], 688c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber mVc.comment_lengths[i] - tagLen - 1); 6899fee0b2a02daa6fcf286ed930e45400dd3ba8dbaAndreas Huber } else if (kMap[j].mKey == kKeyAutoLoop) { 6909fee0b2a02daa6fcf286ed930e45400dd3ba8dbaAndreas Huber if (!strcasecmp(&comment[tagLen + 1], "true")) { 6919fee0b2a02daa6fcf286ed930e45400dd3ba8dbaAndreas Huber mFileMeta->setInt32(kKeyAutoLoop, true); 6929fee0b2a02daa6fcf286ed930e45400dd3ba8dbaAndreas Huber } 693c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else { 694c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber mFileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); 695c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 696c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 697c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 698c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 699c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 700c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber#if 0 701c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber for (int i = 0; i < mVc.comments; ++i) { 702c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber LOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); 703c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 704c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber#endif 705c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber} 706c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 707c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber// The returned buffer should be free()d. 708c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huberstatic uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) { 709c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber *outSize = 0; 710c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 711c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if ((size % 4) != 0) { 712c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber return NULL; 713c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 714c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 715c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber size_t n = size; 716c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber size_t padding = 0; 717c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (n >= 1 && s[n - 1] == '=') { 718c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber padding = 1; 719c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 720c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (n >= 2 && s[n - 2] == '=') { 721c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber padding = 2; 722c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 723c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 724c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 725c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber size_t outLen = 3 * size / 4 - padding; 726c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 727c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber *outSize = outLen; 728c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 729c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber void *buffer = malloc(outLen); 730c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 731c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint8_t *out = (uint8_t *)buffer; 732c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber size_t j = 0; 733c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint32_t accum = 0; 734c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber for (size_t i = 0; i < n; ++i) { 735c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber char c = s[i]; 736c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber unsigned value; 737c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (c >= 'A' && c <= 'Z') { 738c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber value = c - 'A'; 739c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else if (c >= 'a' && c <= 'z') { 740c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber value = 26 + c - 'a'; 741c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else if (c >= '0' && c <= '9') { 742c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber value = 52 + c - '0'; 743c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else if (c == '+') { 744c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber value = 62; 745c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else if (c == '/') { 746c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber value = 63; 747c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else if (c != '=') { 748c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber return NULL; 749c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } else { 750c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (i < n - padding) { 751c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber return NULL; 752c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 753c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 754c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber value = 0; 755c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 756c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 757c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber accum = (accum << 6) | value; 758c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 759c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (((i + 1) % 4) == 0) { 760c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber out[j++] = (accum >> 16); 761c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 762c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } 763c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (j < outLen) { out[j++] = accum & 0xff; } 764c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 765c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber accum = 0; 766c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 767c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 768c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 769c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber return (uint8_t *)buffer; 770c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber} 771c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 772c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Hubervoid MyVorbisExtractor::extractAlbumArt(const void *data, size_t size) { 773c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber LOGV("extractAlbumArt from '%s'", (const char *)data); 774c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 775c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber size_t flacSize; 776c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize); 777c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 778c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (flac == NULL) { 779c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber LOGE("malformed base64 encoded data."); 780c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber return; 781c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 782c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 783c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber LOGV("got flac of size %d", flacSize); 784c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 785c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint32_t picType; 786c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint32_t typeLen; 787c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint32_t descLen; 788c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber uint32_t dataLen; 789c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber char type[128]; 790c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 791c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (flacSize < 8) { 792c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 793c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 794c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 795c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber picType = U32_AT(flac); 796c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 797c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (picType != 3) { 798c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber // This is not a front cover. 799c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 800c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 801c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 802c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber typeLen = U32_AT(&flac[4]); 803c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (typeLen + 1 > sizeof(type)) { 804c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 805c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 806c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 807c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (flacSize < 8 + typeLen) { 808c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 809c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 810c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 811c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber memcpy(type, &flac[8], typeLen); 812c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber type[typeLen] = '\0'; 813c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 814c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber LOGV("picType = %d, type = '%s'", picType, type); 815c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 816c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (!strcmp(type, "-->")) { 817c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber // This is not inline cover art, but an external url instead. 818c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 819c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 820c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 821c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber descLen = U32_AT(&flac[8 + typeLen]); 822c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 823c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (flacSize < 32 + typeLen + descLen) { 824c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 825c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 826c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 827c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]); 828c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 829c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber if (flacSize < 32 + typeLen + descLen + dataLen) { 830c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber goto exit; 831c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber } 832c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 833c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber LOGV("got image data, %d trailing bytes", 834c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber flacSize - 32 - typeLen - descLen - dataLen); 835c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 836c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber mFileMeta->setData( 837c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen); 838c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 839c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber mFileMeta->setCString(kKeyAlbumArtMIME, type); 840c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 841c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huberexit: 842c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber free(flac); 843c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber flac = NULL; 844c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber} 845c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber 846388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber//////////////////////////////////////////////////////////////////////////////// 847388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 848388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberOggExtractor::OggExtractor(const sp<DataSource> &source) 849388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber : mDataSource(source), 850388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mInitCheck(NO_INIT), 851388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mImpl(NULL) { 852388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mImpl = new MyVorbisExtractor(mDataSource); 853eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber mInitCheck = mImpl->seekToOffset(0); 854388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 855eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber if (mInitCheck == OK) { 856eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber mInitCheck = mImpl->init(); 857eae953bfd4ea86a51f7fdd845de9f3d82646dff8Andreas Huber } 858388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 859388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 860388379f8b4cabe7bccf280d450a6db2c3149796bAndreas HuberOggExtractor::~OggExtractor() { 861388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber delete mImpl; 862388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mImpl = NULL; 863388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 864388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 865388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersize_t OggExtractor::countTracks() { 866388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return mInitCheck != OK ? 0 : 1; 867388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 868388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 869388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MediaSource> OggExtractor::getTrack(size_t index) { 870388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (index >= 1) { 871388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return NULL; 872388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 873388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 874388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return new OggSource(this); 875388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 876388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 877388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MetaData> OggExtractor::getTrackMetaData( 878388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber size_t index, uint32_t flags) { 879388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (index >= 1) { 880388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return NULL; 881388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 882388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 883388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return mImpl->getFormat(); 884388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 885388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 886388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Hubersp<MetaData> OggExtractor::getMetaData() { 887c6c62e12c930b137e62c16931cfe340bc93aa8f4Andreas Huber return mImpl->getFileMetaData(); 888388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 889388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 890388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huberbool SniffOgg( 891efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber const sp<DataSource> &source, String8 *mimeType, float *confidence, 892efdd088a71ddd0a96cf9ca2f58e8703fe8c5c494Andreas Huber sp<AMessage> *) { 893388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber char tmp[4]; 894388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) { 895388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return false; 896388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber } 897388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 898388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG); 899388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber *confidence = 0.2f; 900388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 901388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber return true; 902388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} 903388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber 904388379f8b4cabe7bccf280d450a6db2c3149796bAndreas Huber} // namespace android 905