From 4d026f5583e1f61726b8d24569433a6b072ebf6e Mon Sep 17 00:00:00 2001 From: Marco Nelissen Date: Thu, 4 Oct 2018 13:04:29 -0700 Subject: [PATCH] Convert Ogg and Flac extractors to use AMediaFormat Bug: 111407253 Test: manual, CTS Change-Id: I8aeb44ceeb831bb558cac1123f0aaade8163abf8 --- include/media/VorbisComment.h | 1 - media/extractors/flac/Android.bp | 3 + media/extractors/flac/FLACExtractor.cpp | 103 ++++++------ media/extractors/flac/FLACExtractor.h | 14 +- media/extractors/ogg/Android.bp | 2 + media/extractors/ogg/OggExtractor.cpp | 105 ++++++------ media/extractors/ogg/OggExtractor.h | 9 +- media/libmediaextractor/Android.bp | 1 - media/libmediaextractor/VorbisComment.cpp | 151 ------------------ .../include/media/VorbisComment.h | 30 ---- media/libstagefright/MetaDataUtils.cpp | 133 +++++++++++++++ media/libstagefright/Utils.cpp | 11 ++ media/libstagefright/foundation/base64.cpp | 38 +++-- .../media/stagefright/foundation/base64.h | 3 + .../include/media/stagefright/MetaDataUtils.h | 3 + media/ndk/NdkMediaFormat.cpp | 3 + media/ndk/include/media/NdkMediaFormat.h | 3 + 17 files changed, 310 insertions(+), 303 deletions(-) delete mode 120000 include/media/VorbisComment.h delete mode 100644 media/libmediaextractor/VorbisComment.cpp delete mode 100644 media/libmediaextractor/include/media/VorbisComment.h diff --git a/include/media/VorbisComment.h b/include/media/VorbisComment.h deleted file mode 120000 index adaa4898cd..0000000000 --- a/include/media/VorbisComment.h +++ /dev/null @@ -1 +0,0 @@ -../../media/libmediaextractor/include/media/VorbisComment.h \ No newline at end of file diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp index 6282793a7b..eda7b61d93 100644 --- a/media/extractors/flac/Android.bp +++ b/media/extractors/flac/Android.bp @@ -10,11 +10,14 @@ cc_library_shared { shared_libs: [ "liblog", "libmediaextractor", + "libmediandk", ], static_libs: [ "libFLAC", "libstagefright_foundation", + "libstagefright_metadatautils", + "libutils", ], name: "libflacextractor", diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp index 3a646d5697..fcfdaffb6d 100644 --- a/media/extractors/flac/FLACExtractor.cpp +++ b/media/extractors/flac/FLACExtractor.cpp @@ -25,7 +25,7 @@ #include "FLAC/stream_decoder.h" #include -#include +#include #include #include #include @@ -33,24 +33,25 @@ #include #include #include +#include #include namespace android { class FLACParser; -class FLACSource : public MediaTrackHelper { +class FLACSource : public MediaTrackHelperV2 { public: FLACSource( DataSourceHelper *dataSource, - MetaDataBase &meta); + AMediaFormat *meta); - virtual status_t start(); - virtual status_t stop(); - virtual status_t getFormat(MetaDataBase &meta); + virtual media_status_t start(); + virtual media_status_t stop(); + virtual media_status_t getFormat(AMediaFormat *meta); - virtual status_t read( + virtual media_status_t read( MediaBufferBase **buffer, const ReadOptions *options = NULL); protected: @@ -58,7 +59,7 @@ protected: private: DataSourceHelper *mDataSource; - MetaDataBase mTrackMetadata; + AMediaFormat *mTrackMetadata; FLACParser *mParser; bool mInitCheck; bool mStarted; @@ -81,8 +82,8 @@ public: explicit FLACParser( DataSourceHelper *dataSource, // If metadata pointers aren't provided, we don't fill them - MetaDataBase *fileMetadata = 0, - MetaDataBase *trackMetadata = 0); + AMediaFormat *fileMetadata = 0, + AMediaFormat *trackMetadata = 0); virtual ~FLACParser(); @@ -119,8 +120,8 @@ public: private: DataSourceHelper *mDataSource; - MetaDataBase *mFileMetadata; - MetaDataBase *mTrackMetadata; + AMediaFormat *mFileMetadata; + AMediaFormat *mTrackMetadata; bool mInitCheck; // media buffers @@ -364,8 +365,8 @@ void FLACParser::metadataCallback(const FLAC__StreamMetadata *metadata) case FLAC__METADATA_TYPE_PICTURE: if (mFileMetadata != 0) { const FLAC__StreamMetadata_Picture *p = &metadata->data.picture; - mFileMetadata->setData(kKeyAlbumArt, - MetaData::TYPE_NONE, p->data, p->data_length); + AMediaFormat_setBuffer(mFileMetadata, AMEDIAFORMAT_KEY_ALBUMART, + p->data, p->data_length); } break; default: @@ -487,8 +488,8 @@ static void copyTrespass( FLACParser::FLACParser( DataSourceHelper *dataSource, - MetaDataBase *fileMetadata, - MetaDataBase *trackMetadata) + AMediaFormat *fileMetadata, + AMediaFormat *trackMetadata) : mDataSource(dataSource), mFileMetadata(fileMetadata), mTrackMetadata(trackMetadata), @@ -614,20 +615,25 @@ status_t FLACParser::init() } // populate track metadata if (mTrackMetadata != 0) { - mTrackMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); - mTrackMetadata->setInt32(kKeyChannelCount, getChannels()); - mTrackMetadata->setInt32(kKeySampleRate, getSampleRate()); - mTrackMetadata->setInt32(kKeyPcmEncoding, kAudioEncodingPcm16bit); + AMediaFormat_setString(mTrackMetadata, + AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_RAW); + AMediaFormat_setInt32(mTrackMetadata, + AMEDIAFORMAT_KEY_CHANNEL_COUNT, getChannels()); + AMediaFormat_setInt32(mTrackMetadata, + AMEDIAFORMAT_KEY_SAMPLE_RATE, getSampleRate()); + AMediaFormat_setInt32(mTrackMetadata, + AMEDIAFORMAT_KEY_PCM_ENCODING, kAudioEncodingPcm16bit); // sample rate is non-zero, so division by zero not possible - mTrackMetadata->setInt64(kKeyDuration, - (getTotalSamples() * 1000000LL) / getSampleRate()); + AMediaFormat_setInt64(mTrackMetadata, + AMEDIAFORMAT_KEY_DURATION, (getTotalSamples() * 1000000LL) / getSampleRate()); } } else { ALOGE("missing STREAMINFO"); return NO_INIT; } if (mFileMetadata != 0) { - mFileMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC); + AMediaFormat_setString(mFileMetadata, + AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC); } return OK; } @@ -708,7 +714,7 @@ MediaBufferBase *FLACParser::readBuffer(bool doSeek, FLAC__uint64 sample) FLACSource::FLACSource( DataSourceHelper *dataSource, - MetaDataBase &trackMetadata) + AMediaFormat *trackMetadata) : mDataSource(dataSource), mTrackMetadata(trackMetadata), mParser(0), @@ -730,7 +736,7 @@ FLACSource::~FLACSource() delete mParser; } -status_t FLACSource::start() +media_status_t FLACSource::start() { ALOGV("FLACSource::start"); @@ -738,10 +744,10 @@ status_t FLACSource::start() mParser->allocateBuffers(); mStarted = true; - return OK; + return AMEDIA_OK; } -status_t FLACSource::stop() +media_status_t FLACSource::stop() { ALOGV("FLACSource::stop"); @@ -749,16 +755,15 @@ status_t FLACSource::stop() mParser->releaseBuffers(); mStarted = false; - return OK; + return AMEDIA_OK; } -status_t FLACSource::getFormat(MetaDataBase &meta) +media_status_t FLACSource::getFormat(AMediaFormat *meta) { - meta = mTrackMetadata; - return OK; + return AMediaFormat_copy(meta, mTrackMetadata); } -status_t FLACSource::read( +media_status_t FLACSource::read( MediaBufferBase **outBuffer, const ReadOptions *options) { MediaBufferBase *buffer; @@ -782,7 +787,7 @@ status_t FLACSource::read( buffer = mParser->readBuffer(); } *outBuffer = buffer; - return buffer != NULL ? (status_t) OK : (status_t) ERROR_END_OF_STREAM; + return buffer != NULL ? AMEDIA_OK : AMEDIA_ERROR_END_OF_STREAM; } // FLACExtractor @@ -795,7 +800,9 @@ FLACExtractor::FLACExtractor( { ALOGV("FLACExtractor::FLACExtractor"); // FLACParser will fill in the metadata for us - mParser = new FLACParser(mDataSource, &mFileMetadata, &mTrackMetadata); + mFileMetadata = AMediaFormat_new(); + mTrackMetadata = AMediaFormat_new(); + mParser = new FLACParser(mDataSource, mFileMetadata, mTrackMetadata); mInitCheck = mParser->initCheck(); } @@ -804,6 +811,8 @@ FLACExtractor::~FLACExtractor() ALOGV("~FLACExtractor::FLACExtractor"); delete mParser; delete mDataSource; + AMediaFormat_delete(mFileMetadata); + AMediaFormat_delete(mTrackMetadata); } size_t FLACExtractor::countTracks() @@ -811,7 +820,7 @@ size_t FLACExtractor::countTracks() return mInitCheck == OK ? 1 : 0; } -MediaTrackHelper *FLACExtractor::getTrack(size_t index) +MediaTrackHelperV2 *FLACExtractor::getTrack(size_t index) { if (mInitCheck != OK || index > 0) { return NULL; @@ -819,20 +828,18 @@ MediaTrackHelper *FLACExtractor::getTrack(size_t index) return new FLACSource(mDataSource, mTrackMetadata); } -status_t FLACExtractor::getTrackMetaData( - MetaDataBase &meta, +media_status_t FLACExtractor::getTrackMetaData( + AMediaFormat *meta, size_t index, uint32_t /* flags */) { if (mInitCheck != OK || index > 0) { - return UNKNOWN_ERROR; + return AMEDIA_ERROR_UNKNOWN; } - meta = mTrackMetadata; - return OK; + return AMediaFormat_copy(meta, mTrackMetadata); } -status_t FLACExtractor::getMetaData(MetaDataBase &meta) +media_status_t FLACExtractor::getMetaData(AMediaFormat *meta) { - meta = mFileMetadata; - return OK; + return AMediaFormat_copy(meta, mFileMetadata); } // Sniffer @@ -861,22 +868,22 @@ extern "C" { __attribute__ ((visibility ("default"))) ExtractorDef GETEXTRACTORDEF() { return { - EXTRACTORDEF_VERSION, + EXTRACTORDEF_VERSION_CURRENT, UUID("1364b048-cc45-4fda-9934-327d0ebf9829"), 1, "FLAC Extractor", { - []( + .v2 = []( CDataSource *source, float *confidence, void **, - FreeMetaFunc *) -> CreatorFunc { + FreeMetaFunc *) -> CreatorFuncV2 { DataSourceHelper helper(source); if (SniffFLAC(&helper, confidence)) { return []( CDataSource *source, - void *) -> CMediaExtractor* { - return wrap(new FLACExtractor(new DataSourceHelper(source)));}; + void *) -> CMediaExtractorV2* { + return wrapV2(new FLACExtractor(new DataSourceHelper(source)));}; } return NULL; } diff --git a/media/extractors/flac/FLACExtractor.h b/media/extractors/flac/FLACExtractor.h index 829f661f3a..323307b4d9 100644 --- a/media/extractors/flac/FLACExtractor.h +++ b/media/extractors/flac/FLACExtractor.h @@ -20,23 +20,23 @@ #include #include #include -#include +#include #include namespace android { class FLACParser; -class FLACExtractor : public MediaExtractorPluginHelper { +class FLACExtractor : public MediaExtractorPluginHelperV2 { public: explicit FLACExtractor(DataSourceHelper *source); virtual size_t countTracks(); - virtual MediaTrackHelper *getTrack(size_t index); - virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags); + virtual MediaTrackHelperV2 *getTrack(size_t index); + virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags); - virtual status_t getMetaData(MetaDataBase& meta); + virtual media_status_t getMetaData(AMediaFormat *meta); virtual const char * name() { return "FLACExtractor"; } protected: @@ -46,10 +46,10 @@ private: DataSourceHelper *mDataSource; FLACParser *mParser; status_t mInitCheck; - MetaDataBase mFileMetadata; + AMediaFormat *mFileMetadata; // There is only one track - MetaDataBase mTrackMetadata; + AMediaFormat *mTrackMetadata; FLACExtractor(const FLACExtractor &); FLACExtractor &operator=(const FLACExtractor &); diff --git a/media/extractors/ogg/Android.bp b/media/extractors/ogg/Android.bp index 7c6fc7523d..c6deb18129 100644 --- a/media/extractors/ogg/Android.bp +++ b/media/extractors/ogg/Android.bp @@ -10,10 +10,12 @@ cc_library_shared { shared_libs: [ "liblog", "libmediaextractor", + "libmediandk", ], static_libs: [ "libstagefright_foundation", + "libstagefright_metadatautils", "libutils", "libvorbisidec", ], diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp index 123ac91379..1b4fe27329 100644 --- a/media/extractors/ogg/OggExtractor.cpp +++ b/media/extractors/ogg/OggExtractor.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -34,6 +33,7 @@ #include #include #include +#include #include extern "C" { @@ -47,15 +47,15 @@ extern "C" { namespace android { -struct OggSource : public MediaTrackHelper { +struct OggSource : public MediaTrackHelperV2 { explicit OggSource(OggExtractor *extractor); - virtual status_t getFormat(MetaDataBase &); + virtual media_status_t getFormat(AMediaFormat *); - virtual status_t start(); - virtual status_t stop(); + virtual media_status_t start(); + virtual media_status_t stop(); - virtual status_t read( + virtual media_status_t read( MediaBufferBase **buffer, const ReadOptions *options = NULL); protected: @@ -77,7 +77,7 @@ struct MyOggExtractor { int64_t seekPreRollUs); virtual ~MyOggExtractor(); - status_t getFormat(MetaDataBase &) const; + media_status_t getFormat(AMediaFormat *) const; // Returns an approximate bitrate in bits per second. virtual uint64_t approxBitrate() const = 0; @@ -88,9 +88,8 @@ struct MyOggExtractor { status_t init(); - status_t getFileMetaData(MetaDataBase &meta) { - meta = mFileMeta; - return OK; + media_status_t getFileMetaData(AMediaFormat *meta) { + return AMediaFormat_copy(meta, mFileMeta); } protected: @@ -129,8 +128,8 @@ protected: vorbis_info mVi; vorbis_comment mVc; - MetaDataBase mMeta; - MetaDataBase mFileMeta; + AMediaFormat *mMeta; + AMediaFormat *mFileMeta; Vector mTableOfContents; @@ -237,27 +236,27 @@ OggSource::~OggSource() { } } -status_t OggSource::getFormat(MetaDataBase &meta) { +media_status_t OggSource::getFormat(AMediaFormat *meta) { return mExtractor->mImpl->getFormat(meta); } -status_t OggSource::start() { +media_status_t OggSource::start() { if (mStarted) { - return INVALID_OPERATION; + return AMEDIA_ERROR_INVALID_OPERATION; } mStarted = true; - return OK; + return AMEDIA_OK; } -status_t OggSource::stop() { +media_status_t OggSource::stop() { mStarted = false; - return OK; + return AMEDIA_OK; } -status_t OggSource::read( +media_status_t OggSource::read( MediaBufferBase **out, const ReadOptions *options) { *out = NULL; @@ -266,7 +265,7 @@ status_t OggSource::read( if (options && options->getSeekTo(&seekTimeUs, &mode)) { status_t err = mExtractor->mImpl->seekToTime(seekTimeUs); if (err != OK) { - return err; + return AMEDIA_ERROR_UNKNOWN; } } @@ -274,7 +273,7 @@ status_t OggSource::read( status_t err = mExtractor->mImpl->readNextPacket(&packet); if (err != OK) { - return err; + return AMEDIA_ERROR_UNKNOWN; } #if 0 @@ -290,7 +289,7 @@ status_t OggSource::read( *out = packet; - return OK; + return AMEDIA_OK; } //////////////////////////////////////////////////////////////////////////////// @@ -316,16 +315,19 @@ MyOggExtractor::MyOggExtractor( vorbis_info_init(&mVi); vorbis_comment_init(&mVc); + mMeta = AMediaFormat_new(); + mFileMeta = AMediaFormat_new(); } MyOggExtractor::~MyOggExtractor() { + AMediaFormat_delete(mFileMeta); + AMediaFormat_delete(mMeta); vorbis_comment_clear(&mVc); vorbis_info_clear(&mVi); } -status_t MyOggExtractor::getFormat(MetaDataBase &meta) const { - meta = mMeta; - return OK; +media_status_t MyOggExtractor::getFormat(AMediaFormat *meta) const { + return AMediaFormat_copy(meta, mMeta); } status_t MyOggExtractor::findNextPage( @@ -832,7 +834,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT } status_t MyOggExtractor::init() { - mMeta.setCString(kKeyMIMEType, mMimeType); + AMediaFormat_setString(mMeta, AMEDIAFORMAT_KEY_MIME, mMimeType); status_t err; MediaBufferBase *packet; @@ -865,7 +867,7 @@ status_t MyOggExtractor::init() { int64_t durationUs = getTimeUsOfGranule(lastGranulePosition); - mMeta.setInt64(kKeyDuration, durationUs); + AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_DURATION, durationUs); buildTableOfContents(); } @@ -981,11 +983,14 @@ status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) { mChannelCount = data[9]; mCodecDelay = U16LE_AT(&data[10]); - mMeta.setData(kKeyOpusHeader, 0, data, size); - mMeta.setInt32(kKeySampleRate, kOpusSampleRate); - mMeta.setInt32(kKeyChannelCount, mChannelCount); - mMeta.setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/); - mMeta.setInt64(kKeyOpusCodecDelay /* ns */, + // kKeyOpusHeader is csd-0 + AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_0, data, size); + AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, kOpusSampleRate); + AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mChannelCount); + // are these actually used anywhere? + // (they are kKeyOpusSeekPreRoll and kKeyOpusCodecDelay respectively) + AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_CSD_2, kOpusSeekPreRollUs * 1000 /* = 80 ms*/); + AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_CSD_1, mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate); return OK; @@ -1122,10 +1127,10 @@ status_t MyVorbisExtractor::verifyHeader( return ERROR_MALFORMED; } - mMeta.setData(kKeyVorbisInfo, 0, data, size); - mMeta.setInt32(kKeySampleRate, mVi.rate); - mMeta.setInt32(kKeyChannelCount, mVi.channels); - mMeta.setInt32(kKeyBitRate, mVi.bitrate_nominal); + AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_0, data, size); + AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, mVi.rate); + AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mVi.channels); + AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_BIT_RATE, mVi.bitrate_nominal); ALOGV("lower-bitrate = %ld", mVi.bitrate_lower); ALOGV("upper-bitrate = %ld", mVi.bitrate_upper); @@ -1140,7 +1145,7 @@ status_t MyVorbisExtractor::verifyHeader( if (mSource->getSize(&size) == OK) { uint64_t bps = approxBitrate(); if (bps != 0) { - mMeta.setInt64(kKeyDuration, size * 8000000ll / bps); + AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_DURATION, size * 8000000ll / bps); } } break; @@ -1162,7 +1167,7 @@ status_t MyVorbisExtractor::verifyHeader( return ERROR_MALFORMED; } - mMeta.setData(kKeyVorbisBooks, 0, data, size); + AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_1, data, size); break; } } @@ -1180,12 +1185,12 @@ uint64_t MyVorbisExtractor::approxBitrate() const { void MyOggExtractor::parseFileMetaData() { - mFileMeta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); + AMediaFormat_setString(mFileMeta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_CONTAINER_OGG); for (int i = 0; i < mVc.comments; ++i) { const char *comment = mVc.user_comments[i]; size_t commentLength = mVc.comment_lengths[i]; - parseVorbisComment(&mFileMeta, comment, commentLength); + parseVorbisComment(mFileMeta, comment, commentLength); //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); } } @@ -1227,7 +1232,7 @@ size_t OggExtractor::countTracks() { return mInitCheck != OK ? 0 : 1; } -MediaTrackHelper *OggExtractor::getTrack(size_t index) { +MediaTrackHelperV2 *OggExtractor::getTrack(size_t index) { if (index >= 1) { return NULL; } @@ -1235,27 +1240,27 @@ MediaTrackHelper *OggExtractor::getTrack(size_t index) { return new OggSource(this); } -status_t OggExtractor::getTrackMetaData( - MetaDataBase &meta, +media_status_t OggExtractor::getTrackMetaData( + AMediaFormat *meta, size_t index, uint32_t /* flags */) { if (index >= 1) { - return UNKNOWN_ERROR; + return AMEDIA_ERROR_UNKNOWN; } return mImpl->getFormat(meta); } -status_t OggExtractor::getMetaData(MetaDataBase &meta) { +media_status_t OggExtractor::getMetaData(AMediaFormat *meta) { return mImpl->getFileMetaData(meta); } -static CMediaExtractor* CreateExtractor( +static CMediaExtractorV2* CreateExtractor( CDataSource *source, void *) { - return wrap(new OggExtractor(new DataSourceHelper(source))); + return wrapV2(new OggExtractor(new DataSourceHelper(source))); } -static CreatorFunc Sniff( +static CreatorFuncV2 Sniff( CDataSource *source, float *confidence, void **, @@ -1276,11 +1281,11 @@ extern "C" { __attribute__ ((visibility ("default"))) ExtractorDef GETEXTRACTORDEF() { return { - EXTRACTORDEF_VERSION, + EXTRACTORDEF_VERSION_CURRENT, UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"), 1, // version "Ogg Extractor", - { Sniff } + { .v2 = Sniff } }; } diff --git a/media/extractors/ogg/OggExtractor.h b/media/extractors/ogg/OggExtractor.h index c70f832e2e..cd674f3e5b 100644 --- a/media/extractors/ogg/OggExtractor.h +++ b/media/extractors/ogg/OggExtractor.h @@ -21,6 +21,7 @@ #include #include #include +#include namespace android { @@ -30,14 +31,14 @@ class String8; struct MyOggExtractor; struct OggSource; -struct OggExtractor : public MediaExtractorPluginHelper { +struct OggExtractor : public MediaExtractorPluginHelperV2 { explicit OggExtractor(DataSourceHelper *source); virtual size_t countTracks(); - virtual MediaTrackHelper *getTrack(size_t index); - virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags); + virtual MediaTrackHelperV2 *getTrack(size_t index); + virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags); - virtual status_t getMetaData(MetaDataBase& meta); + virtual media_status_t getMetaData(AMediaFormat *meta); virtual const char * name() { return "OggExtractor"; } protected: diff --git a/media/libmediaextractor/Android.bp b/media/libmediaextractor/Android.bp index 4ffbb69de8..0871d60de8 100644 --- a/media/libmediaextractor/Android.bp +++ b/media/libmediaextractor/Android.bp @@ -38,7 +38,6 @@ cc_library { "MediaSource.cpp", "MetaData.cpp", "MetaDataBase.cpp", - "VorbisComment.cpp", ], clang: true, diff --git a/media/libmediaextractor/VorbisComment.cpp b/media/libmediaextractor/VorbisComment.cpp deleted file mode 100644 index 6d16385dab..0000000000 --- a/media/libmediaextractor/VorbisComment.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//#define LOG_NDEBUG 0 -#define LOG_TAG "VorbisComment" -#include - -#include "media/VorbisComment.h" - -#include -#include -#include -#include -#include - -namespace android { - -static void extractAlbumArt( - MetaDataBase *fileMeta, const void *data, size_t size) { - ALOGV("extractAlbumArt from '%s'", (const char *)data); - - sp flacBuffer = decodeBase64(AString((const char *)data, size)); - if (flacBuffer == NULL) { - ALOGE("malformed base64 encoded data."); - return; - } - - size_t flacSize = flacBuffer->size(); - uint8_t *flac = flacBuffer->data(); - ALOGV("got flac of size %zu", flacSize); - - uint32_t picType; - uint32_t typeLen; - uint32_t descLen; - uint32_t dataLen; - char type[128]; - - if (flacSize < 8) { - return; - } - - picType = U32_AT(flac); - - if (picType != 3) { - // This is not a front cover. - return; - } - - typeLen = U32_AT(&flac[4]); - if (typeLen > sizeof(type) - 1) { - return; - } - - // we've already checked above that flacSize >= 8 - if (flacSize - 8 < typeLen) { - return; - } - - memcpy(type, &flac[8], typeLen); - type[typeLen] = '\0'; - - ALOGV("picType = %d, type = '%s'", picType, type); - - if (!strcmp(type, "-->")) { - // This is not inline cover art, but an external url instead. - return; - } - - if (flacSize < 32 || flacSize - 32 < typeLen) { - return; - } - - descLen = U32_AT(&flac[8 + typeLen]); - if (flacSize - 32 - typeLen < descLen) { - return; - } - - dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]); - - // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0 - if (flacSize - 32 - typeLen - descLen < dataLen) { - return; - } - - ALOGV("got image data, %zu trailing bytes", - flacSize - 32 - typeLen - descLen - dataLen); - - fileMeta->setData( - kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen); -} - -void parseVorbisComment( - MetaDataBase *fileMeta, const char *comment, size_t commentLength) -{ - struct { - const char *const mTag; - uint32_t mKey; - } kMap[] = { - { "TITLE", kKeyTitle }, - { "ARTIST", kKeyArtist }, - { "ALBUMARTIST", kKeyAlbumArtist }, - { "ALBUM ARTIST", kKeyAlbumArtist }, - { "COMPILATION", kKeyCompilation }, - { "ALBUM", kKeyAlbum }, - { "COMPOSER", kKeyComposer }, - { "GENRE", kKeyGenre }, - { "AUTHOR", kKeyAuthor }, - { "TRACKNUMBER", kKeyCDTrackNumber }, - { "DISCNUMBER", kKeyDiscNumber }, - { "DATE", kKeyDate }, - { "YEAR", kKeyYear }, - { "LYRICIST", kKeyWriter }, - { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, - { "ANDROID_LOOP", kKeyAutoLoop }, - }; - - for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { - size_t tagLen = strlen(kMap[j].mTag); - if (!strncasecmp(kMap[j].mTag, comment, tagLen) - && comment[tagLen] == '=') { - if (kMap[j].mKey == kKeyAlbumArt) { - extractAlbumArt( - fileMeta, - &comment[tagLen + 1], - commentLength - tagLen - 1); - } else if (kMap[j].mKey == kKeyAutoLoop) { - if (!strcasecmp(&comment[tagLen + 1], "true")) { - fileMeta->setInt32(kKeyAutoLoop, true); - } - } else { - fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); - } - } - } - -} - -} // namespace android diff --git a/media/libmediaextractor/include/media/VorbisComment.h b/media/libmediaextractor/include/media/VorbisComment.h deleted file mode 100644 index 8ba329503c..0000000000 --- a/media/libmediaextractor/include/media/VorbisComment.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#ifndef VORBIS_COMMENT_H_ -#define VORBIS_COMMENT_H_ - -namespace android { - -class MetaDataBase; - -void parseVorbisComment( - MetaDataBase *fileMeta, const char *comment, size_t commentLength); - -} // namespace android - -#endif // VORBIS_COMMENT_H_ diff --git a/media/libstagefright/MetaDataUtils.cpp b/media/libstagefright/MetaDataUtils.cpp index 5672145e3c..2cf79c3479 100644 --- a/media/libstagefright/MetaDataUtils.cpp +++ b/media/libstagefright/MetaDataUtils.cpp @@ -19,8 +19,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -192,4 +194,135 @@ bool MakeAACCodecSpecificData( return true; } + +static void extractAlbumArt( + AMediaFormat *fileMeta, const void *data, size_t size) { + ALOGV("extractAlbumArt from '%s'", (const char *)data); + + size_t inLen = strnlen((const char *)data, size); + size_t flacSize = inLen / 4 * 3; + uint8_t *flac = new uint8_t[flacSize]; + if (!decodeBase64(flac, &flacSize, (const char*)data)) { + ALOGE("malformed base64 encoded data."); + delete[] flac; + return; + } + + ALOGV("got flac of size %zu", flacSize); + + uint32_t picType; + uint32_t typeLen; + uint32_t descLen; + uint32_t dataLen; + char type[128]; + + if (flacSize < 8) { + delete[] flac; + return; + } + + picType = U32_AT(flac); + + if (picType != 3) { + // This is not a front cover. + delete[] flac; + return; + } + + typeLen = U32_AT(&flac[4]); + if (typeLen > sizeof(type) - 1) { + delete[] flac; + return; + } + + // we've already checked above that flacSize >= 8 + if (flacSize - 8 < typeLen) { + delete[] flac; + return; + } + + memcpy(type, &flac[8], typeLen); + type[typeLen] = '\0'; + + ALOGV("picType = %d, type = '%s'", picType, type); + + if (!strcmp(type, "-->")) { + // This is not inline cover art, but an external url instead. + delete[] flac; + return; + } + + if (flacSize < 32 || flacSize - 32 < typeLen) { + delete[] flac; + return; + } + + descLen = U32_AT(&flac[8 + typeLen]); + if (flacSize - 32 - typeLen < descLen) { + delete[] flac; + return; + } + + dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]); + + // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0 + if (flacSize - 32 - typeLen - descLen < dataLen) { + delete[] flac; + return; + } + + ALOGV("got image data, %zu trailing bytes", + flacSize - 32 - typeLen - descLen - dataLen); + + AMediaFormat_setBuffer(fileMeta, AMEDIAFORMAT_KEY_ALBUMART, + &flac[8 + typeLen + 4 + descLen + 20], dataLen); + + delete[] flac; +} + +void parseVorbisComment( + AMediaFormat *fileMeta, const char *comment, size_t commentLength) { + struct { + const char *const mTag; + const char *mKey; + } kMap[] = { + { "TITLE", AMEDIAFORMAT_KEY_TITLE }, + { "ARTIST", AMEDIAFORMAT_KEY_ARTIST }, + { "ALBUMARTIST", AMEDIAFORMAT_KEY_ALBUMARTIST }, + { "ALBUM ARTIST", AMEDIAFORMAT_KEY_ALBUMARTIST }, + { "COMPILATION", AMEDIAFORMAT_KEY_COMPILATION }, + { "ALBUM", AMEDIAFORMAT_KEY_ALBUM }, + { "COMPOSER", AMEDIAFORMAT_KEY_COMPOSER }, + { "GENRE", AMEDIAFORMAT_KEY_GENRE }, + { "AUTHOR", AMEDIAFORMAT_KEY_AUTHOR }, + { "TRACKNUMBER", AMEDIAFORMAT_KEY_CDTRACKNUMBER }, + { "DISCNUMBER", AMEDIAFORMAT_KEY_DISCNUMBER }, + { "DATE", AMEDIAFORMAT_KEY_DATE }, + { "YEAR", AMEDIAFORMAT_KEY_YEAR }, + { "LYRICIST", AMEDIAFORMAT_KEY_LYRICIST }, + { "METADATA_BLOCK_PICTURE", AMEDIAFORMAT_KEY_ALBUMART }, + { "ANDROID_LOOP", AMEDIAFORMAT_KEY_LOOP }, + }; + + for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { + size_t tagLen = strlen(kMap[j].mTag); + if (!strncasecmp(kMap[j].mTag, comment, tagLen) + && comment[tagLen] == '=') { + if (kMap[j].mKey == AMEDIAFORMAT_KEY_ALBUMART) { + extractAlbumArt( + fileMeta, + &comment[tagLen + 1], + commentLength - tagLen - 1); + } else if (kMap[j].mKey == AMEDIAFORMAT_KEY_LOOP) { + if (!strcasecmp(&comment[tagLen + 1], "true")) { + AMediaFormat_setInt32(fileMeta, AMEDIAFORMAT_KEY_LOOP, 1); + } + } else { + AMediaFormat_setString(fileMeta, kMap[j].mKey, &comment[tagLen + 1]); + } + } + } + +} + } // namespace android diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp index a17b648830..456e2e3a2d 100644 --- a/media/libstagefright/Utils.cpp +++ b/media/libstagefright/Utils.cpp @@ -578,8 +578,10 @@ std::vector> tagMappings { { "cdtracknum", kKeyCDTrackNumber }, { "compilation", kKeyCompilation }, { "composer", kKeyComposer }, + { "date", kKeyDate }, { "discnum", kKeyDiscNumber }, { "genre", kKeyGenre }, + { "lyricist", kKeyWriter }, { "title", kKeyTitle }, { "year", kKeyYear }, } @@ -596,6 +598,11 @@ void convertMessageToMetaDataTags(const sp &msg, sp &meta) { if (msg->findBuffer("albumart", &buf)) { meta->setData(kKeyAlbumArt, MetaDataBase::Type::TYPE_NONE, buf->data(), buf->size()); } + + int32_t loop; + if (msg->findInt32("loop", &loop)) { + meta->setInt32(kKeyAutoLoop, loop); + } } void convertMetaDataToMessageTags(const MetaDataBase *meta, sp format) { @@ -612,6 +619,10 @@ void convertMetaDataToMessageTags(const MetaDataBase *meta, sp format) sp buf = ABuffer::CreateAsCopy(data, size); format->setBuffer("albumart", buf); } + int32_t loop; + if (meta->findInt32(kKeyAutoLoop, &loop)) { + format->setInt32("loop", loop); + } } status_t convertMetaDataToMessage( diff --git a/media/libstagefright/foundation/base64.cpp b/media/libstagefright/foundation/base64.cpp index 8f32582a69..834b88ff70 100644 --- a/media/libstagefright/foundation/base64.cpp +++ b/media/libstagefright/foundation/base64.cpp @@ -28,14 +28,31 @@ sp decodeBase64(const AString &s) { return NULL; } + size_t bufSize = n / 4 * 3; + sp buf = new ABuffer(bufSize); + + if (decodeBase64(buf->data(), &bufSize, s.c_str())) { + buf->setRange(0, bufSize); + return buf; + } + return NULL; +} + +bool decodeBase64(uint8_t *out, size_t *inOutBufSize, const char* s) { + size_t n = strlen(s); + + if ((n % 4) != 0) { + return false; + } + size_t padding = 0; - if (n >= 1 && s.c_str()[n - 1] == '=') { + if (n >= 1 && s[n - 1] == '=') { padding = 1; - if (n >= 2 && s.c_str()[n - 2] == '=') { + if (n >= 2 && s[n - 2] == '=') { padding = 2; - if (n >= 3 && s.c_str()[n - 3] == '=') { + if (n >= 3 && s[n - 3] == '=') { padding = 3; } } @@ -45,15 +62,13 @@ sp decodeBase64(const AString &s) { // already made sure that n % 4 == 0. size_t outLen = (n / 4) * 3 - padding; - sp buffer = new ABuffer(outLen); - uint8_t *out = buffer->data(); - if (out == NULL || buffer->size() < outLen) { - return NULL; + if (out == NULL || *inOutBufSize < outLen) { + return false; } size_t j = 0; uint32_t accum = 0; for (size_t i = 0; i < n; ++i) { - char c = s.c_str()[i]; + char c = s[i]; unsigned value; if (c >= 'A' && c <= 'Z') { value = c - 'A'; @@ -66,10 +81,10 @@ sp decodeBase64(const AString &s) { } else if (c == '/' || c == '_') { value = 63; } else if (c != '=') { - return NULL; + return false; } else { if (i < n - padding) { - return NULL; + return false; } value = 0; @@ -86,7 +101,8 @@ sp decodeBase64(const AString &s) { } } - return buffer; + *inOutBufSize = j; + return true; } static char encode6Bit(unsigned x) { diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h b/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h index abc95e013e..60fb9ff5f9 100644 --- a/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h +++ b/media/libstagefright/foundation/include/media/stagefright/foundation/base64.h @@ -26,6 +26,9 @@ struct ABuffer; struct AString; sp decodeBase64(const AString &s); + +bool decodeBase64(uint8_t *out, size_t *inOutBufSize, const char* s); + void encodeBase64(const void *data, size_t size, AString *out); void encodeBase64Url(const void *data, size_t size, AString *out); diff --git a/media/libstagefright/include/media/stagefright/MetaDataUtils.h b/media/libstagefright/include/media/stagefright/MetaDataUtils.h index fd79a9e748..e87c7f9634 100644 --- a/media/libstagefright/include/media/stagefright/MetaDataUtils.h +++ b/media/libstagefright/include/media/stagefright/MetaDataUtils.h @@ -34,6 +34,9 @@ bool MakeAACCodecSpecificData(MetaDataBase &meta, unsigned profile, unsigned sam bool MakeAACCodecSpecificData(AMediaFormat *meta, unsigned profile, unsigned sampling_freq_index, unsigned channel_configuration); +void parseVorbisComment( + AMediaFormat *fileMeta, const char *comment, size_t commentLength); + } // namespace android #endif // META_DATA_UTILS_H_ diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp index a55067e591..22fbb42767 100644 --- a/media/ndk/NdkMediaFormat.cpp +++ b/media/ndk/NdkMediaFormat.cpp @@ -291,6 +291,7 @@ EXPORT const char* AMEDIAFORMAT_KEY_CSD = "csd"; EXPORT const char* AMEDIAFORMAT_KEY_CSD_0 = "csd-0"; EXPORT const char* AMEDIAFORMAT_KEY_CSD_1 = "csd-1"; EXPORT const char* AMEDIAFORMAT_KEY_CSD_2 = "csd-2"; +EXPORT const char* AMEDIAFORMAT_KEY_DATE = "date"; EXPORT const char* AMEDIAFORMAT_KEY_DISCNUMBER = "discnum"; EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_CROP = "crop"; EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_HEIGHT = "display-height"; @@ -314,6 +315,8 @@ EXPORT const char* AMEDIAFORMAT_KEY_I_FRAME_INTERVAL = "i-frame-interval"; EXPORT const char* AMEDIAFORMAT_KEY_LANGUAGE = "language"; EXPORT const char* AMEDIAFORMAT_KEY_LATENCY = "latency"; EXPORT const char* AMEDIAFORMAT_KEY_LEVEL = "level"; +EXPORT const char* AMEDIAFORMAT_KEY_LOOP = "loop"; +EXPORT const char* AMEDIAFORMAT_KEY_LYRICIST = "lyricist"; EXPORT const char* AMEDIAFORMAT_KEY_MAX_HEIGHT = "max-height"; EXPORT const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE = "max-input-size"; EXPORT const char* AMEDIAFORMAT_KEY_MAX_WIDTH = "max-width"; diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h index 2bdc5e36bb..3fc28f3fb0 100644 --- a/media/ndk/include/media/NdkMediaFormat.h +++ b/media/ndk/include/media/NdkMediaFormat.h @@ -184,10 +184,13 @@ extern const char* AMEDIAFORMAT_KEY_AUTHOR __INTRODUCED_IN(29); extern const char* AMEDIAFORMAT_KEY_CDTRACKNUMBER __INTRODUCED_IN(29); extern const char* AMEDIAFORMAT_KEY_COMPILATION __INTRODUCED_IN(29); extern const char* AMEDIAFORMAT_KEY_COMPOSER __INTRODUCED_IN(29); +extern const char* AMEDIAFORMAT_KEY_DATE __INTRODUCED_IN(29); extern const char* AMEDIAFORMAT_KEY_DISCNUMBER __INTRODUCED_IN(29); extern const char* AMEDIAFORMAT_KEY_ENCODER_DELAY __INTRODUCED_IN(29); extern const char* AMEDIAFORMAT_KEY_ENCODER_PADDING __INTRODUCED_IN(29); extern const char* AMEDIAFORMAT_KEY_GENRE __INTRODUCED_IN(29); +extern const char* AMEDIAFORMAT_KEY_LOOP __INTRODUCED_IN(29); +extern const char* AMEDIAFORMAT_KEY_LYRICIST __INTRODUCED_IN(29); extern const char* AMEDIAFORMAT_KEY_TITLE __INTRODUCED_IN(29); extern const char* AMEDIAFORMAT_KEY_YEAR __INTRODUCED_IN(29);