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

Commit b9dfc06a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I1c8b2990,Iba947381

* changes:
  C-ify DataSource
  C API for extractor plugins
parents be7f1796 cec44d0c
Loading
Loading
Loading
Loading
+98 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MEDIA_EXTRACTOR_PLUGIN_API_H_
#define MEDIA_EXTRACTOR_PLUGIN_API_H_

#include <utils/Errors.h> // for status_t

namespace android {

struct MediaTrack;
class MetaDataBase;

extern "C" {

struct CDataSource {
    ssize_t (*readAt)(void *handle, off64_t offset, void *data, size_t size);
    status_t (*getSize)(void *handle, off64_t *size);
    uint32_t (*flags)(void *handle );
    bool (*getUri)(void *handle, char *uriString, size_t bufferSize);
    void *handle;
};

struct CMediaExtractor {
    void *data;

    void (*free)(void *data);
    size_t (*countTracks)(void *data);
    MediaTrack* (*getTrack)(void *data, size_t index);
    status_t (*getTrackMetaData)(
            void *data,
            MetaDataBase& meta,
            size_t index, uint32_t flags);

    status_t (*getMetaData)(void *data, MetaDataBase& meta);
    uint32_t (*flags)(void *data);
    status_t (*setMediaCas)(void *data, const uint8_t* casToken, size_t size);
    const char * (*name)(void *data);
};

typedef CMediaExtractor* (*CreatorFunc)(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)(
        CDataSource *source, float *confidence,
        void **meta, FreeMetaFunc *freeMeta);

typedef struct {
    const uint8_t b[16];
} media_uuid_t;

typedef struct {
    // version number of this structure
    const uint32_t def_version;

    // A unique identifier for this extractor.
    // See below for a convenience macro to create this from a string.
    media_uuid_t extractor_uuid;

    // Version number of this extractor. When two extractors with the same
    // uuid are encountered, the one with the largest version number will
    // be used.
    const uint32_t extractor_version;

    // a human readable name
    const char *extractor_name;

    // the sniffer function
    const SnifferFunc sniff;
} ExtractorDef;

const uint32_t EXTRACTORDEF_VERSION = 1;

// each plugin library exports one function of this type
typedef ExtractorDef (*GetExtractorDef)();

} // extern "C"

}  // namespace android

#endif  // MEDIA_EXTRACTOR_PLUGIN_API_H_
+315 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MEDIA_EXTRACTOR_PLUGIN_HELPER_H_

#define MEDIA_EXTRACTOR_PLUGIN_HELPER_H_

#include <arpa/inet.h>
#include <stdio.h>
#include <vector>

#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/RefBase.h>
#include <media/MediaExtractorPluginApi.h>

namespace android {

class DataSourceBase;
class MetaDataBase;
struct MediaTrack;

// extractor plugins can derive from this class which looks remarkably
// like MediaExtractor and can be easily wrapped in the required C API
class MediaExtractorPluginHelper
{
public:
    virtual ~MediaExtractorPluginHelper() {}
    virtual size_t countTracks() = 0;
    virtual MediaTrack *getTrack(size_t index) = 0;

