1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "OMXClient" 19 20#ifdef __LP64__ 21#define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS 22#endif 23 24#include <utils/Log.h> 25 26#include <binder/IServiceManager.h> 27#include <media/IMediaPlayerService.h> 28#include <media/stagefright/foundation/ADebug.h> 29#include <media/stagefright/OMXClient.h> 30#include <utils/KeyedVector.h> 31 32#include "include/OMX.h" 33 34namespace android { 35 36struct MuxOMX : public IOMX { 37 MuxOMX(const sp<IOMX> &remoteOMX); 38 virtual ~MuxOMX(); 39 40 virtual IBinder *onAsBinder() { return mRemoteOMX->asBinder().get(); } 41 42 virtual bool livesLocally(node_id node, pid_t pid); 43 44 virtual status_t listNodes(List<ComponentInfo> *list); 45 46 virtual status_t allocateNode( 47 const char *name, const sp<IOMXObserver> &observer, 48 node_id *node); 49 50 virtual status_t freeNode(node_id node); 51 52 virtual status_t sendCommand( 53 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param); 54 55 virtual status_t getParameter( 56 node_id node, OMX_INDEXTYPE index, 57 void *params, size_t size); 58 59 virtual status_t setParameter( 60 node_id node, OMX_INDEXTYPE index, 61 const void *params, size_t size); 62 63 virtual status_t getConfig( 64 node_id node, OMX_INDEXTYPE index, 65 void *params, size_t size); 66 67 virtual status_t setConfig( 68 node_id node, OMX_INDEXTYPE index, 69 const void *params, size_t size); 70 71 virtual status_t getState( 72 node_id node, OMX_STATETYPE* state); 73 74 virtual status_t storeMetaDataInBuffers( 75 node_id node, OMX_U32 port_index, OMX_BOOL enable); 76 77 virtual status_t prepareForAdaptivePlayback( 78 node_id node, OMX_U32 port_index, OMX_BOOL enable, 79 OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight); 80 81 virtual status_t configureVideoTunnelMode( 82 node_id node, OMX_U32 portIndex, OMX_BOOL tunneled, 83 OMX_U32 audioHwSync, native_handle_t **sidebandHandle); 84 85 virtual status_t enableGraphicBuffers( 86 node_id node, OMX_U32 port_index, OMX_BOOL enable); 87 88 virtual status_t getGraphicBufferUsage( 89 node_id node, OMX_U32 port_index, OMX_U32* usage); 90 91 virtual status_t useBuffer( 92 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 93 buffer_id *buffer); 94 95 virtual status_t useGraphicBuffer( 96 node_id node, OMX_U32 port_index, 97 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer); 98 99 virtual status_t updateGraphicBufferInMeta( 100 node_id node, OMX_U32 port_index, 101 const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer); 102 103 virtual status_t createInputSurface( 104 node_id node, OMX_U32 port_index, 105 sp<IGraphicBufferProducer> *bufferProducer); 106 107 virtual status_t signalEndOfInputStream(node_id node); 108 109 virtual status_t allocateBuffer( 110 node_id node, OMX_U32 port_index, size_t size, 111 buffer_id *buffer, void **buffer_data); 112 113 virtual status_t allocateBufferWithBackup( 114 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 115 buffer_id *buffer); 116 117 virtual status_t freeBuffer( 118 node_id node, OMX_U32 port_index, buffer_id buffer); 119 120 virtual status_t fillBuffer(node_id node, buffer_id buffer); 121 122 virtual status_t emptyBuffer( 123 node_id node, 124 buffer_id buffer, 125 OMX_U32 range_offset, OMX_U32 range_length, 126 OMX_U32 flags, OMX_TICKS timestamp); 127 128 virtual status_t getExtensionIndex( 129 node_id node, 130 const char *parameter_name, 131 OMX_INDEXTYPE *index); 132 133 virtual status_t setInternalOption( 134 node_id node, 135 OMX_U32 port_index, 136 InternalOptionType type, 137 const void *data, 138 size_t size); 139 140private: 141 mutable Mutex mLock; 142 143 sp<IOMX> mRemoteOMX; 144 sp<IOMX> mLocalOMX; 145 146 KeyedVector<node_id, bool> mIsLocalNode; 147 148 bool isLocalNode(node_id node) const; 149 bool isLocalNode_l(node_id node) const; 150 const sp<IOMX> &getOMX(node_id node) const; 151 const sp<IOMX> &getOMX_l(node_id node) const; 152 153 static bool CanLiveLocally(const char *name); 154 155 DISALLOW_EVIL_CONSTRUCTORS(MuxOMX); 156}; 157 158MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX) 159 : mRemoteOMX(remoteOMX) { 160} 161 162MuxOMX::~MuxOMX() { 163} 164 165bool MuxOMX::isLocalNode(node_id node) const { 166 Mutex::Autolock autoLock(mLock); 167 168 return isLocalNode_l(node); 169} 170 171bool MuxOMX::isLocalNode_l(node_id node) const { 172 return mIsLocalNode.indexOfKey(node) >= 0; 173} 174 175// static 176bool MuxOMX::CanLiveLocally(const char *name) { 177#ifdef __LP64__ 178 (void)name; // disable unused parameter warning 179 // 64 bit processes always run OMX remote on MediaServer 180 return false; 181#else 182 // 32 bit processes run only OMX.google.* components locally 183 return !strncasecmp(name, "OMX.google.", 11); 184#endif 185} 186 187const sp<IOMX> &MuxOMX::getOMX(node_id node) const { 188 return isLocalNode(node) ? mLocalOMX : mRemoteOMX; 189} 190 191const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const { 192 return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX; 193} 194 195bool MuxOMX::livesLocally(node_id node, pid_t pid) { 196 return getOMX(node)->livesLocally(node, pid); 197} 198 199status_t MuxOMX::listNodes(List<ComponentInfo> *list) { 200 Mutex::Autolock autoLock(mLock); 201 202 if (mLocalOMX == NULL) { 203 mLocalOMX = new OMX; 204 } 205 206 return mLocalOMX->listNodes(list); 207} 208 209status_t MuxOMX::allocateNode( 210 const char *name, const sp<IOMXObserver> &observer, 211 node_id *node) { 212 Mutex::Autolock autoLock(mLock); 213 214 sp<IOMX> omx; 215 216 if (CanLiveLocally(name)) { 217 if (mLocalOMX == NULL) { 218 mLocalOMX = new OMX; 219 } 220 omx = mLocalOMX; 221 } else { 222 omx = mRemoteOMX; 223 } 224 225 status_t err = omx->allocateNode(name, observer, node); 226 227 if (err != OK) { 228 return err; 229 } 230 231 if (omx == mLocalOMX) { 232 mIsLocalNode.add(*node, true); 233 } 234 235 return OK; 236} 237 238status_t MuxOMX::freeNode(node_id node) { 239 Mutex::Autolock autoLock(mLock); 240 241 status_t err = getOMX_l(node)->freeNode(node); 242 243 if (err != OK) { 244 return err; 245 } 246 247 mIsLocalNode.removeItem(node); 248 249 return OK; 250} 251 252status_t MuxOMX::sendCommand( 253 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { 254 return getOMX(node)->sendCommand(node, cmd, param); 255} 256 257status_t MuxOMX::getParameter( 258 node_id node, OMX_INDEXTYPE index, 259 void *params, size_t size) { 260 return getOMX(node)->getParameter(node, index, params, size); 261} 262 263status_t MuxOMX::setParameter( 264 node_id node, OMX_INDEXTYPE index, 265 const void *params, size_t size) { 266 return getOMX(node)->setParameter(node, index, params, size); 267} 268 269status_t MuxOMX::getConfig( 270 node_id node, OMX_INDEXTYPE index, 271 void *params, size_t size) { 272 return getOMX(node)->getConfig(node, index, params, size); 273} 274 275status_t MuxOMX::setConfig( 276 node_id node, OMX_INDEXTYPE index, 277 const void *params, size_t size) { 278 return getOMX(node)->setConfig(node, index, params, size); 279} 280 281status_t MuxOMX::getState( 282 node_id node, OMX_STATETYPE* state) { 283 return getOMX(node)->getState(node, state); 284} 285 286status_t MuxOMX::storeMetaDataInBuffers( 287 node_id node, OMX_U32 port_index, OMX_BOOL enable) { 288 return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable); 289} 290 291status_t MuxOMX::prepareForAdaptivePlayback( 292 node_id node, OMX_U32 port_index, OMX_BOOL enable, 293 OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) { 294 return getOMX(node)->prepareForAdaptivePlayback( 295 node, port_index, enable, maxFrameWidth, maxFrameHeight); 296} 297 298status_t MuxOMX::configureVideoTunnelMode( 299 node_id node, OMX_U32 portIndex, OMX_BOOL enable, 300 OMX_U32 audioHwSync, native_handle_t **sidebandHandle) { 301 return getOMX(node)->configureVideoTunnelMode( 302 node, portIndex, enable, audioHwSync, sidebandHandle); 303} 304 305status_t MuxOMX::enableGraphicBuffers( 306 node_id node, OMX_U32 port_index, OMX_BOOL enable) { 307 return getOMX(node)->enableGraphicBuffers(node, port_index, enable); 308} 309 310status_t MuxOMX::getGraphicBufferUsage( 311 node_id node, OMX_U32 port_index, OMX_U32* usage) { 312 return getOMX(node)->getGraphicBufferUsage(node, port_index, usage); 313} 314 315status_t MuxOMX::useBuffer( 316 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 317 buffer_id *buffer) { 318 return getOMX(node)->useBuffer(node, port_index, params, buffer); 319} 320 321status_t MuxOMX::useGraphicBuffer( 322 node_id node, OMX_U32 port_index, 323 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) { 324 return getOMX(node)->useGraphicBuffer( 325 node, port_index, graphicBuffer, buffer); 326} 327 328status_t MuxOMX::updateGraphicBufferInMeta( 329 node_id node, OMX_U32 port_index, 330 const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) { 331 return getOMX(node)->updateGraphicBufferInMeta( 332 node, port_index, graphicBuffer, buffer); 333} 334 335status_t MuxOMX::createInputSurface( 336 node_id node, OMX_U32 port_index, 337 sp<IGraphicBufferProducer> *bufferProducer) { 338 status_t err = getOMX(node)->createInputSurface( 339 node, port_index, bufferProducer); 340 return err; 341} 342 343status_t MuxOMX::signalEndOfInputStream(node_id node) { 344 return getOMX(node)->signalEndOfInputStream(node); 345} 346 347status_t MuxOMX::allocateBuffer( 348 node_id node, OMX_U32 port_index, size_t size, 349 buffer_id *buffer, void **buffer_data) { 350 return getOMX(node)->allocateBuffer( 351 node, port_index, size, buffer, buffer_data); 352} 353 354status_t MuxOMX::allocateBufferWithBackup( 355 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 356 buffer_id *buffer) { 357 return getOMX(node)->allocateBufferWithBackup( 358 node, port_index, params, buffer); 359} 360 361status_t MuxOMX::freeBuffer( 362 node_id node, OMX_U32 port_index, buffer_id buffer) { 363 return getOMX(node)->freeBuffer(node, port_index, buffer); 364} 365 366status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer) { 367 return getOMX(node)->fillBuffer(node, buffer); 368} 369 370status_t MuxOMX::emptyBuffer( 371 node_id node, 372 buffer_id buffer, 373 OMX_U32 range_offset, OMX_U32 range_length, 374 OMX_U32 flags, OMX_TICKS timestamp) { 375 return getOMX(node)->emptyBuffer( 376 node, buffer, range_offset, range_length, flags, timestamp); 377} 378 379status_t MuxOMX::getExtensionIndex( 380 node_id node, 381 const char *parameter_name, 382 OMX_INDEXTYPE *index) { 383 return getOMX(node)->getExtensionIndex(node, parameter_name, index); 384} 385 386status_t MuxOMX::setInternalOption( 387 node_id node, 388 OMX_U32 port_index, 389 InternalOptionType type, 390 const void *data, 391 size_t size) { 392 return getOMX(node)->setInternalOption(node, port_index, type, data, size); 393} 394 395OMXClient::OMXClient() { 396} 397 398status_t OMXClient::connect() { 399 sp<IServiceManager> sm = defaultServiceManager(); 400 sp<IBinder> binder = sm->getService(String16("media.player")); 401 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 402 403 CHECK(service.get() != NULL); 404 405 mOMX = service->getOMX(); 406 CHECK(mOMX.get() != NULL); 407 408 if (!mOMX->livesLocally(0 /* node */, getpid())) { 409 ALOGI("Using client-side OMX mux."); 410 mOMX = new MuxOMX(mOMX); 411 } 412 413 return OK; 414} 415 416void OMXClient::disconnect() { 417 if (mOMX.get() != NULL) { 418 mOMX.clear(); 419 mOMX = NULL; 420 } 421} 422 423} // namespace android 424