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_