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

Commit e13526ad authored by Andreas Huber's avatar Andreas Huber
Browse files

Prefer software decoders over hardware for thumbnail extraction.

While our hardware decoders clearly outperform the software decoders in terms
of raw throughput, their startup latency makes them less suitable for thumbnail
extraction.
parent e981c334
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -30,11 +30,15 @@ struct OMXCodecObserver;

struct OMXCodec : public MediaSource,
                  public MediaBufferObserver {
    enum CreationFlags {
        kPreferSoftwareCodecs = 1,
    };
    static sp<OMXCodec> Create(
            const sp<IOMX> &omx,
            const sp<MetaData> &meta, bool createEncoder,
            const sp<MediaSource> &source,
            const char *matchComponentName = NULL);
            const char *matchComponentName = NULL,
            uint32_t flags = 0);

    static void setComponentRole(
            const sp<IOMX> &omx, IOMX::node_id node, bool isEncoder,
@@ -207,6 +211,14 @@ private:

    void dumpPortStatus(OMX_U32 portIndex);

    static uint32_t getComponentQuirks(const char *componentName);

    static void findMatchingCodecs(
            const char *mime,
            bool createEncoder, const char *matchComponentName,
            uint32_t flags,
            Vector<String8> *matchingCodecs);

    OMXCodec(const OMXCodec &);
    OMXCodec &operator=(const OMXCodec &);
};
+2 −1
Original line number Diff line number Diff line
@@ -122,7 +122,8 @@ VideoFrame *StagefrightMetadataRetriever::captureFrame() {

    sp<MediaSource> decoder =
        OMXCodec::Create(
                mClient.interface(), meta, false, source);
                mClient.interface(), meta, false, source,
                NULL, OMXCodec::kPreferSoftwareCodecs);

    if (decoder.get() == NULL) {
        LOGE("unable to instantiate video decoder.");
+109 −37
Original line number Diff line number Diff line
@@ -172,49 +172,35 @@ static void InitOMXParams(T *params) {
    params->nVersion.s.nStep = 0;
}

// static
sp<OMXCodec> OMXCodec::Create(
        const sp<IOMX> &omx,
        const sp<MetaData> &meta, bool createEncoder,
        const sp<MediaSource> &source,
        const char *matchComponentName) {
    const char *mime;
    bool success = meta->findCString(kKeyMIMEType, &mime);
    CHECK(success);

    const char *componentName = NULL;
    sp<OMXCodecObserver> observer = new OMXCodecObserver;
    IOMX::node_id node = 0;
    for (int index = 0;; ++index) {
        if (createEncoder) {
            componentName = GetCodec(
                    kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
                    mime, index);
        } else {
            componentName = GetCodec(
                    kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
                    mime, index);
static bool IsSoftwareCodec(const char *componentName) {
    if (!strncmp("OMX.PV.", componentName, 7)) {
        return true;
    }

        if (!componentName) {
            return NULL;
    return false;
}

        // If a specific codec is requested, skip the non-matching ones.
        if (matchComponentName && strcmp(componentName, matchComponentName)) {
            continue;
        }
static int CompareSoftwareCodecsFirst(
        const String8 *elem1, const String8 *elem2) {
    bool isSoftwareCodec1 = IsSoftwareCodec(elem1->string());
    bool isSoftwareCodec2 = IsSoftwareCodec(elem2->string());

        LOGV("Attempting to allocate OMX node '%s'", componentName);
    if (isSoftwareCodec1) {
        if (isSoftwareCodec2) { return 0; }
        return -1;
    }

        status_t err = omx->allocateNode(componentName, observer, &node);
        if (err == OK) {
            LOGV("Successfully allocated OMX node '%s'", componentName);
            break;
    if (isSoftwareCodec2) {
        return 1;
    }

    return 0;
}

// static
uint32_t OMXCodec::getComponentQuirks(const char *componentName) {
    uint32_t quirks = 0;

    if (!strcmp(componentName, "OMX.PV.avcdec")) {
        quirks |= kWantsNALFragments;
    }
@@ -244,8 +230,94 @@ sp<OMXCodec> OMXCodec::Create(
        quirks |= kRequiresAllocateBufferOnOutputPorts;
    }

    return quirks;
}

// static
void OMXCodec::findMatchingCodecs(
        const char *mime,
        bool createEncoder, const char *matchComponentName,
        uint32_t flags,
        Vector<String8> *matchingCodecs) {
    matchingCodecs->clear();

    for (int index = 0;; ++index) {
        const char *componentName;

        if (createEncoder) {
            componentName = GetCodec(
                    kEncoderInfo,
                    sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
                    mime, index);
        } else {
            componentName = GetCodec(
                    kDecoderInfo,
                    sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
                    mime, index);
        }

        if (!componentName) {
            break;
        }

        // If a specific codec is requested, skip the non-matching ones.
        if (matchComponentName && strcmp(componentName, matchComponentName)) {
            continue;
        }

        matchingCodecs->push(String8(componentName));
    }

    if (flags & kPreferSoftwareCodecs) {
        matchingCodecs->sort(CompareSoftwareCodecsFirst);
    }
}

// static
sp<OMXCodec> OMXCodec::Create(
        const sp<IOMX> &omx,
        const sp<MetaData> &meta, bool createEncoder,
        const sp<MediaSource> &source,
        const char *matchComponentName,
        uint32_t flags) {
    const char *mime;
    bool success = meta->findCString(kKeyMIMEType, &mime);
    CHECK(success);

    Vector<String8> matchingCodecs;
    findMatchingCodecs(
            mime, createEncoder, matchComponentName, flags, &matchingCodecs);

    if (matchingCodecs.isEmpty()) {
        return NULL;
    }

    sp<OMXCodecObserver> observer = new OMXCodecObserver;
    IOMX::node_id node = 0;
    success = false;

    const char *componentName;
    for (size_t i = 0; i < matchingCodecs.size(); ++i) {
        componentName = matchingCodecs[i].string();

        LOGV("Attempting to allocate OMX node '%s'", componentName);

        status_t err = omx->allocateNode(componentName, observer, &node);
        if (err == OK) {
            LOGV("Successfully allocated OMX node '%s'", componentName);

            success = true;
            break;
        }
    }

    if (!success) {
        return NULL;
    }

    sp<OMXCodec> codec = new OMXCodec(
            omx, node, quirks, createEncoder, mime, componentName,
            omx, node, getComponentQuirks(componentName),
            createEncoder, mime, componentName,
            source);

    observer->setCodec(codec);