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/IMediaCodecService.h> 29#include <media/stagefright/foundation/ADebug.h> 30#include <media/stagefright/OMXClient.h> 31#include <cutils/properties.h> 32#include <utils/KeyedVector.h> 33 34#include "include/OMX.h" 35 36namespace android { 37 38static bool sCodecProcessEnabled = true; 39 40struct MuxOMX : public IOMX { 41 MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX); 42 virtual ~MuxOMX(); 43 44 // Nobody should be calling this. In case someone does anyway, just 45 // return the media server IOMX. 46 // TODO: return NULL 47 virtual IBinder *onAsBinder() { 48 ALOGE("MuxOMX::onAsBinder should not be called"); 49 return IInterface::asBinder(mMediaServerOMX).get(); 50 } 51 52 virtual bool livesLocally(node_id node, pid_t pid); 53 54 virtual status_t listNodes(List<ComponentInfo> *list); 55 56 virtual status_t allocateNode( 57 const char *name, const sp<IOMXObserver> &observer, 58 sp<IBinder> *nodeBinder, 59 node_id *node); 60 61 virtual status_t freeNode(node_id node); 62 63 virtual status_t sendCommand( 64 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param); 65 66 virtual status_t getParameter( 67 node_id node, OMX_INDEXTYPE index, 68 void *params, size_t size); 69 70 virtual status_t setParameter( 71 node_id node, OMX_INDEXTYPE index, 72 const void *params, size_t size); 73 74 virtual status_t getConfig( 75 node_id node, OMX_INDEXTYPE index, 76 void *params, size_t size); 77 78 virtual status_t setConfig( 79 node_id node, OMX_INDEXTYPE index, 80 const void *params, size_t size); 81 82 virtual status_t getState( 83 node_id node, OMX_STATETYPE* state); 84 85 virtual status_t storeMetaDataInBuffers( 86 node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type); 87 88 virtual status_t prepareForAdaptivePlayback( 89 node_id node, OMX_U32 port_index, OMX_BOOL enable, 90 OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight); 91 92 virtual status_t configureVideoTunnelMode( 93 node_id node, OMX_U32 portIndex, OMX_BOOL tunneled, 94 OMX_U32 audioHwSync, native_handle_t **sidebandHandle); 95 96 virtual status_t enableNativeBuffers( 97 node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable); 98 99 virtual status_t getGraphicBufferUsage( 100 node_id node, OMX_U32 port_index, OMX_U32* usage); 101 102 virtual status_t useBuffer( 103 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 104 buffer_id *buffer, OMX_U32 allottedSize); 105 106 virtual status_t useGraphicBuffer( 107 node_id node, OMX_U32 port_index, 108 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer); 109 110 virtual status_t updateGraphicBufferInMeta( 111 node_id node, OMX_U32 port_index, 112 const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer); 113 114 virtual status_t updateNativeHandleInMeta( 115 node_id node, OMX_U32 port_index, 116 const sp<NativeHandle> &nativeHandle, buffer_id buffer); 117 118 virtual status_t createInputSurface( 119 node_id node, OMX_U32 port_index, android_dataspace dataSpace, 120 sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type); 121 122 virtual status_t createPersistentInputSurface( 123 sp<IGraphicBufferProducer> *bufferProducer, 124 sp<IGraphicBufferConsumer> *bufferConsumer); 125 126 virtual status_t setInputSurface( 127 node_id node, OMX_U32 port_index, 128 const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type); 129 130 virtual status_t signalEndOfInputStream(node_id node); 131 132 virtual status_t allocateSecureBuffer( 133 node_id node, OMX_U32 port_index, size_t size, 134 buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle); 135 136 virtual status_t allocateBufferWithBackup( 137 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 138 buffer_id *buffer, OMX_U32 allottedSize); 139 140 virtual status_t freeBuffer( 141 node_id node, OMX_U32 port_index, buffer_id buffer); 142 143 virtual status_t fillBuffer(node_id node, buffer_id buffer, int fenceFd); 144 145 virtual status_t emptyBuffer( 146 node_id node, 147 buffer_id buffer, 148 OMX_U32 range_offset, OMX_U32 range_length, 149 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd); 150 151 virtual status_t getExtensionIndex( 152 node_id node, 153 const char *parameter_name, 154 OMX_INDEXTYPE *index); 155 156 virtual status_t setInternalOption( 157 node_id node, 158 OMX_U32 port_index, 159 InternalOptionType type, 160 const void *data, 161 size_t size); 162 163private: 164 mutable Mutex mLock; 165 166 sp<IOMX> mMediaServerOMX; 167 sp<IOMX> mMediaCodecOMX; 168 sp<IOMX> mLocalOMX; 169 170 typedef enum { 171 LOCAL, 172 MEDIAPROCESS, 173 CODECPROCESS 174 } node_location; 175 176 KeyedVector<node_id, node_location> mNodeLocation; 177 178 bool isLocalNode(node_id node) const; 179 bool isLocalNode_l(node_id node) const; 180 const sp<IOMX> &getOMX(node_id node) const; 181 const sp<IOMX> &getOMX_l(node_id node) const; 182 183 static node_location getPreferredCodecLocation(const char *name); 184 185 DISALLOW_EVIL_CONSTRUCTORS(MuxOMX); 186}; 187 188MuxOMX::MuxOMX(const sp<IOMX> &mediaServerOMX, const sp<IOMX> &mediaCodecOMX) 189 : mMediaServerOMX(mediaServerOMX), 190 mMediaCodecOMX(mediaCodecOMX) { 191 ALOGI("MuxOMX ctor"); 192} 193 194MuxOMX::~MuxOMX() { 195} 196 197bool MuxOMX::isLocalNode(node_id node) const { 198 Mutex::Autolock autoLock(mLock); 199 200 return isLocalNode_l(node); 201} 202 203bool MuxOMX::isLocalNode_l(node_id node) const { 204 return mNodeLocation.valueFor(node) == LOCAL; 205} 206 207// static 208MuxOMX::node_location MuxOMX::getPreferredCodecLocation(const char *name) { 209 if (sCodecProcessEnabled) { 210 // all codecs go to codec process unless excluded using system property, in which case 211 // all non-secure decoders, OMX.google.* codecs and encoders can go in the codec process 212 // (non-OMX.google.* encoders can be excluded using system property.) 213 if ((strcasestr(name, "decoder") 214 && strcasestr(name, ".secure") != name + strlen(name) - 7) 215 || (strcasestr(name, "encoder") 216 && !property_get_bool("media.stagefright.legacyencoder", false)) 217 || !property_get_bool("media.stagefright.less-secure", false) 218 || !strncasecmp(name, "OMX.google.", 11)) { 219 return CODECPROCESS; 220 } 221 // everything else runs in the media server 222 return MEDIAPROCESS; 223 } else { 224#ifdef __LP64__ 225 // 64 bit processes always run OMX remote on MediaServer 226 return MEDIAPROCESS; 227#else 228 // 32 bit processes run only OMX.google.* components locally 229 if (!strncasecmp(name, "OMX.google.", 11)) { 230 return LOCAL; 231 } 232 return MEDIAPROCESS; 233#endif 234 } 235} 236 237const sp<IOMX> &MuxOMX::getOMX(node_id node) const { 238 Mutex::Autolock autoLock(mLock); 239 return getOMX_l(node); 240} 241 242const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const { 243 node_location loc = mNodeLocation.valueFor(node); 244 if (loc == LOCAL) { 245 return mLocalOMX; 246 } else if (loc == MEDIAPROCESS) { 247 return mMediaServerOMX; 248 } else if (loc == CODECPROCESS) { 249 return mMediaCodecOMX; 250 } 251 ALOGE("Couldn't determine node location for node %d: %d, using local", node, loc); 252 return mLocalOMX; 253} 254 255bool MuxOMX::livesLocally(node_id node, pid_t pid) { 256 return getOMX(node)->livesLocally(node, pid); 257} 258 259status_t MuxOMX::listNodes(List<ComponentInfo> *list) { 260 Mutex::Autolock autoLock(mLock); 261 262 if (mLocalOMX == NULL) { 263 mLocalOMX = new OMX; 264 } 265 266 return mLocalOMX->listNodes(list); 267} 268 269status_t MuxOMX::allocateNode( 270 const char *name, const sp<IOMXObserver> &observer, 271 sp<IBinder> *nodeBinder, 272 node_id *node) { 273 Mutex::Autolock autoLock(mLock); 274 275 sp<IOMX> omx; 276 277 node_location loc = getPreferredCodecLocation(name); 278 if (loc == CODECPROCESS) { 279 omx = mMediaCodecOMX; 280 } else if (loc == MEDIAPROCESS) { 281 omx = mMediaServerOMX; 282 } else { 283 if (mLocalOMX == NULL) { 284 mLocalOMX = new OMX; 285 } 286 omx = mLocalOMX; 287 } 288 289 status_t err = omx->allocateNode(name, observer, nodeBinder, node); 290 ALOGV("allocated node_id %x on %s OMX", *node, omx == mMediaCodecOMX ? "codecprocess" : 291 omx == mMediaServerOMX ? "mediaserver" : "local"); 292 293 294 if (err != OK) { 295 return err; 296 } 297 298 mNodeLocation.add(*node, loc); 299 300 return OK; 301} 302 303status_t MuxOMX::freeNode(node_id node) { 304 Mutex::Autolock autoLock(mLock); 305 306 status_t err = getOMX_l(node)->freeNode(node); 307 308 if (err != OK) { 309 return err; 310 } 311 312 mNodeLocation.removeItem(node); 313 314 return OK; 315} 316 317status_t MuxOMX::sendCommand( 318 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { 319 return getOMX(node)->sendCommand(node, cmd, param); 320} 321 322status_t MuxOMX::getParameter( 323 node_id node, OMX_INDEXTYPE index, 324 void *params, size_t size) { 325 return getOMX(node)->getParameter(node, index, params, size); 326} 327 328status_t MuxOMX::setParameter( 329 node_id node, OMX_INDEXTYPE index, 330 const void *params, size_t size) { 331 return getOMX(node)->setParameter(node, index, params, size); 332} 333 334status_t MuxOMX::getConfig( 335 node_id node, OMX_INDEXTYPE index, 336 void *params, size_t size) { 337 return getOMX(node)->getConfig(node, index, params, size); 338} 339 340status_t MuxOMX::setConfig( 341 node_id node, OMX_INDEXTYPE index, 342 const void *params, size_t size) { 343 return getOMX(node)->setConfig(node, index, params, size); 344} 345 346status_t MuxOMX::getState( 347 node_id node, OMX_STATETYPE* state) { 348 return getOMX(node)->getState(node, state); 349} 350 351status_t MuxOMX::storeMetaDataInBuffers( 352 node_id node, OMX_U32 port_index, OMX_BOOL enable, MetadataBufferType *type) { 353 return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable, type); 354} 355 356status_t MuxOMX::prepareForAdaptivePlayback( 357 node_id node, OMX_U32 port_index, OMX_BOOL enable, 358 OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) { 359 return getOMX(node)->prepareForAdaptivePlayback( 360 node, port_index, enable, maxFrameWidth, maxFrameHeight); 361} 362 363status_t MuxOMX::configureVideoTunnelMode( 364 node_id node, OMX_U32 portIndex, OMX_BOOL enable, 365 OMX_U32 audioHwSync, native_handle_t **sidebandHandle) { 366 return getOMX(node)->configureVideoTunnelMode( 367 node, portIndex, enable, audioHwSync, sidebandHandle); 368} 369 370status_t MuxOMX::enableNativeBuffers( 371 node_id node, OMX_U32 port_index, OMX_BOOL graphic, OMX_BOOL enable) { 372 return getOMX(node)->enableNativeBuffers(node, port_index, graphic, enable); 373} 374 375status_t MuxOMX::getGraphicBufferUsage( 376 node_id node, OMX_U32 port_index, OMX_U32* usage) { 377 return getOMX(node)->getGraphicBufferUsage(node, port_index, usage); 378} 379 380status_t MuxOMX::useBuffer( 381 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 382 buffer_id *buffer, OMX_U32 allottedSize) { 383 return getOMX(node)->useBuffer(node, port_index, params, buffer, allottedSize); 384} 385 386status_t MuxOMX::useGraphicBuffer( 387 node_id node, OMX_U32 port_index, 388 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) { 389 return getOMX(node)->useGraphicBuffer( 390 node, port_index, graphicBuffer, buffer); 391} 392 393status_t MuxOMX::updateGraphicBufferInMeta( 394 node_id node, OMX_U32 port_index, 395 const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) { 396 return getOMX(node)->updateGraphicBufferInMeta( 397 node, port_index, graphicBuffer, buffer); 398} 399 400status_t MuxOMX::updateNativeHandleInMeta( 401 node_id node, OMX_U32 port_index, 402 const sp<NativeHandle> &nativeHandle, buffer_id buffer) { 403 return getOMX(node)->updateNativeHandleInMeta( 404 node, port_index, nativeHandle, buffer); 405} 406 407status_t MuxOMX::createInputSurface( 408 node_id node, OMX_U32 port_index, android_dataspace dataSpace, 409 sp<IGraphicBufferProducer> *bufferProducer, MetadataBufferType *type) { 410 status_t err = getOMX(node)->createInputSurface( 411 node, port_index, dataSpace, bufferProducer, type); 412 return err; 413} 414 415status_t MuxOMX::createPersistentInputSurface( 416 sp<IGraphicBufferProducer> *bufferProducer, 417 sp<IGraphicBufferConsumer> *bufferConsumer) { 418 sp<IOMX> omx; 419 { 420 Mutex::Autolock autoLock(mLock); 421 if (property_get_bool("media.stagefright.legacyencoder", false)) { 422 omx = mMediaServerOMX; 423 } else { 424 omx = mMediaCodecOMX; 425 } 426 } 427 return omx->createPersistentInputSurface( 428 bufferProducer, bufferConsumer); 429} 430 431status_t MuxOMX::setInputSurface( 432 node_id node, OMX_U32 port_index, 433 const sp<IGraphicBufferConsumer> &bufferConsumer, MetadataBufferType *type) { 434 return getOMX(node)->setInputSurface(node, port_index, bufferConsumer, type); 435} 436 437status_t MuxOMX::signalEndOfInputStream(node_id node) { 438 return getOMX(node)->signalEndOfInputStream(node); 439} 440 441status_t MuxOMX::allocateSecureBuffer( 442 node_id node, OMX_U32 port_index, size_t size, 443 buffer_id *buffer, void **buffer_data, sp<NativeHandle> *native_handle) { 444 return getOMX(node)->allocateSecureBuffer( 445 node, port_index, size, buffer, buffer_data, native_handle); 446} 447 448status_t MuxOMX::allocateBufferWithBackup( 449 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 450 buffer_id *buffer, OMX_U32 allottedSize) { 451 return getOMX(node)->allocateBufferWithBackup( 452 node, port_index, params, buffer, allottedSize); 453} 454 455status_t MuxOMX::freeBuffer( 456 node_id node, OMX_U32 port_index, buffer_id buffer) { 457 return getOMX(node)->freeBuffer(node, port_index, buffer); 458} 459 460status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer, int fenceFd) { 461 return getOMX(node)->fillBuffer(node, buffer, fenceFd); 462} 463 464status_t MuxOMX::emptyBuffer( 465 node_id node, 466 buffer_id buffer, 467 OMX_U32 range_offset, OMX_U32 range_length, 468 OMX_U32 flags, OMX_TICKS timestamp, int fenceFd) { 469 return getOMX(node)->emptyBuffer( 470 node, buffer, range_offset, range_length, flags, timestamp, fenceFd); 471} 472 473status_t MuxOMX::getExtensionIndex( 474 node_id node, 475 const char *parameter_name, 476 OMX_INDEXTYPE *index) { 477 return getOMX(node)->getExtensionIndex(node, parameter_name, index); 478} 479 480status_t MuxOMX::setInternalOption( 481 node_id node, 482 OMX_U32 port_index, 483 InternalOptionType type, 484 const void *data, 485 size_t size) { 486 return getOMX(node)->setInternalOption(node, port_index, type, data, size); 487} 488 489OMXClient::OMXClient() { 490 char value[PROPERTY_VALUE_MAX]; 491 if (property_get("media.stagefright.codecremote", value, NULL) 492 && (!strcmp("0", value) || !strcasecmp("false", value))) { 493 sCodecProcessEnabled = false; 494 } 495} 496 497status_t OMXClient::connect() { 498 sp<IServiceManager> sm = defaultServiceManager(); 499 sp<IBinder> playerbinder = sm->getService(String16("media.player")); 500 sp<IMediaPlayerService> mediaservice = interface_cast<IMediaPlayerService>(playerbinder); 501 502 if (mediaservice.get() == NULL) { 503 ALOGE("Cannot obtain IMediaPlayerService"); 504 return NO_INIT; 505 } 506 507 sp<IOMX> mediaServerOMX = mediaservice->getOMX(); 508 if (mediaServerOMX.get() == NULL) { 509 ALOGE("Cannot obtain mediaserver IOMX"); 510 return NO_INIT; 511 } 512 513 // If we don't want to use the codec process, and the media server OMX 514 // is local, use it directly instead of going through MuxOMX 515 if (!sCodecProcessEnabled && 516 mediaServerOMX->livesLocally(0 /* node */, getpid())) { 517 mOMX = mediaServerOMX; 518 return OK; 519 } 520 521 sp<IBinder> codecbinder = sm->getService(String16("media.codec")); 522 sp<IMediaCodecService> codecservice = interface_cast<IMediaCodecService>(codecbinder); 523 524 if (codecservice.get() == NULL) { 525 ALOGE("Cannot obtain IMediaCodecService"); 526 return NO_INIT; 527 } 528 529 sp<IOMX> mediaCodecOMX = codecservice->getOMX(); 530 if (mediaCodecOMX.get() == NULL) { 531 ALOGE("Cannot obtain mediacodec IOMX"); 532 return NO_INIT; 533 } 534 535 mOMX = new MuxOMX(mediaServerOMX, mediaCodecOMX); 536 537 return OK; 538} 539 540void OMXClient::disconnect() { 541 if (mOMX.get() != NULL) { 542 mOMX.clear(); 543 mOMX = NULL; 544 } 545} 546 547} // namespace android 548