Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56f1938e authored by Marco Nelissen's avatar Marco Nelissen
Browse files

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
parent f441367a
Loading
Loading
Loading
Loading
+54 −8
Original line number Diff line number Diff line
@@ -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)();
+154 −0
Original line number Diff line number Diff line
@@ -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:
+32 −3
Original line number Diff line number Diff line
@@ -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_
+1 −1
Original line number Diff line number Diff line
@@ -393,7 +393,7 @@ ExtractorDef GETEXTRACTORDEF() {
        UUID("4fd80eae-03d2-4d72-9eb9-48fa6bb54613"),
        1, // version
        "AAC Extractor",
        Sniff
        { Sniff }
    };
}

+14 −12
Original line number Diff line number Diff line
@@ -370,6 +370,7 @@ ExtractorDef GETEXTRACTORDEF() {
        UUID("c86639c9-2f31-40ac-a715-fa01b4493aaf"),
        1,
        "AMR Extractor",
        {
           [](
                    CDataSource *source,
                    float *confidence,
@@ -384,6 +385,7 @@ ExtractorDef GETEXTRACTORDEF() {
                }
                return NULL;
            }
        }
    };
}

Loading