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
diff --git a/include/media/MediaExtractorPluginApi.h b/include/media/MediaExtractorPluginApi.h
index cccfc91..9caea3e 100644
--- a/include/media/MediaExtractorPluginApi.h
+++ b/include/media/MediaExtractorPluginApi.h
@@ -19,6 +19,8 @@
 
 #include <utils/Errors.h> // for status_t
 
+struct AMediaFormat;
+
 namespace android {
 
 struct MediaTrack;
@@ -56,7 +58,19 @@
     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 @@
     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 @@
     // 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 = 1;
+const uint32_t EXTRACTORDEF_VERSION_LEGACY = 1;
+const uint32_t EXTRACTORDEF_VERSION_CURRENT = 2;
+
+const uint32_t EXTRACTORDEF_VERSION = EXTRACTORDEF_VERSION_LEGACY;
 
 // each plugin library exports one function of this type
 typedef ExtractorDef (*GetExtractorDef)();
diff --git a/include/media/MediaExtractorPluginHelper.h b/include/media/MediaExtractorPluginHelper.h
index 961033b..2acc2bf 100644
--- a/include/media/MediaExtractorPluginHelper.h
+++ b/include/media/MediaExtractorPluginHelper.h
@@ -102,6 +102,77 @@
     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 @@
     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:
diff --git a/include/media/MediaTrack.h b/include/media/MediaTrack.h
index 3f77bda..174f4cc 100644
--- a/include/media/MediaTrack.h
+++ b/include/media/MediaTrack.h
@@ -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 @@
             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 @@
     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_
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index 9effd57..b52aec5 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -393,7 +393,7 @@
         UUID("4fd80eae-03d2-4d72-9eb9-48fa6bb54613"),
         1, // version
         "AAC Extractor",
-        Sniff
+        { Sniff }
     };
 }
 
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index 6648103..8039f3a 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -370,19 +370,21 @@
         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;
         }
     };
 }
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index c10a557..debdcfc 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -866,19 +866,21 @@
             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;
             }
      };
 }
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index 5b61f34..ea56734 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -332,18 +332,20 @@
         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;
         }
     };
 }
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index 4ef6892..73c8d17 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -1645,19 +1645,21 @@
         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;
         }
     };
 }
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 165ce50..e56a71b 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -718,7 +718,7 @@
         UUID("812a3f6c-c8cf-46de-b529-3774b14103d4"),
         1, // version
         "MP3 Extractor",
-        Sniff
+        { Sniff }
     };
 }
 
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index da240d6..e3da6d8 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -5969,7 +5969,7 @@
         UUID("27575c67-4417-4c54-8d3d-8e626985a164"),
         1, // version
         "MP4 Extractor",
-        Sniff
+        { Sniff }
     };
 }
 
diff --git a/media/extractors/mpeg2/ExtractorBundle.cpp b/media/extractors/mpeg2/ExtractorBundle.cpp
index 88c2d87..366aa59 100644
--- a/media/extractors/mpeg2/ExtractorBundle.cpp
+++ b/media/extractors/mpeg2/ExtractorBundle.cpp
@@ -35,24 +35,26 @@
         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;
         }
     };
 }
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index 668b012..dc6b0b7 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -1280,7 +1280,7 @@
         UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"),
         1, // version
         "Ogg Extractor",
-        Sniff
+        { Sniff }
     };
 }
 
diff --git a/media/extractors/wav/Android.bp b/media/extractors/wav/Android.bp
index 067933e..d8b4144 100644
--- a/media/extractors/wav/Android.bp
+++ b/media/extractors/wav/Android.bp
@@ -9,6 +9,7 @@
     shared_libs: [
         "liblog",
         "libmediaextractor",
+        "libmediandk",
     ],
 
     static_libs: [
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index cda568b..1b7c2e4 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -54,17 +54,17 @@
     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 @@
     static const size_t kMaxFrameSize;
 
     DataSourceHelper *mDataSource;
-    MetaDataBase &mMeta;
+    AMediaFormat *mMeta;
     uint16_t mWaveFormat;
     int32_t mSampleRate;
     int32_t mNumChannels;
@@ -97,17 +97,19 @@
     : 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 @@
     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 @@
 }
 
 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 @@
                 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 @@
                         1000000LL * num_samples / mSampleRate;
                 }
 