    enum GetTrackMetaDataFlags {
        kIncludeExtensiveMetaData = 1
    };
    virtual status_t getTrackMetaData(
            MetaDataBase& 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(MetaDataBase& 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:
    MediaExtractorPluginHelper() {}

private:
    MediaExtractorPluginHelper(const MediaExtractorPluginHelper &);
    MediaExtractorPluginHelper &operator=(const MediaExtractorPluginHelper &);
};

inline CMediaExtractor *wrap(MediaExtractorPluginHelper *extractor) {
    CMediaExtractor *wrapper = (CMediaExtractor*) malloc(sizeof(CMediaExtractor));
    wrapper->data = extractor;
    wrapper->free = [](void *data) -> void {
        delete (MediaExtractorPluginHelper*)(data);
    };
    wrapper->countTracks = [](void *data) -> size_t {
        return ((MediaExtractorPluginHelper*)data)->countTracks();
    };
    wrapper->getTrack = [](void *data, size_t index) -> MediaTrack* {
        return ((MediaExtractorPluginHelper*)data)->getTrack(index);
    };
    wrapper->getTrackMetaData = [](
            void *data,
            MetaDataBase& meta,
            size_t index, uint32_t flags) -> status_t {
        return ((MediaExtractorPluginHelper*)data)->getTrackMetaData(meta, index, flags);
    };
    wrapper->getMetaData = [](
            void *data,
            MetaDataBase& meta) -> status_t {
        return ((MediaExtractorPluginHelper*)data)->getMetaData(meta);
    };
    wrapper->flags = [](
            void *data) -> uint32_t {
        return ((MediaExtractorPluginHelper*)data)->flags();
    };
    wrapper->setMediaCas = [](
            void *data, const uint8_t *casToken, size_t size) -> status_t {
        return ((MediaExtractorPluginHelper*)data)->setMediaCas(casToken, size);
    };
    wrapper->name = [](
            void *data) -> const char * {
        return ((MediaExtractorPluginHelper*)data)->name();
    };
    return wrapper;
}

/* adds some convience methods */
class DataSourceHelper {
public:
    explicit DataSourceHelper(CDataSource *csource) {
        mSource = csource;
    }

    explicit DataSourceHelper(DataSourceHelper *source) {
        mSource = source->mSource;
    }

    ssize_t readAt(off64_t offset, void *data, size_t size) {
        return mSource->readAt(mSource->handle, offset, data, size);
    }

    status_t getSize(off64_t *size) {
        return mSource->getSize(mSource->handle, size);
    }

    bool getUri(char *uriString, size_t bufferSize) {
        return mSource->getUri(mSource->handle, uriString, bufferSize);
    }

    uint32_t flags() {
        return mSource->flags(mSource->handle);
    }

    // Convenience methods:
    bool getUInt16(off64_t offset, uint16_t *x) {
        *x = 0;

        uint8_t byte[2];
        if (readAt(offset, byte, 2) != 2) {
            return false;
        }

        *x = (byte[0] << 8) | byte[1];

        return true;
    }

    // 3 byte int, returned as a 32-bit int
    bool getUInt24(off64_t offset, uint32_t *x) {
        *x = 0;

        uint8_t byte[3];
        if (readAt(offset, byte, 3) != 3) {
            return false;
        }

        *x = (byte[0] << 16) | (byte[1] << 8) | byte[2];

        return true;
    }

    bool getUInt32(off64_t offset, uint32_t *x) {
        *x = 0;

        uint32_t tmp;
        if (readAt(offset, &tmp, 4) != 4) {
            return false;
        }

        *x = ntohl(tmp);

        return true;
    }

    bool getUInt64(off64_t offset, uint64_t *x) {
        *x = 0;

        uint64_t tmp;
        if (readAt(offset, &tmp, 8) != 8) {
            return false;
        }

        *x = ((uint64_t)ntohl(tmp & 0xffffffff) << 32) | ntohl(tmp >> 32);

        return true;
    }

    // read either int<N> or int<2N> into a uint<2N>_t, size is the int size in bytes.
    bool getUInt16Var(off64_t offset, uint16_t *x, size_t size) {
        if (size == 2) {
            return getUInt16(offset, x);
        }
        if (size == 1) {
            uint8_t tmp;
            if (readAt(offset, &tmp, 1) == 1) {
                *x = tmp;
                return true;
            }
        }
        return false;
    }

    bool getUInt32Var(off64_t offset, uint32_t *x, size_t size) {
        if (size == 4) {
            return getUInt32(offset, x);
        }
        if (size == 2) {
            uint16_t tmp;
            if (getUInt16(offset, &tmp)) {
                *x = tmp;
                return true;
            }
        }
        return false;
    }

    bool getUInt64Var(off64_t offset, uint64_t *x, size_t size) {
        if (size == 8) {
            return getUInt64(offset, x);
        }
        if (size == 4) {
            uint32_t tmp;
            if (getUInt32(offset, &tmp)) {
                *x = tmp;
                return true;
            }
        }
        return false;
    }

protected:
    CDataSource *mSource;
};



// helpers to create a media_uuid_t from a string literal

// purposely not defined anywhere so that this will fail to link if
// expressions below are not evaluated at compile time
int invalid_uuid_string(const char *);

template <typename T, size_t N>
constexpr uint8_t _digitAt_(const T (&s)[N], const size_t n) {
    return s[n] >= '0' && s[n] <= '9' ? s[n] - '0'
            : s[n] >= 'a' && s[n] <= 'f' ? s[n] - 'a' + 10
                    : s[n] >= 'A' && s[n] <= 'F' ? s[n] - 'A' + 10
                            : invalid_uuid_string("uuid: bad digits");
}

template <typename T, size_t N>
constexpr uint8_t _hexByteAt_(const T (&s)[N], size_t n) {
    return (_digitAt_(s, n) << 4) + _digitAt_(s, n + 1);
}

constexpr bool _assertIsDash_(char c) {
    return c == '-' ? true : invalid_uuid_string("Wrong format");
}

template <size_t N>
constexpr media_uuid_t constUUID(const char (&s) [N]) {
    static_assert(N == 37, "uuid: wrong length");
    return
            _assertIsDash_(s[8]),
            _assertIsDash_(s[13]),
            _assertIsDash_(s[18]),
            _assertIsDash_(s[23]),
            media_uuid_t {{
                _hexByteAt_(s, 0),
                _hexByteAt_(s, 2),
                _hexByteAt_(s, 4),
                _hexByteAt_(s, 6),
                _hexByteAt_(s, 9),
                _hexByteAt_(s, 11),
                _hexByteAt_(s, 14),
                _hexByteAt_(s, 16),
                _hexByteAt_(s, 19),
                _hexByteAt_(s, 21),
                _hexByteAt_(s, 24),
                _hexByteAt_(s, 26),
                _hexByteAt_(s, 28),
                _hexByteAt_(s, 30),
                _hexByteAt_(s, 32),
                _hexByteAt_(s, 34),
            }};
}
// Convenience macro to create a media_uuid_t from a string literal, which should
// be formatted as "12345678-1234-1234-1234-123456789abc", as generated by
// e.g. https://www.uuidgenerator.net/ or the 'uuidgen' linux command.
// Hex digits may be upper or lower case.
//
// The macro call is otherwise equivalent to specifying the structure directly
// (e.g. UUID("7d613858-5837-4a38-84c5-332d1cddee27") is the same as
//       {{0x7d, 0x61, 0x38, 0x58, 0x58, 0x37, 0x4a, 0x38,
//         0x84, 0xc5, 0x33, 0x2d, 0x1c, 0xdd, 0xee, 0x27}})

#define UUID(str) []{ constexpr media_uuid_t uuid = constUUID(str); return uuid; }()

}  // namespace android

#endif  // MEDIA_EXTRACTOR_PLUGIN_HELPER_H_
+17 −16
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@
#include <utils/Log.h>

#include "AACExtractor.h"
#include <media/DataSourceBase.h>
#include <media/MediaExtractorPluginApi.h>
#include <media/MediaTrack.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -36,7 +36,7 @@ namespace android {
class AACSource : public MediaTrack {
public:
    AACSource(
            DataSourceBase *source,
            DataSourceHelper *source,
            MetaDataBase &meta,
            const Vector<uint64_t> &offset_vector,
            int64_t frame_duration_us);
@@ -54,7 +54,7 @@ protected:

private:
    static const size_t kMaxFrameSize;
    DataSourceBase *mDataSource;
    DataSourceHelper *mDataSource;
    MetaDataBase mMeta;

