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
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 9a7dff6..b9ee91a 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -98,7 +98,9 @@
}
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 @@
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 @@
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);
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 0dc5d4c..ee573f0 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -5541,7 +5541,7 @@
ALOGV("Now uninitialized");
if (mDeathNotifier != NULL) {
- IInterface::asBinder(mCodec->mOMX)->unlinkToDeath(mDeathNotifier);
+ mCodec->mNodeBinder->unlinkToDeath(mDeathNotifier);
mDeathNotifier.clear();
}
@@ -5638,13 +5638,6 @@
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 @@
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 @@
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 @@
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;
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 50f235e..8e72405 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -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 @@
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 @@
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_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;
+ // 64 bit processes always run OMX remote on MediaServer
+ return MEDIAPROCESS;
#else
- // 32 bit processes run only OMX.google.* components locally
- return !strncasecmp(name, "OMX.google.", 11);
+ // 32 bit processes run only OMX.google.* components locally
+ 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::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 @@
return err;
}
- mIsLocalNode.removeItem(node);
+ mNodeLocation.removeItem(node);
return OK;
}
@@ -352,7 +399,7 @@
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 @@
}
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;
}
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index 4c27360..c715939 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -36,7 +36,9 @@
virtual status_t listNodes(List<ComponentInfo> *list);
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);
virtual status_t freeNode(node_id node);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index a20028b..6be289b 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -235,10 +235,14 @@
}
status_t OMX::allocateNode(
- const char *name, const sp<IOMXObserver> &observer, node_id *node) {
+ const char *name, const sp<IOMXObserver> &observer,
+ sp<IBinder> *nodeBinder, node_id *node) {
Mutex::Autolock autoLock(mLock);
*node = 0;
+ if (nodeBinder != NULL) {
+ *nodeBinder = NULL;
+ }
if (mNodeIDToInstance.size() == kMaxNodeInstances) {
// all possible node IDs are in use
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index c0ccb35..50bb0de 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -267,7 +267,7 @@
IOMX::node_id node;
status_t err =
- mOMX->allocateNode(componentName, this, &node);
+ mOMX->allocateNode(componentName, this, NULL, &node);
EXPECT_SUCCESS(err, "allocateNode");
NodeReaper reaper(this, node);