-                mTrackMeta.setInt64(kKeyDuration, durationUs);
+                AMediaFormat_setInt64(mTrackMeta, AMEDIAFORMAT_KEY_DURATION, durationUs);
 
                 return OK;
             }
@@ -348,7 +351,7 @@
 
 WAVSource::WAVSource(
         DataSourceHelper *dataSource,
-        MetaDataBase &meta,
+        AMediaFormat *meta,
         uint16_t waveFormat,
         int32_t bitsPerSample,
         off64_t offset, size_t size)
@@ -362,10 +365,10 @@
       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 @@
     }
 }
 
-status_t WAVSource::start(MetaDataBase * /* params */) {
+status_t WAVSource::start(AMediaFormat * /* params */) {
     ALOGV("WAVSource::start");
 
     CHECK(!mStarted);
@@ -407,10 +410,10 @@
     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 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-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 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION_CURRENT,
         UUID("7d613858-5837-4a38-84c5-332d1cddee27"),
         1, // version
         "WAV Extractor",
-        Sniff
+        { .v2 = Sniff }
     };
 }
 
diff --git a/media/extractors/wav/WAVExtractor.h b/media/extractors/wav/WAVExtractor.h
index a7c2691..2822e80 100644
--- a/media/extractors/wav/WAVExtractor.h
+++ b/media/extractors/wav/WAVExtractor.h
@@ -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 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 @@
     uint16_t mBitsPerSample;
     off64_t mDataOffset;
     size_t mDataSize;
-    MetaDataBase mTrackMeta;
+    AMediaFormat *mTrackMeta;
 
     status_t init();
 
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 2389a5d..bb87b10 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -176,7 +176,6 @@
         "IResourceManagerClient.cpp",
         "IResourceManagerService.cpp",
         "IStreamSource.cpp",
-        "MediaTrack.cpp",
         "MediaUtils.cpp",
         "Metadata.cpp",
         "mediarecorder.cpp",
diff --git a/media/libmedia/MediaTrack.cpp b/media/libmedia/MediaTrack.cpp
deleted file mode 100644
index 7117b94..0000000
--- a/media/libmedia/MediaTrack.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#include <mutex>
-
-#include <media/MediaTrack.h>
-
-namespace android {
-
-MediaTrack::MediaTrack() {}
-
-MediaTrack::~MediaTrack() {}
-
-////////////////////////////////////////////////////////////////////////////////
-
-MediaTrack::ReadOptions::ReadOptions() {
-    reset();
-}
-
-void MediaTrack::ReadOptions::reset() {
-    mOptions = 0;
-    mSeekTimeUs = 0;
-    mNonBlocking = false;
-}
-
-void MediaTrack::ReadOptions::setNonBlocking() {
-    mNonBlocking = true;
-}
-
-void MediaTrack::ReadOptions::clearNonBlocking() {
-    mNonBlocking = false;
-}
-
-bool MediaTrack::ReadOptions::getNonBlocking() const {
-    return mNonBlocking;
-}
-
-void MediaTrack::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
-    mOptions |= kSeekTo_Option;
-    mSeekTimeUs = time_us;
-    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;
-    *mode = mSeekMode;
-    return (mOptions & kSeekTo_Option) != 0;
-}
-
-MediaTrackCUnwrapper::MediaTrackCUnwrapper(CMediaTrack *cmediatrack) {
-    wrapper = cmediatrack;
-}
-
-MediaTrackCUnwrapper::~MediaTrackCUnwrapper() {
-    wrapper->free(wrapper->data);
-    free(wrapper);
-}
-
-status_t MediaTrackCUnwrapper::start(MetaDataBase *params) {
-    return wrapper->start(wrapper->data, params);
-}
-
-status_t MediaTrackCUnwrapper::stop() {
-    return wrapper->stop(wrapper->data);
-}
-
-status_t MediaTrackCUnwrapper::getFormat(MetaDataBase& format) {
-    return wrapper->getFormat(wrapper->data, format);
-}
-
-status_t MediaTrackCUnwrapper::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 MediaTrackCUnwrapper::supportNonblockingRead() {
-    return wrapper->supportsNonBlockingRead(wrapper->data);
-}
-
-}  // namespace android
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 4127818..90a7eb5 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -124,6 +124,7 @@
         "MediaExtractor.cpp",
         "MediaExtractorFactory.cpp",
         "MediaSync.cpp",