    off64_t mOffset;
@@ -92,7 +92,7 @@ uint32_t get_sample_rate(const uint8_t sf_index)
// The returned value is the AAC frame size with the ADTS header length (regardless of
//     the presence of the CRC).
// If headerSize is non-NULL, it will be used to return the size of the header of this ADTS frame.
static size_t getAdtsFrameLength(DataSourceBase *source, off64_t offset, size_t* headerSize) {
static size_t getAdtsFrameLength(DataSourceHelper *source, off64_t offset, size_t* headerSize) {

    const size_t kAdtsHeaderLengthNoCrc = 7;
    const size_t kAdtsHeaderLengthWithCrc = 9;
@@ -133,7 +133,7 @@ static size_t getAdtsFrameLength(DataSourceBase *source, off64_t offset, size_t*
}

AACExtractor::AACExtractor(
        DataSourceBase *source, off64_t offset)
        DataSourceHelper *source, off64_t offset)
    : mDataSource(source),
      mInitCheck(NO_INIT),
      mFrameDurationUs(0) {
@@ -219,7 +219,7 @@ status_t AACExtractor::getTrackMetaData(MetaDataBase &meta, size_t index, uint32
const size_t AACSource::kMaxFrameSize = 8192;

AACSource::AACSource(
        DataSourceBase *source,
        DataSourceHelper *source,
        MetaDataBase &meta,
        const Vector<uint64_t> &offset_vector,
        int64_t frame_duration_us)
@@ -323,21 +323,22 @@ status_t AACSource::read(

////////////////////////////////////////////////////////////////////////////////

static MediaExtractor* CreateExtractor(
        DataSourceBase *source,
static CMediaExtractor* CreateExtractor(
        CDataSource *source,
        void *meta) {
    off64_t offset = *static_cast<off64_t*>(meta);
    return new AACExtractor(source, offset);
    return wrap(new AACExtractor(new DataSourceHelper(source), offset));
}

static MediaExtractor::CreatorFunc Sniff(
        DataSourceBase *source, float *confidence, void **meta,
        MediaExtractor::FreeMetaFunc *freeMeta) {
static CreatorFunc Sniff(
        CDataSource *source, float *confidence, void **meta,
        FreeMetaFunc *freeMeta) {
    off64_t pos = 0;

    DataSourceHelper helper(source);
    for (;;) {
        uint8_t id3header[10];
        if (source->readAt(pos, id3header, sizeof(id3header))
        if (helper.readAt(pos, id3header, sizeof(id3header))
                < (ssize_t)sizeof(id3header)) {
            return NULL;
        }
@@ -364,7 +365,7 @@ static MediaExtractor::CreatorFunc Sniff(

    uint8_t header[2];

    if (source->readAt(pos, &header, 2) != 2) {
    if (helper.readAt(pos, &header, 2) != 2) {
        return NULL;
    }

@@ -387,9 +388,9 @@ static MediaExtractor::CreatorFunc Sniff(
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
MediaExtractor::ExtractorDef GETEXTRACTORDEF() {
ExtractorDef GETEXTRACTORDEF() {
    return {
        MediaExtractor::EXTRACTORDEF_VERSION,
        EXTRACTORDEF_VERSION,
        UUID("4fd80eae-03d2-4d72-9eb9-48fa6bb54613"),
        1, // version
        "AAC Extractor",
+6 −5
Original line number Diff line number Diff line
@@ -18,7 +18,8 @@

#define AAC_EXTRACTOR_H_

#include <media/MediaExtractor.h>
#include <media/MediaExtractorPluginApi.h>
#include <media/MediaExtractorPluginHelper.h>
#include <media/stagefright/MetaDataBase.h>

#include <utils/Vector.h>
@@ -28,9 +29,9 @@ namespace android {
struct AMessage;
class String8;

class AACExtractor : public MediaExtractor {
class AACExtractor : public MediaExtractorPluginHelper {
public:
    AACExtractor(DataSourceBase *source, off64_t offset);
    AACExtractor(DataSourceHelper *source, off64_t offset);

    virtual size_t countTracks();
    virtual MediaTrack *getTrack(size_t index);
@@ -43,7 +44,7 @@ protected:
    virtual ~AACExtractor();

private:
    DataSourceBase *mDataSource;
    DataSourceHelper *mDataSource;
    MetaDataBase mMeta;
    status_t mInitCheck;

@@ -55,7 +56,7 @@ private:
};

bool SniffAAC(
        DataSourceBase *source, String8 *mimeType, float *confidence, off64_t *offset);
        DataSourceHelper *source, String8 *mimeType, float *confidence, off64_t *offset);

}  // namespace android

+16 −15
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@

#include "AMRExtractor.h"

#include <media/DataSourceBase.h>
#include <media/MediaTrack.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaBufferGroup.h>
@@ -34,7 +33,7 @@ namespace android {
class AMRSource : public MediaTrack {
public:
    AMRSource(
            DataSourceBase *source,
            DataSourceHelper *source,
            MetaDataBase &meta,
            bool isWide,
            const off64_t *offset_table,
@@ -52,7 +51,7 @@ protected:
    virtual ~AMRSource();

private:
    DataSourceBase *mDataSource;
    DataSourceHelper *mDataSource;
    MetaDataBase mMeta;
    bool mIsWide;

@@ -98,7 +97,7 @@ static size_t getFrameSize(bool isWide, unsigned FT) {
    return frameSize;
}

static status_t getFrameSizeByOffset(DataSourceBase *source,
static status_t getFrameSizeByOffset(DataSourceHelper *source,
        off64_t offset, bool isWide, size_t *frameSize) {
    uint8_t header;
    ssize_t count = source->readAt(offset, &header, 1);
@@ -118,7 +117,7 @@ static status_t getFrameSizeByOffset(DataSourceBase *source,
}

static bool SniffAMR(
        DataSourceBase *source, bool *isWide, float *confidence) {
        DataSourceHelper *source, bool *isWide, float *confidence) {
    char header[9];

    if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
@@ -144,7 +143,7 @@ static bool SniffAMR(
    return false;
}

AMRExtractor::AMRExtractor(DataSourceBase *source)
AMRExtractor::AMRExtractor(DataSourceHelper *source)
    : mDataSource(source),
      mInitCheck(NO_INIT),
      mOffsetTableLength(0) {
@@ -192,6 +191,7 @@ AMRExtractor::AMRExtractor(DataSourceBase *source)
}

AMRExtractor::~AMRExtractor() {
    delete mDataSource;
}

status_t AMRExtractor::getMetaData(MetaDataBase &meta) {
@@ -229,7 +229,7 @@ status_t AMRExtractor::getTrackMetaData(MetaDataBase &meta, size_t index, uint32
////////////////////////////////////////////////////////////////////////////////

AMRSource::AMRSource(
        DataSourceBase *source, MetaDataBase &meta,
        DataSourceHelper *source, MetaDataBase &meta,
        bool isWide, const off64_t *offset_table, size_t offset_table_length)
    : mDataSource(source),
      mMeta(meta),
@@ -365,22 +365,23 @@ status_t AMRSource::read(
extern "C" {
// This is the only symbol that needs to be exported
__attribute__ ((visibility ("default")))
MediaExtractor::ExtractorDef GETEXTRACTORDEF() {
ExtractorDef GETEXTRACTORDEF() {
    return {
        MediaExtractor::EXTRACTORDEF_VERSION,
        EXTRACTORDEF_VERSION,
        UUID("c86639c9-2f31-40ac-a715-fa01b4493aaf"),
        1,
        "AMR Extractor",
        [](
                DataSourceBase *source,
                CDataSource *source,
                float *confidence,
                void **,
                MediaExtractor::FreeMetaFunc *) -> MediaExtractor::CreatorFunc {
            if (SniffAMR(source, nullptr, confidence)) {
                FreeMetaFunc *) -> CreatorFunc {
            DataSourceHelper helper(source);
            if (SniffAMR(&helper, nullptr, confidence)) {
                return [](
                        DataSourceBase *source,
                        void *) -> MediaExtractor* {
                    return new AMRExtractor(source);};
                        CDataSource *source,
                        void *) -> CMediaExtractor* {
                    return wrap(new AMRExtractor(new DataSourceHelper(source)));};
            }
            return NULL;
        }
Loading