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

Commit 23858874 authored by Marco Nelissen's avatar Marco Nelissen
Browse files

Move (some) codecs into the codec process

Encoders and secure decoders still run in the mediaserver, while
all other codecs run in a separate codec process.

Bug: 22775369

Change-Id: Ie2ac87d53edbcf7c8f46a68a15857c9940f6d00d
parent f25f8410
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ public:

    virtual status_t allocateNode(
            const char *name, const sp<IOMXObserver> &observer,
            sp<IBinder> *nodeBinder,
            node_id *node) = 0;

    virtual status_t freeNode(node_id node) = 0;
+1 −0
Original line number Diff line number Diff line
@@ -238,6 +238,7 @@ private:
    uint32_t mFlags;
    uint32_t mQuirks;
    sp<IOMX> mOMX;
    sp<IBinder> mNodeBinder;
    IOMX::node_id mNode;
    sp<MemoryDealer> mDealer[2];

+8 −2
Original line number Diff line number Diff line
@@ -98,7 +98,9 @@ public:
    }

    virtual status_t allocateNode(
            const char *name, const sp<IOMXObserver> &observer, node_id *node) {
            const char *name, const sp<IOMXObserver> &observer,
            sp<IBinder> *nodeBinder,
            node_id *node) {
        Parcel data, reply;
        data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
        data.writeCString(name);
@@ -108,6 +110,9 @@ public:
        status_t err = reply.readInt32();
        if (err == OK) {
            *node = (node_id)reply.readInt32();
            if (nodeBinder != NULL) {
                *nodeBinder = remote();
            }
        } else {
            *node = 0;
        }
@@ -656,7 +661,8 @@ status_t BnOMX::onTransact(

            node_id node;

            status_t err = allocateNode(name, observer, &node);
            status_t err = allocateNode(name, observer,
                    NULL /* nodeBinder */, &node);
            reply->writeInt32(err);
            if (err == OK) {
                reply->writeInt32((int32_t)node);
+11 −10
Original line number Diff line number Diff line
@@ -5541,7 +5541,7 @@ void ACodec::UninitializedState::stateEntered() {
    ALOGV("Now uninitialized");

    if (mDeathNotifier != NULL) {
        IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier);
        mCodec->mNodeBinder->unlinkToDeath(mDeathNotifier);
        mDeathNotifier.clear();
    }

@@ -5638,13 +5638,6 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {

    sp<AMessage> notify = new AMessage(kWhatOMXDied, mCodec);

    mDeathNotifier = new DeathNotifier(notify);
    if (IInterface::asBinder(omx)->linkToDeath(mDeathNotifier) != OK) {
        // This was a local binder, if it dies so do we, we won't care
        // about any notifications in the afterlife.
        mDeathNotifier.clear();
    }

    Vector<AString> matchingCodecs;

    AString mime;
@@ -5683,7 +5676,7 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
        pid_t tid = gettid();
        int prevPriority = androidGetThreadPriority(tid);
        androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
        err = omx->allocateNode(componentName.c_str(), observer, &node);
        err = omx->allocateNode(componentName.c_str(), observer, &mCodec->mNodeBinder, &node);
        androidSetThreadPriority(tid, prevPriority);

        if (err == OK) {
@@ -5707,6 +5700,14 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
        return false;
    }

    mDeathNotifier = new DeathNotifier(notify);
    if (mCodec->mNodeBinder == NULL ||
            mCodec->mNodeBinder->linkToDeath(mDeathNotifier) != OK) {
        // This was a local binder, if it dies so do we, we won't care
        // about any notifications in the afterlife.
        mDeathNotifier.clear();
    }

    notify = new AMessage(kWhatOMXMessageList, mCodec);
    observer->setNotificationMessage(notify);

@@ -7078,7 +7079,7 @@ status_t ACodec::queryCapabilities(
    sp<CodecObserver> observer = new CodecObserver;
    IOMX::node_id node = 0;

    err = omx->allocateNode(name.c_str(), observer, &node);
    err = omx->allocateNode(name.c_str(), observer, NULL, &node);
    if (err != OK) {
        client.disconnect();
        return err;
+105 −34
Original line number Diff line number Diff line
@@ -25,19 +25,29 @@

#include <binder/IServiceManager.h>
#include <media/IMediaPlayerService.h>
#include <media/IMediaCodecService.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/OMXClient.h>
#include <cutils/properties.h>
#include <utils/KeyedVector.h>

#include "include/OMX.h"

namespace android {

static bool sCodecProcessEnabled = true;

struct MuxOMX : public IOMX {
    MuxOMX(const sp<IOMX> &remoteOMX);
    MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX);
    virtual ~MuxOMX();

    virtual IBinder *onAsBinder() { return IInterface::asBinder(mRemoteOMX).get(); }
    // Nobody should be calling this. In case someone does anyway, just
    // return the media server IOMX.
    // TODO: return NULL
    virtual IBinder *onAsBinder() {
        ALOGE("MuxOMX::onAsBinder should not be called");
        return IInterface::asBinder(mMediaServerOMX).get();
    }

    virtual bool livesLocally(node_id node, pid_t pid);

@@ -45,6 +55,7 @@ struct MuxOMX : public IOMX {

    virtual status_t allocateNode(
            const char *name, const sp<IOMXObserver> &observer,
            sp<IBinder> *nodeBinder,
            node_id *node);

    virtual status_t freeNode(node_id node);
@@ -148,23 +159,32 @@ struct MuxOMX : public IOMX {
private:
    mutable Mutex mLock;

    sp<IOMX> mRemoteOMX;
    sp<IOMX> mMediaServerOMX;
    sp<IOMX> mMediaCodecOMX;
    sp<IOMX> mLocalOMX;

    KeyedVector<node_id, bool> mIsLocalNode;
    typedef enum {
        LOCAL,
        MEDIAPROCESS,
        CODECPROCESS
    } node_location;

    KeyedVector<node_id, node_location> mNodeLocation;

    bool isLocalNode(node_id node) const;
    bool isLocalNode_l(node_id node) const;
    const sp<IOMX> &getOMX(node_id node) const;
    const sp<IOMX> &getOMX_l(node_id node) const;

    static bool CanLiveLocally(const char *name);
    static node_location getPreferredCodecLocation(const char *name);

    DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
};

MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
    : mRemoteOMX(remoteOMX) {
MuxOMX::MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX)
    : mMediaServerOMX(mediaServerOMX),
      mMediaCodecOMX(mediaCodecOMX) {
    ALOGI("MuxOMX ctor");
}

MuxOMX::~MuxOMX() {
@@ -177,27 +197,49 @@ bool MuxOMX::isLocalNode(node_id node) const {
}

bool MuxOMX::isLocalNode_l(node_id node) const {
    return mIsLocalNode.indexOfKey(node) >= 0;
    return mNodeLocation.valueFor(node) == LOCAL;
}

// static
bool MuxOMX::CanLiveLocally(const char *name) {
MuxOMX::node_location MuxOMX::getPreferredCodecLocation(const char *name) {
    if (sCodecProcessEnabled) {
        // all non-secure decoders plus OMX.google.* encoders can go in the codec process
        if ((strcasestr(name, "decoder") && !strcasestr(name, "secure")) ||
                !strncasecmp(name, "OMX.google.", 11)) {
            return CODECPROCESS;
        }
        // everything else runs in the media server
        return MEDIAPROCESS;
    } else {
#ifdef __LP64__
    (void)name; // disable unused parameter warning
        // 64 bit processes always run OMX remote on MediaServer
    return false;
        return MEDIAPROCESS;
#else
        // 32 bit processes run only OMX.google.* components locally
    return !strncasecmp(name, "OMX.google.", 11);
        if (!strncasecmp(name, "OMX.google.", 11)) {
            return LOCAL;
        }
        return MEDIAPROCESS;
#endif
    }
}

const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
    return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
    Mutex::Autolock autoLock(mLock);
    return getOMX_l(node);
}

const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
    return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
    node_location loc = mNodeLocation.valueFor(node);
    if (loc == LOCAL) {
        return mLocalOMX;
    } else if (loc == MEDIAPROCESS) {
        return mMediaServerOMX;
    } else if (loc == CODECPROCESS) {
        return mMediaCodecOMX;
    }
    ALOGE("Couldn't determine node location for node %d: %d, using local", node, loc);
    return mLocalOMX;
}

bool MuxOMX::livesLocally(node_id node, pid_t pid) {
@@ -216,29 +258,34 @@ status_t MuxOMX::listNodes(List<ComponentInfo> *list) {

status_t MuxOMX::allocateNode(
        const char *name, const sp<IOMXObserver> &observer,
        sp<IBinder> *nodeBinder,
        node_id *node) {
    Mutex::Autolock autoLock(mLock);

    sp<IOMX> omx;

    if (CanLiveLocally(name)) {
    node_location loc = getPreferredCodecLocation(name);
    if (loc == CODECPROCESS) {
        omx = mMediaCodecOMX;
    } else if (loc == MEDIAPROCESS) {
        omx = mMediaServerOMX;
    } else {
        if (mLocalOMX == NULL) {
            mLocalOMX = new OMX;
        }
        omx = mLocalOMX;
    } else {
        omx = mRemoteOMX;
    }

    status_t err = omx->allocateNode(name, observer, node);
    status_t err = omx->allocateNode(name, observer, nodeBinder, node);
    ALOGV("allocated node_id %x on %s OMX", *node, omx == mMediaCodecOMX ? "codecprocess" :
            omx == mMediaServerOMX ? "mediaserver" : "local");


    if (err != OK) {
        return err;
    }

    if (omx == mLocalOMX) {
        mIsLocalNode.add(*node, true);
    }
    mNodeLocation.add(*node, loc);

    return OK;
}
@@ -252,7 +299,7 @@ status_t MuxOMX::freeNode(node_id node) {
        return err;
    }

    mIsLocalNode.removeItem(node);
    mNodeLocation.removeItem(node);

    return OK;
}
@@ -352,7 +399,7 @@ status_t MuxOMX::createPersistentInputSurface(
        sp<IGraphicBufferProducer> *bufferProducer,
        sp<IGraphicBufferConsumer> *bufferConsumer) {
    // TODO: local or remote? Always use remote for now
    return mRemoteOMX->createPersistentInputSurface(
    return mMediaServerOMX->createPersistentInputSurface(
            bufferProducer, bufferConsumer);
}

@@ -415,29 +462,53 @@ status_t MuxOMX::setInternalOption(
}

OMXClient::OMXClient() {
    char value[PROPERTY_VALUE_MAX];
    if (property_get("media.stagefright.codecremote", value, NULL)
            && (!strcmp("0", value) || !strcasecmp("false", value))) {
        sCodecProcessEnabled = false;
    }
}

status_t OMXClient::connect() {
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("media.player"));
    sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
    sp<IBinder> playerbinder = sm->getService(String16("media.player"));
    sp<IMediaPlayerService> mediaservice = interface_cast<IMediaPlayerService>(playerbinder);

    if (service.get() == NULL) {
    if (mediaservice.get() == NULL) {
        ALOGE("Cannot obtain IMediaPlayerService");
        return NO_INIT;
    }

    mOMX = service->getOMX();
    if (mOMX.get() == NULL) {
        ALOGE("Cannot obtain IOMX");
    sp<IOMX> mediaServerOMX = mediaservice->getOMX();
    if (mediaServerOMX.get() == NULL) {
        ALOGE("Cannot obtain mediaserver IOMX");
        return NO_INIT;
    }

    if (!mOMX->livesLocally(0 /* node */, getpid())) {
        ALOGI("Using client-side OMX mux.");
        mOMX = new MuxOMX(mOMX);
    // If we don't want to use the codec process, and the media server OMX
    // is local, use it directly instead of going through MuxOMX
    if (!sCodecProcessEnabled &&
            mediaServerOMX->livesLocally(0 /* node */, getpid())) {
        mOMX = mediaServerOMX;
        return OK;
    }

    sp<IBinder> codecbinder = sm->getService(String16("media.codec"));
    sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder);

    if (codecservice.get() == NULL) {
        ALOGE("Cannot obtain IMediaCodecService");
        return NO_INIT;
    }

    sp<IOMX> mediaCodecOMX = codecservice->getOMX();
    if (mediaCodecOMX.get() == NULL) {
        ALOGE("Cannot obtain mediacodec IOMX");
        return NO_INIT;
    }

    mOMX = new MuxOMX(mediaServerOMX, mediaCodecOMX);

    return OK;
}

Loading