Convert Ogg and Flac extractors to use AMediaFormat

Bug: 111407253
Test: manual, CTS
Change-Id: I8aeb44ceeb831bb558cac1123f0aaade8163abf8
gugelfrei
Marco Nelissen 6 years ago
parent fdd42e9535
commit 4d026f5583

@ -1 +0,0 @@
../../media/libmediaextractor/include/media/VorbisComment.h

@ -10,11 +10,14 @@ cc_library_shared {
shared_libs: [ shared_libs: [
"liblog", "liblog",
"libmediaextractor", "libmediaextractor",
"libmediandk",
], ],
static_libs: [ static_libs: [
"libFLAC", "libFLAC",
"libstagefright_foundation", "libstagefright_foundation",
"libstagefright_metadatautils",
"libutils",
], ],
name: "libflacextractor", name: "libflacextractor",

@ -25,7 +25,7 @@
#include "FLAC/stream_decoder.h" #include "FLAC/stream_decoder.h"
#include <media/MediaExtractorPluginApi.h> #include <media/MediaExtractorPluginApi.h>
#include <media/VorbisComment.h> #include <media/NdkMediaFormat.h>
#include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/base64.h> #include <media/stagefright/foundation/base64.h>
@ -33,24 +33,25 @@
#include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h> #include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h> #include <media/stagefright/MetaData.h>
#include <media/stagefright/MetaDataUtils.h>
#include <media/stagefright/MediaBufferBase.h> #include <media/stagefright/MediaBufferBase.h>
namespace android { namespace android {
class FLACParser; class FLACParser;
class FLACSource : public MediaTrackHelper { class FLACSource : public MediaTrackHelperV2 {
public: public:
FLACSource( FLACSource(
DataSourceHelper *dataSource, DataSourceHelper *dataSource,
MetaDataBase &meta); AMediaFormat *meta);
virtual status_t start(); virtual media_status_t start();
virtual status_t stop(); virtual media_status_t stop();
virtual status_t getFormat(MetaDataBase &meta); virtual media_status_t getFormat(AMediaFormat *meta);
virtual status_t read( virtual media_status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL); MediaBufferBase **buffer, const ReadOptions *options = NULL);
protected: protected:
@ -58,7 +59,7 @@ protected:
private: private:
DataSourceHelper *mDataSource; DataSourceHelper *mDataSource;
MetaDataBase mTrackMetadata; AMediaFormat *mTrackMetadata;
FLACParser *mParser; FLACParser *mParser;
bool mInitCheck; bool mInitCheck;
bool mStarted; bool mStarted;
@ -81,8 +82,8 @@ public:
explicit FLACParser( explicit FLACParser(
DataSourceHelper *dataSource, DataSourceHelper *dataSource,
// If metadata pointers aren't provided, we don't fill them // If metadata pointers aren't provided, we don't fill them
MetaDataBase *fileMetadata = 0, AMediaFormat *fileMetadata = 0,
MetaDataBase *trackMetadata = 0); AMediaFormat *trackMetadata = 0);
virtual ~FLACParser(); virtual ~FLACParser();
@ -119,8 +120,8 @@ public:
private: private:
DataSourceHelper *mDataSource; DataSourceHelper *mDataSource;
MetaDataBase *mFileMetadata; AMediaFormat *mFileMetadata;
MetaDataBase *mTrackMetadata; AMediaFormat *mTrackMetadata;
bool mInitCheck; bool mInitCheck;
// media buffers // media buffers
@ -364,8 +365,8 @@ void FLACParser::metadataCallback(const FLAC__StreamMetadata *metadata)
case FLAC__METADATA_TYPE_PICTURE: case FLAC__METADATA_TYPE_PICTURE:
if (mFileMetadata != 0) { if (mFileMetadata != 0) {
const FLAC__StreamMetadata_Picture *p = &metadata->data.picture; const FLAC__StreamMetadata_Picture *p = &metadata->data.picture;
mFileMetadata->setData(kKeyAlbumArt, AMediaFormat_setBuffer(mFileMetadata, AMEDIAFORMAT_KEY_ALBUMART,
MetaData::TYPE_NONE, p->data, p->data_length); p->data, p->data_length);
} }
break; break;
default: default:
@ -487,8 +488,8 @@ static void copyTrespass(
FLACParser::FLACParser( FLACParser::FLACParser(
DataSourceHelper *dataSource, DataSourceHelper *dataSource,
MetaDataBase *fileMetadata, AMediaFormat *fileMetadata,
MetaDataBase *trackMetadata) AMediaFormat *trackMetadata)
: mDataSource(dataSource), : mDataSource(dataSource),
mFileMetadata(fileMetadata), mFileMetadata(fileMetadata),
mTrackMetadata(trackMetadata), mTrackMetadata(trackMetadata),
@ -614,20 +615,25 @@ status_t FLACParser::init()
} }
// populate track metadata // populate track metadata
if (mTrackMetadata != 0) { if (mTrackMetadata != 0) {
mTrackMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW); AMediaFormat_setString(mTrackMetadata,
mTrackMetadata->setInt32(kKeyChannelCount, getChannels()); AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_RAW);
mTrackMetadata->setInt32(kKeySampleRate, getSampleRate()); AMediaFormat_setInt32(mTrackMetadata,
mTrackMetadata->setInt32(kKeyPcmEncoding, kAudioEncodingPcm16bit); 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 // sample rate is non-zero, so division by zero not possible
mTrackMetadata->setInt64(kKeyDuration, AMediaFormat_setInt64(mTrackMetadata,
(getTotalSamples() * 1000000LL) / getSampleRate()); AMEDIAFORMAT_KEY_DURATION, (getTotalSamples() * 1000000LL) / getSampleRate());
} }
} else { } else {
ALOGE("missing STREAMINFO"); ALOGE("missing STREAMINFO");
return NO_INIT; return NO_INIT;
} }
if (mFileMetadata != 0) { if (mFileMetadata != 0) {
mFileMetadata->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_FLAC); AMediaFormat_setString(mFileMetadata,
AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
} }
return OK; return OK;
} }
@ -708,7 +714,7 @@ MediaBufferBase *FLACParser::readBuffer(bool doSeek, FLAC__uint64 sample)
FLACSource::FLACSource( FLACSource::FLACSource(
DataSourceHelper *dataSource, DataSourceHelper *dataSource,
MetaDataBase &trackMetadata) AMediaFormat *trackMetadata)
: mDataSource(dataSource), : mDataSource(dataSource),
mTrackMetadata(trackMetadata), mTrackMetadata(trackMetadata),
mParser(0), mParser(0),
@ -730,7 +736,7 @@ FLACSource::~FLACSource()
delete mParser; delete mParser;
} }
status_t FLACSource::start() media_status_t FLACSource::start()
{ {
ALOGV("FLACSource::start"); ALOGV("FLACSource::start");
@ -738,10 +744,10 @@ status_t FLACSource::start()
mParser->allocateBuffers(); mParser->allocateBuffers();
mStarted = true; mStarted = true;
return OK; return AMEDIA_OK;
} }
status_t FLACSource::stop() media_status_t FLACSource::stop()
{ {
ALOGV("FLACSource::stop"); ALOGV("FLACSource::stop");
@ -749,16 +755,15 @@ status_t FLACSource::stop()
mParser->releaseBuffers(); mParser->releaseBuffers();
mStarted = false; mStarted = false;
return OK; return AMEDIA_OK;
} }
status_t FLACSource::getFormat(MetaDataBase &meta) media_status_t FLACSource::getFormat(AMediaFormat *meta)
{ {
meta = mTrackMetadata; return AMediaFormat_copy(meta, mTrackMetadata);
return OK;
} }
status_t FLACSource::read( media_status_t FLACSource::read(
MediaBufferBase **outBuffer, const ReadOptions *options) MediaBufferBase **outBuffer, const ReadOptions *options)
{ {
MediaBufferBase *buffer; MediaBufferBase *buffer;
@ -782,7 +787,7 @@ status_t FLACSource::read(
buffer = mParser->readBuffer(); buffer = mParser->readBuffer();
} }
*outBuffer = buffer; *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 // FLACExtractor
@ -795,7 +800,9 @@ FLACExtractor::FLACExtractor(
{ {
ALOGV("FLACExtractor::FLACExtractor"); ALOGV("FLACExtractor::FLACExtractor");
// FLACParser will fill in the metadata for us // 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(); mInitCheck = mParser->initCheck();
} }
@ -804,6 +811,8 @@ FLACExtractor::~FLACExtractor()
ALOGV("~FLACExtractor::FLACExtractor"); ALOGV("~FLACExtractor::FLACExtractor");
delete mParser; delete mParser;
delete mDataSource; delete mDataSource;
AMediaFormat_delete(mFileMetadata);
AMediaFormat_delete(mTrackMetadata);
} }
size_t FLACExtractor::countTracks() size_t FLACExtractor::countTracks()
@ -811,7 +820,7 @@ size_t FLACExtractor::countTracks()
return mInitCheck == OK ? 1 : 0; return mInitCheck == OK ? 1 : 0;
} }
MediaTrackHelper *FLACExtractor::getTrack(size_t index) MediaTrackHelperV2 *FLACExtractor::getTrack(size_t index)
{ {
if (mInitCheck != OK || index > 0) { if (mInitCheck != OK || index > 0) {
return NULL; return NULL;
@ -819,20 +828,18 @@ MediaTrackHelper *FLACExtractor::getTrack(size_t index)
return new FLACSource(mDataSource, mTrackMetadata); return new FLACSource(mDataSource, mTrackMetadata);
} }
status_t FLACExtractor::getTrackMetaData( media_status_t FLACExtractor::getTrackMetaData(
MetaDataBase &meta, AMediaFormat *meta,
size_t index, uint32_t /* flags */) { size_t index, uint32_t /* flags */) {
if (mInitCheck != OK || index > 0) { if (mInitCheck != OK || index > 0) {
return UNKNOWN_ERROR; return AMEDIA_ERROR_UNKNOWN;
} }
meta = mTrackMetadata; return AMediaFormat_copy(meta, mTrackMetadata);
return OK;
} }
status_t FLACExtractor::getMetaData(MetaDataBase &meta) media_status_t FLACExtractor::getMetaData(AMediaFormat *meta)
{ {
meta = mFileMetadata; return AMediaFormat_copy(meta, mFileMetadata);
return OK;
} }
// Sniffer // Sniffer
@ -861,22 +868,22 @@ extern "C" {
__attribute__ ((visibility ("default"))) __attribute__ ((visibility ("default")))
ExtractorDef GETEXTRACTORDEF() { ExtractorDef GETEXTRACTORDEF() {
return { return {
EXTRACTORDEF_VERSION, EXTRACTORDEF_VERSION_CURRENT,
UUID("1364b048-cc45-4fda-9934-327d0ebf9829"), UUID("1364b048-cc45-4fda-9934-327d0ebf9829"),
1, 1,
"FLAC Extractor", "FLAC Extractor",
{ {
[]( .v2 = [](
CDataSource *source, CDataSource *source,
float *confidence, float *confidence,
void **, void **,
FreeMetaFunc *) -> CreatorFunc { FreeMetaFunc *) -> CreatorFuncV2 {
DataSourceHelper helper(source); DataSourceHelper helper(source);
if (SniffFLAC(&helper, confidence)) { if (SniffFLAC(&helper, confidence)) {
return []( return [](
CDataSource *source, CDataSource *source,
void *) -> CMediaExtractor* { void *) -> CMediaExtractorV2* {
return wrap(new FLACExtractor(new DataSourceHelper(source)));}; return wrapV2(new FLACExtractor(new DataSourceHelper(source)));};
} }
return NULL; return NULL;
} }

@ -20,23 +20,23 @@
#include <media/DataSourceBase.h> #include <media/DataSourceBase.h>
#include <media/MediaExtractorPluginApi.h> #include <media/MediaExtractorPluginApi.h>
#include <media/MediaExtractorPluginHelper.h> #include <media/MediaExtractorPluginHelper.h>
#include <media/stagefright/MetaDataBase.h> #include <media/NdkMediaFormat.h>
#include <utils/String8.h> #include <utils/String8.h>
namespace android { namespace android {
class FLACParser; class FLACParser;
class FLACExtractor : public MediaExtractorPluginHelper { class FLACExtractor : public MediaExtractorPluginHelperV2 {
public: public:
explicit FLACExtractor(DataSourceHelper *source); explicit FLACExtractor(DataSourceHelper *source);
virtual size_t countTracks(); virtual size_t countTracks();
virtual MediaTrackHelper *getTrack(size_t index); virtual MediaTrackHelperV2 *getTrack(size_t index);
virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags); 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"; } virtual const char * name() { return "FLACExtractor"; }
protected: protected:
@ -46,10 +46,10 @@ private:
DataSourceHelper *mDataSource; DataSourceHelper *mDataSource;
FLACParser *mParser; FLACParser *mParser;
status_t mInitCheck; status_t mInitCheck;
MetaDataBase mFileMetadata; AMediaFormat *mFileMetadata;
// There is only one track // There is only one track
MetaDataBase mTrackMetadata; AMediaFormat *mTrackMetadata;
FLACExtractor(const FLACExtractor &); FLACExtractor(const FLACExtractor &);
FLACExtractor &operator=(const FLACExtractor &); FLACExtractor &operator=(const FLACExtractor &);

@ -10,10 +10,12 @@ cc_library_shared {
shared_libs: [ shared_libs: [
"liblog", "liblog",
"libmediaextractor", "libmediaextractor",
"libmediandk",
], ],
static_libs: [ static_libs: [
"libstagefright_foundation", "libstagefright_foundation",
"libstagefright_metadatautils",
"libutils", "libutils",
"libvorbisidec", "libvorbisidec",
], ],

@ -24,7 +24,6 @@
#include <utils/Vector.h> #include <utils/Vector.h>
#include <media/DataSourceBase.h> #include <media/DataSourceBase.h>
#include <media/ExtractorUtils.h> #include <media/ExtractorUtils.h>
#include <media/VorbisComment.h>
#include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/base64.h> #include <media/stagefright/foundation/base64.h>
@ -34,6 +33,7 @@
#include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaErrors.h> #include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaDataBase.h> #include <media/stagefright/MetaDataBase.h>
#include <media/stagefright/MetaDataUtils.h>
#include <utils/String8.h> #include <utils/String8.h>
extern "C" { extern "C" {
@ -47,15 +47,15 @@ extern "C" {
namespace android { namespace android {
struct OggSource : public MediaTrackHelper { struct OggSource : public MediaTrackHelperV2 {
explicit OggSource(OggExtractor *extractor); explicit OggSource(OggExtractor *extractor);
virtual status_t getFormat(MetaDataBase &); virtual media_status_t getFormat(AMediaFormat *);
virtual status_t start(); virtual media_status_t start();
virtual status_t stop(); virtual media_status_t stop();
virtual status_t read( virtual media_status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL); MediaBufferBase **buffer, const ReadOptions *options = NULL);
protected: protected:
@ -77,7 +77,7 @@ struct MyOggExtractor {
int64_t seekPreRollUs); int64_t seekPreRollUs);
virtual ~MyOggExtractor(); virtual ~MyOggExtractor();
status_t getFormat(MetaDataBase &) const; media_status_t getFormat(AMediaFormat *) const;
// Returns an approximate bitrate in bits per second. // Returns an approximate bitrate in bits per second.
virtual uint64_t approxBitrate() const = 0; virtual uint64_t approxBitrate() const = 0;
@ -88,9 +88,8 @@ struct MyOggExtractor {
status_t init(); status_t init();
status_t getFileMetaData(MetaDataBase &meta) { media_status_t getFileMetaData(AMediaFormat *meta) {
meta = mFileMeta; return AMediaFormat_copy(meta, mFileMeta);
return OK;
} }
protected: protected:
@ -129,8 +128,8 @@ protected:
vorbis_info mVi; vorbis_info mVi;
vorbis_comment mVc; vorbis_comment mVc;
MetaDataBase mMeta; AMediaFormat *mMeta;
MetaDataBase mFileMeta; AMediaFormat *mFileMeta;
Vector<TOCEntry> mTableOfContents; Vector<TOCEntry> 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); return mExtractor->mImpl->getFormat(meta);
} }
status_t OggSource::start() { media_status_t OggSource::start() {
if (mStarted) { if (mStarted) {
return INVALID_OPERATION; return AMEDIA_ERROR_INVALID_OPERATION;
} }
mStarted = true; mStarted = true;
return OK; return AMEDIA_OK;
} }
status_t OggSource::stop() { media_status_t OggSource::stop() {
mStarted = false; mStarted = false;
return OK; return AMEDIA_OK;
} }
status_t OggSource::read( media_status_t OggSource::read(
MediaBufferBase **out, const ReadOptions *options) { MediaBufferBase **out, const ReadOptions *options) {
*out = NULL; *out = NULL;
@ -266,7 +265,7 @@ status_t OggSource::read(
if (options && options->getSeekTo(&seekTimeUs, &mode)) { if (options && options->getSeekTo(&seekTimeUs, &mode)) {
status_t err = mExtractor->mImpl->seekToTime(seekTimeUs); status_t err = mExtractor->mImpl->seekToTime(seekTimeUs);
if (err != OK) { if (err != OK) {
return err; return AMEDIA_ERROR_UNKNOWN;
} }
} }
@ -274,7 +273,7 @@ status_t OggSource::read(
status_t err = mExtractor->mImpl->readNextPacket(&packet); status_t err = mExtractor->mImpl->readNextPacket(&packet);
if (err != OK) { if (err != OK) {
return err; return AMEDIA_ERROR_UNKNOWN;
} }
#if 0 #if 0
@ -290,7 +289,7 @@ status_t OggSource::read(
*out = packet; *out = packet;
return OK; return AMEDIA_OK;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -316,16 +315,19 @@ MyOggExtractor::MyOggExtractor(
vorbis_info_init(&mVi); vorbis_info_init(&mVi);
vorbis_comment_init(&mVc); vorbis_comment_init(&mVc);
mMeta = AMediaFormat_new();
mFileMeta = AMediaFormat_new();
} }
MyOggExtractor::~MyOggExtractor() { MyOggExtractor::~MyOggExtractor() {
AMediaFormat_delete(mFileMeta);
AMediaFormat_delete(mMeta);
vorbis_comment_clear(&mVc); vorbis_comment_clear(&mVc);
vorbis_info_clear(&mVi); vorbis_info_clear(&mVi);
} }
status_t MyOggExtractor::getFormat(MetaDataBase &meta) const { media_status_t MyOggExtractor::getFormat(AMediaFormat *meta) const {
meta = mMeta; return AMediaFormat_copy(meta, mMeta);
return OK;
} }
status_t MyOggExtractor::findNextPage( status_t MyOggExtractor::findNextPage(
@ -832,7 +834,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT
} }
status_t MyOggExtractor::init() { status_t MyOggExtractor::init() {
mMeta.setCString(kKeyMIMEType, mMimeType); AMediaFormat_setString(mMeta, AMEDIAFORMAT_KEY_MIME, mMimeType);
status_t err; status_t err;
MediaBufferBase *packet; MediaBufferBase *packet;
@ -865,7 +867,7 @@ status_t MyOggExtractor::init() {
int64_t durationUs = getTimeUsOfGranule(lastGranulePosition); int64_t durationUs = getTimeUsOfGranule(lastGranulePosition);
mMeta.setInt64(kKeyDuration, durationUs); AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_DURATION, durationUs);
buildTableOfContents(); buildTableOfContents();
} }
@ -981,11 +983,14 @@ status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) {
mChannelCount = data[9]; mChannelCount = data[9];
mCodecDelay = U16LE_AT(&data[10]); mCodecDelay = U16LE_AT(&data[10]);
mMeta.setData(kKeyOpusHeader, 0, data, size); // kKeyOpusHeader is csd-0
mMeta.setInt32(kKeySampleRate, kOpusSampleRate); AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_0, data, size);
mMeta.setInt32(kKeyChannelCount, mChannelCount); AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, kOpusSampleRate);
mMeta.setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/); AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mChannelCount);
mMeta.setInt64(kKeyOpusCodecDelay /* ns */, // 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); mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate);
return OK; return OK;
@ -1122,10 +1127,10 @@ status_t MyVorbisExtractor::verifyHeader(
return ERROR_MALFORMED; return ERROR_MALFORMED;
} }
mMeta.setData(kKeyVorbisInfo, 0, data, size); AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_0, data, size);
mMeta.setInt32(kKeySampleRate, mVi.rate); AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, mVi.rate);
mMeta.setInt32(kKeyChannelCount, mVi.channels); AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mVi.channels);
mMeta.setInt32(kKeyBitRate, mVi.bitrate_nominal); AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_BIT_RATE, mVi.bitrate_nominal);
ALOGV("lower-bitrate = %ld", mVi.bitrate_lower); ALOGV("lower-bitrate = %ld", mVi.bitrate_lower);
ALOGV("upper-bitrate = %ld", mVi.bitrate_upper); ALOGV("upper-bitrate = %ld", mVi.bitrate_upper);
@ -1140,7 +1145,7 @@ status_t MyVorbisExtractor::verifyHeader(
if (mSource->getSize(&size) == OK) { if (mSource->getSize(&size) == OK) {
uint64_t bps = approxBitrate(); uint64_t bps = approxBitrate();
if (bps != 0) { if (bps != 0) {
mMeta.setInt64(kKeyDuration, size * 8000000ll / bps); AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_DURATION, size * 8000000ll / bps);
} }
} }
break; break;
@ -1162,7 +1167,7 @@ status_t MyVorbisExtractor::verifyHeader(
return ERROR_MALFORMED; return ERROR_MALFORMED;
} }
mMeta.setData(kKeyVorbisBooks, 0, data, size); AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_1, data, size);
break; break;
} }
} }
@ -1180,12 +1185,12 @@ uint64_t MyVorbisExtractor::approxBitrate() const {
void MyOggExtractor::parseFileMetaData() { 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) { for (int i = 0; i < mVc.comments; ++i) {
const char *comment = mVc.user_comments[i]; const char *comment = mVc.user_comments[i];
size_t commentLength = mVc.comment_lengths[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]); //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]);
} }
} }
@ -1227,7 +1232,7 @@ size_t OggExtractor::countTracks() {
return mInitCheck != OK ? 0 : 1; return mInitCheck != OK ? 0 : 1;
} }
MediaTrackHelper *OggExtractor::getTrack(size_t index) { MediaTrackHelperV2 *OggExtractor::getTrack(size_t index) {
if (index >= 1) { if (index >= 1) {
return NULL; return NULL;
} }
@ -1235,27 +1240,27 @@ MediaTrackHelper *OggExtractor::getTrack(size_t index) {
return new OggSource(this); return new OggSource(this);
} }
status_t OggExtractor::getTrackMetaData( media_status_t OggExtractor::getTrackMetaData(
MetaDataBase &meta, AMediaFormat *meta,
size_t index, uint32_t /* flags */) { size_t index, uint32_t /* flags */) {
if (index >= 1) { if (index >= 1) {
return UNKNOWN_ERROR; return AMEDIA_ERROR_UNKNOWN;
} }
return mImpl->getFormat(meta); return mImpl->getFormat(meta);
} }
status_t OggExtractor::getMetaData(MetaDataBase &meta) { media_status_t OggExtractor::getMetaData(AMediaFormat *meta) {
return mImpl->getFileMetaData(meta); return mImpl->getFileMetaData(meta);
} }
static CMediaExtractor* CreateExtractor( static CMediaExtractorV2* CreateExtractor(
CDataSource *source, CDataSource *source,
void *) { void *) {
return wrap(new OggExtractor(new DataSourceHelper(source))); return wrapV2(new OggExtractor(new DataSourceHelper(source)));
} }
static CreatorFunc Sniff( static CreatorFuncV2 Sniff(
CDataSource *source, CDataSource *source,
float *confidence, float *confidence,
void **, void **,
@ -1276,11 +1281,11 @@ extern "C" {
__attribute__ ((visibility ("default"))) __attribute__ ((visibility ("default")))
ExtractorDef GETEXTRACTORDEF() { ExtractorDef GETEXTRACTORDEF() {
return { return {
EXTRACTORDEF_VERSION, EXTRACTORDEF_VERSION_CURRENT,
UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"), UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"),
1, // version 1, // version
"Ogg Extractor", "Ogg Extractor",
{ Sniff } { .v2 = Sniff }
}; };
} }

@ -21,6 +21,7 @@
#include <utils/Errors.h> #include <utils/Errors.h>
#include <media/MediaExtractorPluginApi.h> #include <media/MediaExtractorPluginApi.h>
#include <media/MediaExtractorPluginHelper.h> #include <media/MediaExtractorPluginHelper.h>
#include <media/NdkMediaFormat.h>
namespace android { namespace android {
@ -30,14 +31,14 @@ class String8;
struct MyOggExtractor; struct MyOggExtractor;
struct OggSource; struct OggSource;
struct OggExtractor : public MediaExtractorPluginHelper { struct OggExtractor : public MediaExtractorPluginHelperV2 {
explicit OggExtractor(DataSourceHelper *source); explicit OggExtractor(DataSourceHelper *source);
virtual size_t countTracks(); virtual size_t countTracks();
virtual MediaTrackHelper *getTrack(size_t index); virtual MediaTrackHelperV2 *getTrack(size_t index);
virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags); 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"; } virtual const char * name() { return "OggExtractor"; }
protected: protected:

@ -38,7 +38,6 @@ cc_library {
"MediaSource.cpp", "MediaSource.cpp",
"MetaData.cpp", "MetaData.cpp",
"MetaDataBase.cpp", "MetaDataBase.cpp",
"VorbisComment.cpp",
], ],
clang: true, clang: true,

@ -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 <utils/Log.h>
#include "media/VorbisComment.h"
#include <media/stagefright/foundation/base64.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/foundation/ByteUtils.h>
#include <media/stagefright/MetaDataBase.h>
namespace android {
static void extractAlbumArt(
MetaDataBase *fileMeta, const void *data, size_t size) {
ALOGV("extractAlbumArt from '%s'", (const char *)data);
sp<ABuffer> 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

@ -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_

@ -19,8 +19,10 @@
#include <utils/Log.h> #include <utils/Log.h>
#include <media/stagefright/foundation/avc_utils.h> #include <media/stagefright/foundation/avc_utils.h>
#include <media/stagefright/foundation/base64.h>
#include <media/stagefright/foundation/ABitReader.h> #include <media/stagefright/foundation/ABitReader.h>
#include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ByteUtils.h>
#include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaDataUtils.h> #include <media/stagefright/MetaDataUtils.h>
#include <media/stagefright/Utils.h> #include <media/stagefright/Utils.h>
@ -192,4 +194,135 @@ bool MakeAACCodecSpecificData(
return true; 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 } // namespace android

@ -578,8 +578,10 @@ std::vector<std::pair<const char *, uint32_t>> tagMappings {
{ "cdtracknum", kKeyCDTrackNumber }, { "cdtracknum", kKeyCDTrackNumber },
{ "compilation", kKeyCompilation }, { "compilation", kKeyCompilation },
{ "composer", kKeyComposer }, { "composer", kKeyComposer },
{ "date", kKeyDate },
{ "discnum", kKeyDiscNumber }, { "discnum", kKeyDiscNumber },
{ "genre", kKeyGenre }, { "genre", kKeyGenre },
{ "lyricist", kKeyWriter },
{ "title", kKeyTitle }, { "title", kKeyTitle },
{ "year", kKeyYear }, { "year", kKeyYear },
} }
@ -596,6 +598,11 @@ void convertMessageToMetaDataTags(const sp<AMessage> &msg, sp<MetaData> &meta) {
if (msg->findBuffer("albumart", &buf)) { if (msg->findBuffer("albumart", &buf)) {
meta->setData(kKeyAlbumArt, MetaDataBase::Type::TYPE_NONE, buf->data(), buf->size()); 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<AMessage> format) { void convertMetaDataToMessageTags(const MetaDataBase *meta, sp<AMessage> format) {
@ -612,6 +619,10 @@ void convertMetaDataToMessageTags(const MetaDataBase *meta, sp<AMessage> format)
sp<ABuffer> buf = ABuffer::CreateAsCopy(data, size); sp<ABuffer> buf = ABuffer::CreateAsCopy(data, size);
format->setBuffer("albumart", buf); format->setBuffer("albumart", buf);
} }
int32_t loop;
if (meta->findInt32(kKeyAutoLoop, &loop)) {
format->setInt32("loop", loop);
}
} }
status_t convertMetaDataToMessage( status_t convertMetaDataToMessage(

@ -28,14 +28,31 @@ sp<ABuffer> decodeBase64(const AString &s) {
return NULL; return NULL;
} }
size_t bufSize = n / 4 * 3;
sp<ABuffer> 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; size_t padding = 0;
if (n >= 1 && s.c_str()[n - 1] == '=') { if (n >= 1 && s[n - 1] == '=') {
padding = 1; padding = 1;
if (n >= 2 && s.c_str()[n - 2] == '=') { if (n >= 2 && s[n - 2] == '=') {
padding = 2; padding = 2;
if (n >= 3 && s.c_str()[n - 3] == '=') { if (n >= 3 && s[n - 3] == '=') {
padding = 3; padding = 3;
} }
} }
@ -45,15 +62,13 @@ sp<ABuffer> decodeBase64(const AString &s) {
// already made sure that n % 4 == 0. // already made sure that n % 4 == 0.
size_t outLen = (n / 4) * 3 - padding; size_t outLen = (n / 4) * 3 - padding;
sp<ABuffer> buffer = new ABuffer(outLen); if (out == NULL || *inOutBufSize < outLen) {
uint8_t *out = buffer->data(); return false;
if (out == NULL || buffer->size() < outLen) {
return NULL;
} }
size_t j = 0; size_t j = 0;
uint32_t accum = 0; uint32_t accum = 0;
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
char c = s.c_str()[i]; char c = s[i];
unsigned value; unsigned value;
if (c >= 'A' && c <= 'Z') { if (c >= 'A' && c <= 'Z') {
value = c - 'A'; value = c - 'A';
@ -66,10 +81,10 @@ sp<ABuffer> decodeBase64(const AString &s) {
} else if (c == '/' || c == '_') { } else if (c == '/' || c == '_') {
value = 63; value = 63;
} else if (c != '=') { } else if (c != '=') {
return NULL; return false;
} else { } else {
if (i < n - padding) { if (i < n - padding) {
return NULL; return false;
} }
value = 0; value = 0;
@ -86,7 +101,8 @@ sp<ABuffer> decodeBase64(const AString &s) {
} }
} }
return buffer; *inOutBufSize = j;
return true;
} }
static char encode6Bit(unsigned x) { static char encode6Bit(unsigned x) {

@ -26,6 +26,9 @@ struct ABuffer;
struct AString; struct AString;
sp<ABuffer> decodeBase64(const AString &s); sp<ABuffer> 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 encodeBase64(const void *data, size_t size, AString *out);
void encodeBase64Url(const void *data, size_t size, AString *out); void encodeBase64Url(const void *data, size_t size, AString *out);

@ -34,6 +34,9 @@ bool MakeAACCodecSpecificData(MetaDataBase &meta, unsigned profile, unsigned sam
bool MakeAACCodecSpecificData(AMediaFormat *meta, unsigned profile, unsigned sampling_freq_index, bool MakeAACCodecSpecificData(AMediaFormat *meta, unsigned profile, unsigned sampling_freq_index,
unsigned channel_configuration); unsigned channel_configuration);
void parseVorbisComment(
AMediaFormat *fileMeta, const char *comment, size_t commentLength);
} // namespace android } // namespace android
#endif // META_DATA_UTILS_H_ #endif // META_DATA_UTILS_H_

@ -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_0 = "csd-0";
EXPORT const char* AMEDIAFORMAT_KEY_CSD_1 = "csd-1"; EXPORT const char* AMEDIAFORMAT_KEY_CSD_1 = "csd-1";
EXPORT const char* AMEDIAFORMAT_KEY_CSD_2 = "csd-2"; 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_DISCNUMBER = "discnum";
EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_CROP = "crop"; EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_CROP = "crop";
EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_HEIGHT = "display-height"; 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_LANGUAGE = "language";
EXPORT const char* AMEDIAFORMAT_KEY_LATENCY = "latency"; EXPORT const char* AMEDIAFORMAT_KEY_LATENCY = "latency";
EXPORT const char* AMEDIAFORMAT_KEY_LEVEL = "level"; 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_HEIGHT = "max-height";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE = "max-input-size"; EXPORT const char* AMEDIAFORMAT_KEY_MAX_INPUT_SIZE = "max-input-size";
EXPORT const char* AMEDIAFORMAT_KEY_MAX_WIDTH = "max-width"; EXPORT const char* AMEDIAFORMAT_KEY_MAX_WIDTH = "max-width";

@ -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_CDTRACKNUMBER __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_COMPILATION __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_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_DISCNUMBER __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_ENCODER_DELAY __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_ENCODER_PADDING __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_GENRE __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_TITLE __INTRODUCED_IN(29);
extern const char* AMEDIAFORMAT_KEY_YEAR __INTRODUCED_IN(29); extern const char* AMEDIAFORMAT_KEY_YEAR __INTRODUCED_IN(29);

Loading…
Cancel
Save