Support extractors that use AMediaFormat for metadata

Support secondary plugin API that uses AMediaFormat so plugins can be gradually
changed over to it.

Bug: 111407253
Test: CTS, manual

Change-Id: I25de3cb9463ca3b91370cecd16c80915d6407daf
gugelfrei
Marco Nelissen 6 years ago
parent f441367a5f
commit 56f1938e51

@ -19,6 +19,8 @@
#include <utils/Errors.h> // for status_t
struct AMediaFormat;
namespace android {
struct MediaTrack;
@ -56,7 +58,19 @@ struct CMediaTrack {
bool (*supportsNonBlockingRead)(void *data);
};
struct CMediaExtractor {
struct CMediaTrackV2 {
void *data;
void (*free)(void *data);
status_t (*start)(void *data, AMediaFormat *params);
status_t (*stop)(void *data);
status_t (*getFormat)(void *data, AMediaFormat *format);
status_t (*read)(void *data, MediaBufferBase **buffer, uint32_t options, int64_t seekPosUs);
bool (*supportsNonBlockingRead)(void *data);
};
struct CMediaExtractorV1 {
void *data;
void (*free)(void *data);
@ -73,22 +87,49 @@ struct CMediaExtractor {
const char * (*name)(void *data);
};
typedef CMediaExtractor* (*CreatorFunc)(CDataSource *source, void *meta);
struct CMediaExtractorV2 {
void *data;
void (*free)(void *data);
size_t (*countTracks)(void *data);
CMediaTrackV2* (*getTrack)(void *data, size_t index);
status_t (*getTrackMetaData)(
void *data,
AMediaFormat *meta,
size_t index, uint32_t flags);
status_t (*getMetaData)(void *data, AMediaFormat *meta);
uint32_t (*flags)(void *data);
status_t (*setMediaCas)(void *data, const uint8_t* casToken, size_t size);
const char * (*name)(void *data);
};
typedef CMediaExtractorV1* (*CreatorFuncV1)(CDataSource *source, void *meta);
typedef void (*FreeMetaFunc)(void *meta);
// The sniffer can optionally fill in an opaque object, "meta", that helps
// the corresponding extractor initialize its state without duplicating
// effort already exerted by the sniffer. If "freeMeta" is given, it will be
// called against the opaque object when it is no longer used.
typedef CreatorFunc (*SnifferFunc)(
typedef CreatorFuncV1 (*SnifferFuncV1)(
CDataSource *source, float *confidence,
void **meta, FreeMetaFunc *freeMeta);
typedef CMediaExtractorV2* (*CreatorFuncV2)(CDataSource *source, void *meta);
typedef CreatorFuncV2 (*SnifferFuncV2)(
CDataSource *source, float *confidence,
void **meta, FreeMetaFunc *freeMeta);
typedef CMediaExtractorV1 CMediaExtractor;
typedef CreatorFuncV1 CreatorFunc;
typedef struct {
const uint8_t b[16];
} media_uuid_t;
typedef struct {
struct ExtractorDef {
// version number of this structure
const uint32_t def_version;
@ -104,11 +145,16 @@ typedef struct {
// a human readable name
const char *extractor_name;
// the sniffer function
const SnifferFunc sniff;
} ExtractorDef;
union {
SnifferFuncV1 v1;
SnifferFuncV2 v2;
} sniff;
};
const uint32_t EXTRACTORDEF_VERSION_LEGACY = 1;
const uint32_t EXTRACTORDEF_VERSION_CURRENT = 2;
const uint32_t EXTRACTORDEF_VERSION = 1;
const uint32_t EXTRACTORDEF_VERSION = EXTRACTORDEF_VERSION_LEGACY;
// each plugin library exports one function of this type
typedef ExtractorDef (*GetExtractorDef)();

@ -102,6 +102,77 @@ inline CMediaTrack *wrap(MediaTrackHelper *track) {
return wrapper;
}
class MediaTrackHelperV2 {
public:
virtual ~MediaTrackHelperV2() {};
virtual status_t start(AMediaFormat *params = NULL) = 0;
virtual status_t stop() = 0;
virtual status_t getFormat(AMediaFormat *format) = 0;
class ReadOptions {
public:
enum SeekMode : int32_t {
SEEK_PREVIOUS_SYNC,
SEEK_NEXT_SYNC,
SEEK_CLOSEST_SYNC,
SEEK_CLOSEST,
SEEK_FRAME_INDEX,
};
ReadOptions(uint32_t options, int64_t seekPosUs) {
mOptions = options;
mSeekPosUs = seekPosUs;
}
bool getSeekTo(int64_t *time_us, SeekMode *mode) const {
if ((mOptions & CMediaTrackReadOptions::SEEK) == 0) {
return false;
}
*time_us = mSeekPosUs;
*mode = (SeekMode) (mOptions & 7);
return true;
}
bool getNonBlocking() const {
return mOptions & CMediaTrackReadOptions::NONBLOCKING;
}
private:
uint32_t mOptions;
int64_t mSeekPosUs;
};
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL) = 0;
virtual bool supportsNonBlockingRead() { return false; }
};
inline CMediaTrackV2 *wrapV2(MediaTrackHelperV2 *track) {
CMediaTrackV2 *wrapper = (CMediaTrackV2*) malloc(sizeof(CMediaTrackV2));
wrapper->data = track;
wrapper->free = [](void *data) -> void {
delete (MediaTrackHelperV2*)(data);
};
wrapper->start = [](void *data, AMediaFormat *params) -> status_t {
return ((MediaTrackHelperV2*)data)->start(params);
};
wrapper->stop = [](void *data) -> status_t {
return ((MediaTrackHelperV2*)data)->stop();
};
wrapper->getFormat = [](void *data, AMediaFormat *meta) -> status_t {
return ((MediaTrackHelperV2*)data)->getFormat(meta);
};
wrapper->read = [](void *data, MediaBufferBase **buffer, uint32_t options, int64_t seekPosUs)
-> status_t {
MediaTrackHelperV2::ReadOptions opts(options, seekPosUs);
return ((MediaTrackHelperV2*)data)->read(buffer, &opts);
};
wrapper->supportsNonBlockingRead = [](void *data) -> bool {
return ((MediaTrackHelperV2*)data)->supportsNonBlockingRead();
};
return wrapper;
}
// extractor plugins can derive from this class which looks remarkably
// like MediaExtractor and can be easily wrapped in the required C API
class MediaExtractorPluginHelper
@ -187,6 +258,89 @@ inline CMediaExtractor *wrap(MediaExtractorPluginHelper *extractor) {
return wrapper;
}
class MediaExtractorPluginHelperV2
{
public:
virtual ~MediaExtractorPluginHelperV2() {}
virtual size_t countTracks() = 0;
virtual MediaTrackHelperV2 *getTrack(size_t index) = 0;
enum GetTrackMetaDataFlags {
kIncludeExtensiveMetaData = 1
};
virtual status_t getTrackMetaData(
AMediaFormat *meta,
size_t index, uint32_t flags = 0) = 0;
// Return container specific meta-data. The default implementation
// returns an empty metadata object.
virtual status_t getMetaData(AMediaFormat *meta) = 0;
enum Flags {
CAN_SEEK_BACKWARD = 1, // the "seek 10secs back button"
CAN_SEEK_FORWARD = 2, // the "seek 10secs forward button"
CAN_PAUSE = 4,
CAN_SEEK = 8, // the "seek bar"
};
// If subclasses do _not_ override this, the default is
// CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
virtual uint32_t flags() const {
return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE;
};
virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) {
return INVALID_OPERATION;
}
virtual const char * name() { return "<unspecified>"; }
protected:
MediaExtractorPluginHelperV2() {}
private:
MediaExtractorPluginHelperV2(const MediaExtractorPluginHelperV2 &);
MediaExtractorPluginHelperV2 &operator=(const MediaExtractorPluginHelperV2 &);
};
inline CMediaExtractorV2 *wrapV2(MediaExtractorPluginHelperV2 *extractor) {
CMediaExtractorV2 *wrapper = (CMediaExtractorV2*) malloc(sizeof(CMediaExtractorV2));
wrapper->data = extractor;
wrapper->free = [](void *data) -> void {
delete (MediaExtractorPluginHelperV2*)(data);
};
wrapper->countTracks = [](void *data) -> size_t {
return ((MediaExtractorPluginHelperV2*)data)->countTracks();
};
wrapper->getTrack = [](void *data, size_t index) -> CMediaTrackV2* {
return wrapV2(((MediaExtractorPluginHelperV2*)data)->getTrack(index));
};
wrapper->getTrackMetaData = [](
void *data,
AMediaFormat *meta,
size_t index, uint32_t flags) -> status_t {
return ((MediaExtractorPluginHelperV2*)data)->getTrackMetaData(meta, index, flags);
};
wrapper->getMetaData = [](
void *data,
AMediaFormat *meta) -> status_t {
return ((MediaExtractorPluginHelperV2*)data)->getMetaData(meta);
};
wrapper->flags = [](
void *data) -> uint32_t {
return ((MediaExtractorPluginHelperV2*)data)->flags();
};
wrapper->setMediaCas = [](
void *data, const uint8_t *casToken, size_t size) -> status_t {
return ((MediaExtractorPluginHelperV2*)data)->setMediaCas(casToken, size);
};
wrapper->name = [](
void *data) -> const char * {
return ((MediaExtractorPluginHelperV2*)data)->name();
};
return wrapper;
}
/* adds some convience methods */
class DataSourceHelper {
public:

@ -22,6 +22,7 @@
#include <binder/IMemory.h>
#include <binder/MemoryDealer.h>
#include <media/MediaExtractorPluginApi.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
#include <media/MediaExtractorPluginApi.h>
@ -76,13 +77,23 @@ struct MediaTrack
SEEK_FRAME_INDEX = CMediaTrackReadOptions::SEEK_FRAME_INDEX,
};
ReadOptions();
ReadOptions() {
reset();
}
// Reset everything back to defaults.
void reset();
void reset() {
mOptions = 0;
mSeekTimeUs = 0;
mNonBlocking = false;
}
void setSeekTo(int64_t time_us, SeekMode mode = SEEK_CLOSEST_SYNC);
void clearSeekTo();
void clearSeekTo() {
mOptions &= ~kSeekTo_Option;
mSeekTimeUs = 0;
mSeekMode = SEEK_CLOSEST_SYNC;
}
bool getSeekTo(int64_t *time_us, SeekMode *mode) const;
void setNonBlocking();
@ -146,6 +157,24 @@ private:
CMediaTrack *wrapper;
};
class MediaTrackCUnwrapperV2 : public MediaTrack {
public:
explicit MediaTrackCUnwrapperV2(CMediaTrackV2 *wrapper);
virtual status_t start(MetaDataBase *params = NULL);
virtual status_t stop();
virtual status_t getFormat(MetaDataBase& format);
virtual status_t read(MediaBufferBase **buffer, const ReadOptions *options = NULL);
virtual bool supportNonblockingRead();
protected:
virtual ~MediaTrackCUnwrapperV2();
private:
CMediaTrackV2 *wrapper;
};
} // namespace android
#endif // MEDIA_SOURCE_BASE_H_

@ -393,7 +393,7 @@ ExtractorDef GETEXTRACTORDEF() {
UUID("4fd80eae-03d2-4d72-9eb9-48fa6bb54613"),
1, // version
"AAC Extractor",
Sniff
{ Sniff }
};
}