+        "MediaTrack.cpp",
         "http/ClearMediaHTTP.cpp",
         "http/MediaHTTP.cpp",
         "MediaMuxer.cpp",
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 6710121..e00c3c8 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.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 @@
 }
 
 // --------------------------------------------------------------------------------
-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
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index f1c6acd..8f1dd36 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -74,22 +74,32 @@
     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::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 @@
         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 @@
                 *freeMeta = newFreeMeta;
                 plugin = *it;
                 bestCreator = curCreator;
+                *creatorVersion = (*it)->def.def_version;
             } else {
                 if (newMeta != nullptr && newFreeMeta != nullptr) {
                     newFreeMeta(newMeta);
@@ -178,7 +197,7 @@
         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 @@
     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());
diff --git a/media/libstagefright/MediaTrack.cpp b/media/libstagefright/MediaTrack.cpp
new file mode 100644
index 0000000..792b317
--- /dev/null
+++ b/media/libstagefright/MediaTrack.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+#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 {
+
+MediaTrack::MediaTrack() {}
+
+MediaTrack::~MediaTrack() {}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void MediaTrack::ReadOptions::setNonBlocking() {
+    mNonBlocking = true;
+}
+
+void MediaTrack::ReadOptions::clearNonBlocking() {
+    mNonBlocking = false;
+}
+
+bool MediaTrack::ReadOptions::getNonBlocking() const {
+    return mNonBlocking;
+}
+
+void MediaTrack::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
+    mOptions |= kSeekTo_Option;
+    mSeekTimeUs = time_us;
+    mSeekMode = mode;
+}
+
+bool MediaTrack::ReadOptions::getSeekTo(
+        int64_t *time_us, SeekMode *mode) const {
+    *time_us = mSeekTimeUs;
+    *mode = mSeekMode;
+    return (mOptions & kSeekTo_Option) != 0;
+}
+
+/* -------------- unwrapper v1 --------------- */
+
+MediaTrackCUnwrapper::MediaTrackCUnwrapper(CMediaTrack *cmediatrack) {
+    wrapper = cmediatrack;
+}
+
+MediaTrackCUnwrapper::~MediaTrackCUnwrapper() {
+    wrapper->free(wrapper->data);
+    free(wrapper);
+}
+
+status_t MediaTrackCUnwrapper::start(MetaDataBase *params) {
+    return wrapper->start(wrapper->data, params);
+}
+
+status_t MediaTrackCUnwrapper::stop() {
+    return wrapper->stop(wrapper->data);
+}
+
+status_t MediaTrackCUnwrapper::getFormat(MetaDataBase& format) {
+    return wrapper->getFormat(wrapper->data, format);
+}
+
+status_t MediaTrackCUnwrapper::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 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
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index ada37a6..ebc3b33 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -74,7 +74,7 @@
 }
 #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 @@
     }
 }
 
+
 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();
 
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractor.h b/media/libstagefright/include/media/stagefright/MediaExtractor.h
index 3e5c905..71343d5 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractor.h
@@ -90,7 +90,22 @@
 
 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);
@@ -99,9 +114,25 @@
     virtual uint32_t flags() const;
     virtual status_t setMediaCas(const uint8_t* casToken, size_t size);
 protected:
-    virtual ~MediaExtractorCUnwrapper();
+    virtual ~MediaExtractorCUnwrapperV1();
 private:
-    CMediaExtractor *wrapper;
+    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);
+    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 ~MediaExtractorCUnwrapperV2();
+private:
+    CMediaExtractorV2 *plugin;
 };
 
 }  // namespace android
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index e603176..ef9f7ed 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -49,9 +49,9 @@
     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);
 };
diff --git a/media/libstagefright/include/media/stagefright/Utils.h b/media/libstagefright/include/media/stagefright/Utils.h
index 6a28e0b..46a419d 100644
--- a/media/libstagefright/include/media/stagefright/Utils.h
+++ b/media/libstagefright/include/media/stagefright/Utils.h
@@ -30,6 +30,8 @@
 
 struct AMessage;
 status_t convertMetaDataToMessage(
+        const MetaDataBase *meta, sp<AMessage> *format);
+status_t convertMetaDataToMessage(
         const sp<MetaData> &meta, sp<AMessage> *format);
 void convertMessageToMetaData(
         const sp<AMessage> &format, sp<MetaData> &meta);
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index a66f3b3..249c76e 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -35,23 +35,6 @@
 
 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
  */