@ -370,19 +370,21 @@ ExtractorDef GETEXTRACTORDEF() {
UUID("c86639c9-2f31-40ac-a715-fa01b4493aaf"),
1,
"AMR Extractor",
[](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
DataSourceHelper helper(source);
if (SniffAMR(&helper, nullptr, confidence)) {
return [](
CDataSource *source,
void *) -> CMediaExtractor* {
return wrap(new AMRExtractor(new DataSourceHelper(source)));};
{
[](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
DataSourceHelper helper(source);
if (SniffAMR(&helper, nullptr, confidence)) {
return [](
CDataSource *source,
void *) -> CMediaExtractor* {
return wrap(new AMRExtractor(new DataSourceHelper(source)));};
}
return NULL;
}
return NULL;
}
};
}

@ -866,19 +866,21 @@ ExtractorDef GETEXTRACTORDEF() {
UUID("1364b048-cc45-4fda-9934-327d0ebf9829"),
1,
"FLAC Extractor",
[](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
DataSourceHelper helper(source);
if (SniffFLAC(&helper, confidence)) {
return [](
CDataSource *source,
void *) -> CMediaExtractor* {
return wrap(new FLACExtractor(new DataSourceHelper(source)));};
{
[](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
DataSourceHelper helper(source);
if (SniffFLAC(&helper, confidence)) {
return [](
CDataSource *source,
void *) -> CMediaExtractor* {
return wrap(new FLACExtractor(new DataSourceHelper(source)));};
}
return NULL;
}
return NULL;
}
};
}

@ -332,18 +332,20 @@ ExtractorDef GETEXTRACTORDEF() {
UUID("ef6cca0a-f8a2-43e6-ba5f-dfcd7c9a7ef2"),
1,
"MIDI Extractor",
[](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
if (SniffMidi(source, confidence)) {
return [](
CDataSource *source,
void *) -> CMediaExtractor* {
return wrap(new MidiExtractor(source));};
{
[](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
if (SniffMidi(source, confidence)) {
return [](
CDataSource *source,
void *) -> CMediaExtractor* {
return wrap(new MidiExtractor(source));};
}
return NULL;
}
return NULL;
}
};
}

@ -1645,19 +1645,21 @@ ExtractorDef GETEXTRACTORDEF() {
UUID("abbedd92-38c4-4904-a4c1-b3f45f899980"),
1,
"Matroska Extractor",
[](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
DataSourceHelper helper(source);
if (SniffMatroska(&helper, confidence)) {
return [](
CDataSource *source,
void *) -> CMediaExtractor* {
return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
{
[](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
DataSourceHelper helper(source);
if (SniffMatroska(&helper, confidence)) {
return [](
CDataSource *source,
void *) -> CMediaExtractor* {
return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
}
return NULL;
}
return NULL;
}
};
}

@ -718,7 +718,7 @@ ExtractorDef GETEXTRACTORDEF() {
UUID("812a3f6c-c8cf-46de-b529-3774b14103d4"),
1, // version
"MP3 Extractor",
Sniff
{ Sniff }
};
}

@ -5969,7 +5969,7 @@ ExtractorDef GETEXTRACTORDEF() {
UUID("27575c67-4417-4c54-8d3d-8e626985a164"),
1, // version
"MP4 Extractor",
Sniff
{ Sniff }
};
}

@ -35,24 +35,26 @@ ExtractorDef GETEXTRACTORDEF() {
UUID("3d1dcfeb-e40a-436d-a574-c2438a555e5f"),
1,
"MPEG2-PS/TS Extractor",
[](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
DataSourceHelper helper(source);
if (SniffMPEG2TS(&helper, confidence)) {
return [](
CDataSource *source,
void *) -> CMediaExtractor* {
return wrap(new MPEG2TSExtractor(new DataSourceHelper(source)));};
} else if (SniffMPEG2PS(&helper, confidence)) {
return [](
CDataSource *source,
void *) -> CMediaExtractor* {
return wrap(new MPEG2PSExtractor(new DataSourceHelper(source)));};
{
[](
CDataSource *source,
float *confidence,
void **,
FreeMetaFunc *) -> CreatorFunc {
DataSourceHelper helper(source);
if (SniffMPEG2TS(&helper, confidence)) {
return [](
CDataSource *source,
void *) -> CMediaExtractor* {
return wrap(new MPEG2TSExtractor(new DataSourceHelper(source)));};
} else if (SniffMPEG2PS(&helper, confidence)) {
return [](
CDataSource *source,
void *) -> CMediaExtractor* {
return wrap(new MPEG2PSExtractor(new DataSourceHelper(source)));};
}
return NULL;
}
return NULL;
}
};
}

@ -1280,7 +1280,7 @@ ExtractorDef GETEXTRACTORDEF() {
UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"),
1, // version
"Ogg Extractor",
Sniff
{ Sniff }
};
}

@ -9,6 +9,7 @@ cc_library_shared {
shared_libs: [
"liblog",
"libmediaextractor",
"libmediandk",
],
static_libs: [

@ -54,17 +54,17 @@ static uint16_t U16_LE_AT(const uint8_t *ptr) {
return ptr[1] << 8 | ptr[0];
}
struct WAVSource : public MediaTrackHelper {
struct WAVSource : public MediaTrackHelperV2 {
WAVSource(
DataSourceHelper *dataSource,
MetaDataBase &meta,
AMediaFormat *meta,
uint16_t waveFormat,
int32_t bitsPerSample,
off64_t offset, size_t size);
virtual status_t start(MetaDataBase *params = NULL);
virtual status_t start(AMediaFormat *params = NULL);
virtual status_t stop();
virtual status_t getFormat(MetaDataBase &meta);
virtual status_t getFormat(AMediaFormat *meta);
virtual status_t read(
MediaBufferBase **buffer, const ReadOptions *options = NULL);
@ -78,7 +78,7 @@ private:
static const size_t kMaxFrameSize;
DataSourceHelper *mDataSource;
MetaDataBase &mMeta;
AMediaFormat *mMeta;
uint16_t mWaveFormat;
int32_t mSampleRate;
int32_t mNumChannels;
@ -97,17 +97,19 @@ WAVExtractor::WAVExtractor(DataSourceHelper *source)
: mDataSource(source),
mValidFormat(false),
mChannelMask(CHANNEL_MASK_USE_CHANNEL_ORDER) {
mTrackMeta = AMediaFormat_new();
mInitCheck = init();
}
WAVExtractor::~WAVExtractor() {
delete mDataSource;
AMediaFormat_delete(mTrackMeta);
}
status_t WAVExtractor::getMetaData(MetaDataBase &meta) {
meta.clear();
status_t WAVExtractor::getMetaData(AMediaFormat *meta) {
AMediaFormat_clear(meta);
if (mInitCheck == OK) {
meta.setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_WAV);
AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_CONTAINER_WAV);
}
return OK;
@ -117,7 +119,7 @@ size_t WAVExtractor::countTracks() {
return mInitCheck == OK ? 1 : 0;
}
MediaTrackHelper *WAVExtractor::getTrack(size_t index) {
MediaTrackHelperV2 *WAVExtractor::getTrack(size_t index) {
if (mInitCheck != OK || index > 0) {
return NULL;
}
@ -128,13 +130,13 @@ MediaTrackHelper *WAVExtractor::getTrack(size_t index) {
}
status_t WAVExtractor::getTrackMetaData(
MetaDataBase &meta,
AMediaFormat *meta,
size_t index, uint32_t /* flags */) {
if (mInitCheck != OK || index > 0) {
return UNKNOWN_ERROR;
}
meta = mTrackMeta;
AMediaFormat_copy(meta, mTrackMeta);
return OK;
}
@ -284,33 +286,34 @@ status_t WAVExtractor::init() {
mDataOffset = offset;
mDataSize = chunkSize;
mTrackMeta.clear();
AMediaFormat_clear(mTrackMeta);
switch (mWaveFormat) {
case WAVE_FORMAT_PCM:
case WAVE_FORMAT_IEEE_FLOAT:
mTrackMeta.setCString(
kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
AMediaFormat_setString(mTrackMeta,
AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_RAW);
break;
case WAVE_FORMAT_ALAW:
mTrackMeta.setCString(
kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_ALAW);
AMediaFormat_setString(mTrackMeta,
AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_G711_ALAW);
break;
case WAVE_FORMAT_MSGSM:
mTrackMeta.setCString(
kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MSGSM);
AMediaFormat_setString(mTrackMeta,
AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MSGSM);
break;
default:
CHECK_EQ(mWaveFormat, (uint16_t)WAVE_FORMAT_MULAW);
mTrackMeta.setCString(
kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_G711_MLAW);
AMediaFormat_setString(mTrackMeta,
AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_G711_MLAW);
break;
}
mTrackMeta.setInt32(kKeyChannelCount, mNumChannels);
mTrackMeta.setInt32(kKeyChannelMask, mChannelMask);
mTrackMeta.setInt32(kKeySampleRate, mSampleRate);
mTrackMeta.setInt32(kKeyPcmEncoding, kAudioEncodingPcm16bit);
AMediaFormat_setInt32(mTrackMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, mNumChannels);
AMediaFormat_setInt32(mTrackMeta, AMEDIAFORMAT_KEY_CHANNEL_MASK, mChannelMask);
AMediaFormat_setInt32(mTrackMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, mSampleRate);
AMediaFormat_setInt32(mTrackMeta, AMEDIAFORMAT_KEY_PCM_ENCODING,
kAudioEncodingPcm16bit);
int64_t durationUs = 0;
if (mWaveFormat == WAVE_FORMAT_MSGSM) {
@ -332,7 +335,7 @@ status_t WAVExtractor::init() {
1000000LL * num_samples / mSampleRate;
}
mTrackMeta.setInt64(kKeyDuration, durationUs);
AMediaFormat_setInt64(mTrackMeta, AMEDIAFORMAT_KEY_DURATION, durationUs);
return OK;
}
@ -348,7 +351,7 @@ const size_t WAVSource::kMaxFrameSize = 32768;
WAVSource::WAVSource(
DataSourceHelper *dataSource,
MetaDataBase &meta,
AMediaFormat *meta,
uint16_t waveFormat,
int32_t bitsPerSample,
off64_t offset, size_t size)
@ -362,10 +365,10 @@ WAVSource::WAVSource(
mSize(size),
mStarted(false),
mGroup(NULL) {
CHECK(mMeta.findInt32(kKeySampleRate, &mSampleRate));
CHECK(mMeta.findInt32(kKeyChannelCount, &mNumChannels));
CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_SAMPLE_RATE, &mSampleRate));
CHECK(AMediaFormat_getInt32(mMeta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &mNumChannels));
mMeta.setInt32(kKeyMaxInputSize, kMaxFrameSize);
AMediaFormat_setInt32(mMeta, AMEDIAFORMAT_KEY_MAX_INPUT_SIZE, kMaxFrameSize);
}
WAVSource::~WAVSource() {
@ -374,7 +377,7 @@ WAVSource::~WAVSource() {
}
}
status_t WAVSource::start(MetaDataBase * /* params */) {
status_t WAVSource::start(AMediaFormat * /* params */) {
ALOGV("WAVSource::start");
CHECK(!mStarted);
@ -407,10 +410,10 @@ status_t WAVSource::stop() {
return OK;
}
status_t WAVSource::getFormat(MetaDataBase &meta) {
status_t WAVSource::getFormat(AMediaFormat *meta) {
ALOGV("WAVSource::getFormat");
meta = mMeta;
AMediaFormat_copy(meta, mMeta);
return OK;
}
@ -544,13 +547,13 @@ status_t WAVSource::read(
////////////////////////////////////////////////////////////////////////////////
static CMediaExtractor* CreateExtractor(
static CMediaExtractorV2* CreateExtractor(
CDataSource *source,
void *) {
return wrap(new WAVExtractor(new DataSourceHelper(source)));
return wrapV2(new WAVExtractor(new DataSourceHelper(source)));
}
static CreatorFunc Sniff(
static CreatorFuncV2 Sniff(
CDataSource *source,
float *confidence,
void **,
@ -584,11 +587,11 @@ extern "C" {
__attribute__ ((visibility ("default")))
ExtractorDef GETEXTRACTORDEF() {
return {
EXTRACTORDEF_VERSION,
EXTRACTORDEF_VERSION_CURRENT,
UUID("7d613858-5837-4a38-84c5-332d1cddee27"),
1, // version
"WAV Extractor",
Sniff
{ .v2 = Sniff }
};
}

@ -21,7 +21,7 @@
#include <utils/Errors.h>
#include <media/MediaExtractorPluginApi.h>
#include <media/MediaExtractorPluginHelper.h>
#include <media/stagefright/MetaDataBase.h>
#include <media/NdkMediaFormat.h>
namespace android {
@ -29,15 +29,15 @@ struct AMessage;
struct CDataSource;
class String8;
class WAVExtractor : public MediaExtractorPluginHelper {
class WAVExtractor : public MediaExtractorPluginHelperV2 {
public:
explicit WAVExtractor(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 status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
virtual status_t getMetaData(MetaDataBase& meta);
virtual status_t getMetaData(AMediaFormat *meta);
virtual const char * name() { return "WAVExtractor"; }
virtual ~WAVExtractor();
@ -53,7 +53,7 @@ private:
uint16_t mBitsPerSample;
off64_t mDataOffset;
size_t mDataSize;
MetaDataBase mTrackMeta;
AMediaFormat *mTrackMeta;
status_t init();

@ -176,7 +176,6 @@ cc_library {
"IResourceManagerClient.cpp",
"IResourceManagerService.cpp",
"IStreamSource.cpp",
"MediaTrack.cpp",
"MediaUtils.cpp",
"Metadata.cpp",
"mediarecorder.cpp",

@ -124,6 +124,7 @@ cc_library_shared {
"MediaExtractor.cpp",
"MediaExtractorFactory.cpp",
"MediaSync.cpp",
"MediaTrack.cpp",
"http/ClearMediaHTTP.cpp",
"http/MediaHTTP.cpp",
"MediaMuxer.cpp",

@ -22,7 +22,8 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MetaData.h>
#include <media/MediaTrack.h>
#include <media/stagefright/Utils.h>
#include <media/NdkMediaFormatPriv.h>
namespace android {
@ -41,42 +42,95 @@ uint32_t MediaExtractor::flags() const {
}
// --------------------------------------------------------------------------------
MediaExtractorCUnwrapper::MediaExtractorCUnwrapper(CMediaExtractor *wrapper) {
this->wrapper = wrapper;
MediaExtractorCUnwrapperV1::MediaExtractorCUnwrapperV1(CMediaExtractor *plugin) {
this->plugin = plugin;
}
MediaExtractorCUnwrapper::~MediaExtractorCUnwrapper() {
wrapper->free(wrapper->data);
free(wrapper);
MediaExtractorCUnwrapperV1::~MediaExtractorCUnwrapperV1() {
plugin->free(plugin->data);
free(plugin);
}
size_t MediaExtractorCUnwrapper::countTracks() {
return wrapper->countTracks(wrapper->data);
size_t MediaExtractorCUnwrapperV1::countTracks() {
return plugin->countTracks(plugin->data);
}
MediaTrack *MediaExtractorCUnwrapper::getTrack(size_t index) {
return new MediaTrackCUnwrapper(wrapper->getTrack(wrapper->data, index));
MediaTrack *MediaExtractorCUnwrapperV1::getTrack(size_t index) {
return new MediaTrackCUnwrapper(plugin->getTrack(plugin->data, index));
}
status_t MediaExtractorCUnwrapper::getTrackMetaData(
status_t MediaExtractorCUnwrapperV1::getTrackMetaData(
MetaDataBase& meta, size_t index, uint32_t flags) {
return wrapper->getTrackMetaData(wrapper->data, meta, index, flags);
return plugin->getTrackMetaData(plugin->data, meta, index, flags);
}
status_t MediaExtractorCUnwrapper::getMetaData(MetaDataBase& meta) {
return wrapper->getMetaData(wrapper->data, meta);
status_t MediaExtractorCUnwrapperV1::getMetaData(MetaDataBase& meta) {
return plugin->getMetaData(plugin->data, meta);
}
const char * MediaExtractorCUnwrapper::name() {
return wrapper->name(wrapper->data);
const char * MediaExtractorCUnwrapperV1::name() {
return plugin->name(plugin->data);
}
uint32_t MediaExtractorCUnwrapper::flags() const {
return wrapper->flags(wrapper->data);
uint32_t MediaExtractorCUnwrapperV1::flags() const {
return plugin->flags(plugin->data);
}
status_t MediaExtractorCUnwrapper::setMediaCas(const uint8_t* casToken, size_t size) {
return wrapper->setMediaCas(wrapper->data, casToken, size);
status_t MediaExtractorCUnwrapperV1::setMediaCas(const uint8_t* casToken, size_t size) {
return plugin->setMediaCas(plugin->data, casToken, size);
}
// --------------------------------------------------------------------------------
MediaExtractorCUnwrapperV2::MediaExtractorCUnwrapperV2(CMediaExtractorV2 *plugin) {
this->plugin = plugin;
}
MediaExtractorCUnwrapperV2::~MediaExtractorCUnwrapperV2() {
plugin->free(plugin->data);
free(plugin);
}
size_t MediaExtractorCUnwrapperV2::countTracks() {
return plugin->countTracks(plugin->data);
}
MediaTrack *MediaExtractorCUnwrapperV2::getTrack(size_t index) {
return new MediaTrackCUnwrapperV2(plugin->getTrack(plugin->data, index));
}
status_t MediaExtractorCUnwrapperV2::getTrackMetaData(
MetaDataBase& meta, size_t index, uint32_t flags) {
sp<AMessage> msg = new AMessage();
AMediaFormat *format = AMediaFormat_fromMsg(&msg);
status_t ret = plugin->getTrackMetaData(plugin->data, format, index, flags);
sp<MetaData> newMeta = new MetaData();
convertMessageToMetaData(msg, newMeta);
delete format;
meta = *newMeta;
return ret;
}
status_t MediaExtractorCUnwrapperV2::getMetaData(MetaDataBase& meta) {
sp<AMessage> msg = new AMessage();
AMediaFormat *format = AMediaFormat_fromMsg(&msg);
status_t ret = plugin->getMetaData(plugin->data, format);
sp<MetaData> newMeta = new MetaData();
convertMessageToMetaData(msg, newMeta);
delete format;
meta = *newMeta;
return ret;
}
const char * MediaExtractorCUnwrapperV2::name() {
return plugin->name(plugin->data);
}
uint32_t MediaExtractorCUnwrapperV2::flags() const {
return plugin->flags(plugin->data);
}
status_t MediaExtractorCUnwrapperV2::setMediaCas(const uint8_t* casToken, size_t size) {
return plugin->setMediaCas(plugin->data, casToken, size);
}
} // namespace android

@ -74,22 +74,32 @@ sp<IMediaExtractor> MediaExtractorFactory::CreateFromService(
source->DrmInitialization(nullptr /* mime */);
void *meta = nullptr;
CreatorFunc creator = NULL;
void *creator = NULL;
FreeMetaFunc freeMeta = nullptr;
float confidence;
sp<ExtractorPlugin> plugin;
creator = sniff(source, &confidence, &meta, &freeMeta, plugin);
uint32_t creatorVersion = 0;
creator = sniff(source, &confidence, &meta, &freeMeta, plugin, &creatorVersion);
if (!creator) {
ALOGV("FAILED to autodetect media content.");
return NULL;
}
CMediaExtractor *ret = creator(source->wrap(), meta);
if (meta != nullptr && freeMeta != nullptr) {
freeMeta(meta);
MediaExtractor *ex = nullptr;
if (creatorVersion == 1) {
CMediaExtractor *ret = ((CreatorFuncV1)creator)(source->wrap(), meta);
if (meta != nullptr && freeMeta != nullptr) {
freeMeta(meta);
}
ex = ret != nullptr ? new MediaExtractorCUnwrapperV1(ret) : nullptr;
} else if (creatorVersion == 2) {
CMediaExtractorV2 *ret = ((CreatorFuncV2)creator)(source->wrap(), meta);
if (meta != nullptr && freeMeta != nullptr) {
freeMeta(meta);
}
ex = ret != nullptr ? new MediaExtractorCUnwrapperV2(ret) : nullptr;
}
MediaExtractor *ex = ret != nullptr ? new MediaExtractorCUnwrapper(ret) : nullptr;
ALOGV("Created an extractor '%s' with confidence %.2f",
ex != nullptr ? ex->name() : "<null>", confidence);
@ -129,9 +139,9 @@ bool MediaExtractorFactory::gPluginsRegistered = false;
bool MediaExtractorFactory::gIgnoreVersion = false;
// static
CreatorFunc MediaExtractorFactory::sniff(
void *MediaExtractorFactory::sniff(
const sp<DataSource> &source, float *confidence, void **meta,
FreeMetaFunc *freeMeta, sp<ExtractorPlugin> &plugin) {
FreeMetaFunc *freeMeta, sp<ExtractorPlugin> &plugin, uint32_t *creatorVersion) {
*confidence = 0.0f;
*meta = nullptr;
@ -144,15 +154,23 @@ CreatorFunc MediaExtractorFactory::sniff(
plugins = gPlugins;
}
CreatorFunc curCreator = NULL;
CreatorFunc bestCreator = NULL;
void *bestCreator = NULL;
for (auto it = plugins->begin(); it != plugins->end(); ++it) {
ALOGV("sniffing %s", (*it)->def.extractor_name);
float newConfidence;
void *newMeta = nullptr;
FreeMetaFunc newFreeMeta = nullptr;
if ((curCreator = (*it)->def.sniff(
source->wrap(), &newConfidence, &newMeta, &newFreeMeta))) {
void *curCreator = NULL;
if ((*it)->def.def_version == 1) {
curCreator = (void*) (*it)->def.sniff.v1(
source->wrap(), &newConfidence, &newMeta, &newFreeMeta);
} else if ((*it)->def.def_version == 2) {
curCreator = (void*) (*it)->def.sniff.v2(
source->wrap(), &newConfidence, &newMeta, &newFreeMeta);
}
if (curCreator) {
if (newConfidence > *confidence) {
*confidence = newConfidence;
if (*meta != nullptr && *freeMeta != nullptr) {
@ -162,6 +180,7 @@ CreatorFunc MediaExtractorFactory::sniff(
*freeMeta = newFreeMeta;
plugin = *it;
bestCreator = curCreator;
*creatorVersion = (*it)->def.def_version;
} else {
if (newMeta != nullptr && newFreeMeta != nullptr) {
newFreeMeta(newMeta);
@ -178,7 +197,7 @@ void MediaExtractorFactory::RegisterExtractor(const sp<ExtractorPlugin> &plugin,
std::list<sp<ExtractorPlugin>> &pluginList) {
// sanity check check struct version, uuid, name
if (plugin->def.def_version == 0
|| plugin->def.def_version > EXTRACTORDEF_VERSION) {
|| plugin->def.def_version > EXTRACTORDEF_VERSION_CURRENT) {
ALOGE("don't understand extractor format %u, ignoring.", plugin->def.def_version);
return;
}
@ -337,8 +356,9 @@ status_t MediaExtractorFactory::dump(int fd, const Vector<String16>&) {
out.append("Available extractors:\n");
if (gPluginsRegistered) {
for (auto it = gPlugins->begin(); it != gPlugins->end(); ++it) {
out.appendFormat(" %25s: uuid(%s), version(%u), path(%s)\n",
out.appendFormat(" %25s: plugin_version(%d), uuid(%s), version(%u), path(%s)\n",
(*it)->def.extractor_name,
(*it)->def.def_version,
(*it)->uuidString.c_str(),
(*it)->def.extractor_version,
(*it)->libPath.c_str());

@ -16,7 +16,12 @@
#include <mutex>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/Utils.h>
#include <media/MediaTrack.h>
#include <media/MediaExtractorPluginApi.h>
#include <media/NdkMediaFormatPriv.h>
namespace android {
@ -26,16 +31,6 @@ MediaTrack::~MediaTrack() {}
////////////////////////////////////////////////////////////////////////////////
MediaTrack::ReadOptions::ReadOptions() {
reset();
}
void MediaTrack::ReadOptions::reset() {
mOptions = 0;
mSeekTimeUs = 0;
mNonBlocking = false;
}
void MediaTrack::ReadOptions::setNonBlocking() {
mNonBlocking = true;
}
@ -54,12 +49,6 @@ void MediaTrack::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
mSeekMode = mode;
}
void MediaTrack::ReadOptions::clearSeekTo() {
mOptions &= ~kSeekTo_Option;
mSeekTimeUs = 0;
mSeekMode = SEEK_CLOSEST_SYNC;
}
bool MediaTrack::ReadOptions::getSeekTo(
int64_t *time_us, SeekMode *mode) const {
*time_us = mSeekTimeUs;
@ -67,6 +56,8 @@ bool MediaTrack::ReadOptions::getSeekTo(
return (mOptions & kSeekTo_Option) != 0;
}
/* -------------- unwrapper v1 --------------- */
MediaTrackCUnwrapper::MediaTrackCUnwrapper(CMediaTrack *cmediatrack) {
wrapper = cmediatrack;
}
@ -111,4 +102,59 @@ bool MediaTrackCUnwrapper::supportNonblockingRead() {
return wrapper->supportsNonBlockingRead(wrapper->data);
}
/* -------------- unwrapper v2 --------------- */
MediaTrackCUnwrapperV2::MediaTrackCUnwrapperV2(CMediaTrackV2 *cmediatrack2) {
wrapper = cmediatrack2;
}
MediaTrackCUnwrapperV2::~MediaTrackCUnwrapperV2() {
}
status_t MediaTrackCUnwrapperV2::start(MetaDataBase *meta) {
sp<AMessage> msg;
convertMetaDataToMessage(meta, &msg);
AMediaFormat *format = AMediaFormat_fromMsg(&msg);
status_t ret = wrapper->start(wrapper->data, format);
delete format;
return ret;
}
status_t MediaTrackCUnwrapperV2::stop() {
return wrapper->stop(wrapper->data);
}
status_t MediaTrackCUnwrapperV2::getFormat(MetaDataBase& format) {
sp<AMessage> msg = new AMessage();
AMediaFormat *tmpFormat = AMediaFormat_fromMsg(&msg);
status_t ret = wrapper->getFormat(wrapper->data, tmpFormat);
sp<MetaData> newMeta = new MetaData();
convertMessageToMetaData(msg, newMeta);
delete tmpFormat;
format = *newMeta;
return ret;
}
status_t MediaTrackCUnwrapperV2::read(MediaBufferBase **buffer, const ReadOptions *options) {
uint32_t opts = 0;
if (options->getNonBlocking()) {
opts |= CMediaTrackReadOptions::NONBLOCKING;
}
int64_t seekPosition = 0;
MediaTrack::ReadOptions::SeekMode seekMode;
if (options->getSeekTo(&seekPosition, &seekMode)) {
opts |= SEEK;
opts |= (uint32_t) seekMode;
}
return wrapper->read(wrapper->data, buffer, opts, seekPosition);
}
bool MediaTrackCUnwrapperV2::supportNonblockingRead() {
return wrapper->supportsNonBlockingRead(wrapper->data);
}
} // namespace android

@ -74,7 +74,7 @@ static void convertMetaDataToMessageInt32(
}
#endif
static void convertMetaDataToMessageColorAspects(const sp<MetaData> &meta, sp<AMessage> &msg) {
static void convertMetaDataToMessageColorAspects(const MetaDataBase *meta, sp<AMessage> &msg) {
// 0 values are unspecified
int32_t range = 0;
int32_t primaries = 0;
@ -568,8 +568,14 @@ static void parseVp9ProfileLevelFromCsd(const sp<ABuffer> &csd, sp<AMessage> &fo
}
}
status_t convertMetaDataToMessage(
const sp<MetaData> &meta, sp<AMessage> *format) {
return convertMetaDataToMessage(meta.get(), format);
}
status_t convertMetaDataToMessage(
const MetaDataBase *meta, sp<AMessage> *format) {
format->clear();

@ -90,7 +90,38 @@ private:
class MediaExtractorCUnwrapper : public MediaExtractor {
public:
explicit MediaExtractorCUnwrapper(CMediaExtractor *wrapper);
MediaExtractorCUnwrapper() {};
virtual size_t countTracks() = 0;
virtual MediaTrack *getTrack(size_t index) = 0;
virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags = 0) = 0;
virtual status_t getMetaData(MetaDataBase& meta) = 0;
virtual const char * name() = 0;
virtual uint32_t flags() const = 0;
virtual status_t setMediaCas(const uint8_t* casToken, size_t size) = 0;
protected:
virtual ~MediaExtractorCUnwrapper() {};
};
class MediaExtractorCUnwrapperV1 : public MediaExtractorCUnwrapper {
public:
explicit MediaExtractorCUnwrapperV1(CMediaExtractor *plugin);
virtual size_t countTracks();
virtual MediaTrack *getTrack(size_t index);
virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags = 0);
virtual status_t getMetaData(MetaDataBase& meta);
virtual const char * name();
virtual uint32_t flags() const;
virtual status_t setMediaCas(const uint8_t* casToken, size_t size);
protected:
virtual ~MediaExtractorCUnwrapperV1();
private:
CMediaExtractor *plugin;
};
class MediaExtractorCUnwrapperV2 : public MediaExtractorCUnwrapper {
public:
explicit MediaExtractorCUnwrapperV2(CMediaExtractorV2 *plugin);
virtual size_t countTracks();
virtual MediaTrack *getTrack(size_t index);
virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags = 0);
@ -99,9 +130,9 @@ public:
virtual uint32_t flags() const;
virtual status_t setMediaCas(const uint8_t* casToken, size_t size);
protected:
virtual ~MediaExtractorCUnwrapper();
virtual ~MediaExtractorCUnwrapperV2();
private:
CMediaExtractor *wrapper;
CMediaExtractorV2 *plugin;
};
} // namespace android

@ -49,9 +49,9 @@ private:
static void RegisterExtractor(
const sp<ExtractorPlugin> &plugin, std::list<sp<ExtractorPlugin>> &pluginList);
static CreatorFunc sniff(const sp<DataSource> &source,
static void *sniff(const sp<DataSource> &source,
float *confidence, void **meta, FreeMetaFunc *freeMeta,
sp<ExtractorPlugin> &plugin);
sp<ExtractorPlugin> &plugin, uint32_t *creatorVersion);
static void UpdateExtractors(const char *newUpdateApkPath);
};

@ -29,6 +29,8 @@
namespace android {
struct AMessage;
status_t convertMetaDataToMessage(
const MetaDataBase *meta, sp<AMessage> *format);
status_t convertMetaDataToMessage(
const sp<MetaData> &meta, sp<AMessage> *format);
void convertMessageToMetaData(

@ -35,23 +35,6 @@ using namespace android;
extern "C" {
// private functions for conversion to/from AMessage
AMediaFormat* AMediaFormat_fromMsg(const void* data) {
ALOGV("private ctor");
AMediaFormat* mData = new AMediaFormat();
mData->mFormat = *((sp<AMessage>*)data);
if (mData->mFormat == NULL) {
ALOGW("got NULL format");
mData->mFormat = new AMessage;
}
return mData;
}
void AMediaFormat_getFormat(const AMediaFormat* mData, void* dest) {
*((sp<AMessage>*)dest) = mData->mFormat;
}
/*
* public function follow
*/

Loading…
Cancel
Save