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 #include <utils/Log.h> 20 21 #include <binder/IServiceManager.h> 22 #include <media/IMediaPlayerService.h> 23 #include <media/stagefright/foundation/ADebug.h> 24 #include <media/stagefright/OMXClient.h> 25 #include <utils/KeyedVector.h> 26 27 #include "include/OMX.h" 28 29 namespace android { 30 31 struct MuxOMX : public IOMX { 32 MuxOMX(const sp<IOMX> &remoteOMX); 33 virtual ~MuxOMX(); 34 35 virtual IBinder *onAsBinder() { return mRemoteOMX->asBinder().get(); } 36 37 virtual bool livesLocally(node_id node, pid_t pid); 38 39 virtual status_t listNodes(List<ComponentInfo> *list); 40 41 virtual status_t allocateNode( 42 const char *name, const sp<IOMXObserver> &observer, 43 node_id *node); 44 45 virtual status_t freeNode(node_id node); 46 47 virtual status_t sendCommand( 48 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param); 49 50 virtual status_t getParameter( 51 node_id node, OMX_INDEXTYPE index, 52 void *params, size_t size); 53 54 virtual status_t setParameter( 55 node_id node, OMX_INDEXTYPE index, 56 const void *params, size_t size); 57 58 virtual status_t getConfig( 59 node_id node, OMX_INDEXTYPE index, 60 void *params, size_t size); 61 62 virtual status_t setConfig( 63 node_id node, OMX_INDEXTYPE index, 64 const void *params, size_t size); 65 66 virtual status_t getState( 67 node_id node, OMX_STATETYPE* state); 68 69 virtual status_t storeMetaDataInBuffers( 70 node_id node, OMX_U32 port_index, OMX_BOOL enable); 71 72 virtual status_t enableGraphicBuffers( 73 node_id node, OMX_U32 port_index, OMX_BOOL enable); 74 75 virtual status_t getGraphicBufferUsage( 76 node_id node, OMX_U32 port_index, OMX_U32* usage); 77 78 virtual status_t useBuffer( 79 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 80 buffer_id *buffer); 81 82 virtual status_t useGraphicBuffer( 83 node_id node, OMX_U32 port_index, 84 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer); 85 86 virtual status_t createInputSurface( 87 node_id node, OMX_U32 port_index, 88 sp<IGraphicBufferProducer> *bufferProducer); 89 90 virtual status_t signalEndOfInputStream(node_id node); 91 92 virtual status_t allocateBuffer( 93 node_id node, OMX_U32 port_index, size_t size, 94 buffer_id *buffer, void **buffer_data); 95 96 virtual status_t allocateBufferWithBackup( 97 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 98 buffer_id *buffer); 99 100 virtual status_t freeBuffer( 101 node_id node, OMX_U32 port_index, buffer_id buffer); 102 103 virtual status_t fillBuffer(node_id node, buffer_id buffer); 104 105 virtual status_t emptyBuffer( 106 node_id node, 107 buffer_id buffer, 108 OMX_U32 range_offset, OMX_U32 range_length, 109 OMX_U32 flags, OMX_TICKS timestamp); 110 111 virtual status_t getExtensionIndex( 112 node_id node, 113 const char *parameter_name, 114 OMX_INDEXTYPE *index); 115 116 private: 117 mutable Mutex mLock; 118 119 sp<IOMX> mRemoteOMX; 120 sp<IOMX> mLocalOMX; 121 122 KeyedVector<node_id, bool> mIsLocalNode; 123 124 bool isLocalNode(node_id node) const; 125 bool isLocalNode_l(node_id node) const; 126 const sp<IOMX> &getOMX(node_id node) const; 127 const sp<IOMX> &getOMX_l(node_id node) const; 128 129 static bool IsSoftwareComponent(const char *name); 130 131 DISALLOW_EVIL_CONSTRUCTORS(MuxOMX); 132 }; 133 134 MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX) 135 : mRemoteOMX(remoteOMX) { 136 } 137 138 MuxOMX::~MuxOMX() { 139 } 140 141 bool MuxOMX::isLocalNode(node_id node) const { 142 Mutex::Autolock autoLock(mLock); 143 144 return isLocalNode_l(node); 145 } 146 147 bool MuxOMX::isLocalNode_l(node_id node) const { 148 return mIsLocalNode.indexOfKey(node) >= 0; 149 } 150 151 // static 152 bool MuxOMX::IsSoftwareComponent(const char *name) { 153 return !strncasecmp(name, "OMX.google.", 11); 154 } 155 156 const sp<IOMX> &MuxOMX::getOMX(node_id node) const { 157 return isLocalNode(node) ? mLocalOMX : mRemoteOMX; 158 } 159 160 const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const { 161 return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX; 162 } 163 164 bool MuxOMX::livesLocally(node_id node, pid_t pid) { 165 return getOMX(node)->livesLocally(node, pid); 166 } 167 168 status_t MuxOMX::listNodes(List<ComponentInfo> *list) { 169 Mutex::Autolock autoLock(mLock); 170 171 if (mLocalOMX == NULL) { 172 mLocalOMX = new OMX; 173 } 174 175 return mLocalOMX->listNodes(list); 176 } 177 178 status_t MuxOMX::allocateNode( 179 const char *name, const sp<IOMXObserver> &observer, 180 node_id *node) { 181 Mutex::Autolock autoLock(mLock); 182 183 sp<IOMX> omx; 184 185 if (IsSoftwareComponent(name)) { 186 if (mLocalOMX == NULL) { 187 mLocalOMX = new OMX; 188 } 189 omx = mLocalOMX; 190 } else { 191 omx = mRemoteOMX; 192 } 193 194 status_t err = omx->allocateNode(name, observer, node); 195 196 if (err != OK) { 197 return err; 198 } 199 200 if (omx == mLocalOMX) { 201 mIsLocalNode.add(*node, true); 202 } 203 204 return OK; 205 } 206 207 status_t MuxOMX::freeNode(node_id node) { 208 Mutex::Autolock autoLock(mLock); 209 210 status_t err = getOMX_l(node)->freeNode(node); 211 212 if (err != OK) { 213 return err; 214 } 215 216 mIsLocalNode.removeItem(node); 217 218 return OK; 219 } 220 221 status_t MuxOMX::sendCommand( 222 node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) { 223 return getOMX(node)->sendCommand(node, cmd, param); 224 } 225 226 status_t MuxOMX::getParameter( 227 node_id node, OMX_INDEXTYPE index, 228 void *params, size_t size) { 229 return getOMX(node)->getParameter(node, index, params, size); 230 } 231 232 status_t MuxOMX::setParameter( 233 node_id node, OMX_INDEXTYPE index, 234 const void *params, size_t size) { 235 return getOMX(node)->setParameter(node, index, params, size); 236 } 237 238 status_t MuxOMX::getConfig( 239 node_id node, OMX_INDEXTYPE index, 240 void *params, size_t size) { 241 return getOMX(node)->getConfig(node, index, params, size); 242 } 243 244 status_t MuxOMX::setConfig( 245 node_id node, OMX_INDEXTYPE index, 246 const void *params, size_t size) { 247 return getOMX(node)->setConfig(node, index, params, size); 248 } 249 250 status_t MuxOMX::getState( 251 node_id node, OMX_STATETYPE* state) { 252 return getOMX(node)->getState(node, state); 253 } 254 255 status_t MuxOMX::storeMetaDataInBuffers( 256 node_id node, OMX_U32 port_index, OMX_BOOL enable) { 257 return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable); 258 } 259 260 status_t MuxOMX::enableGraphicBuffers( 261 node_id node, OMX_U32 port_index, OMX_BOOL enable) { 262 return getOMX(node)->enableGraphicBuffers(node, port_index, enable); 263 } 264 265 status_t MuxOMX::getGraphicBufferUsage( 266 node_id node, OMX_U32 port_index, OMX_U32* usage) { 267 return getOMX(node)->getGraphicBufferUsage(node, port_index, usage); 268 } 269 270 status_t MuxOMX::useBuffer( 271 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 272 buffer_id *buffer) { 273 return getOMX(node)->useBuffer(node, port_index, params, buffer); 274 } 275 276 status_t MuxOMX::useGraphicBuffer( 277 node_id node, OMX_U32 port_index, 278 const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) { 279 return getOMX(node)->useGraphicBuffer( 280 node, port_index, graphicBuffer, buffer); 281 } 282 283 status_t MuxOMX::createInputSurface( 284 node_id node, OMX_U32 port_index, 285 sp<IGraphicBufferProducer> *bufferProducer) { 286 status_t err = getOMX(node)->createInputSurface( 287 node, port_index, bufferProducer); 288 return err; 289 } 290 291 status_t MuxOMX::signalEndOfInputStream(node_id node) { 292 return getOMX(node)->signalEndOfInputStream(node); 293 } 294 295 status_t MuxOMX::allocateBuffer( 296 node_id node, OMX_U32 port_index, size_t size, 297 buffer_id *buffer, void **buffer_data) { 298 return getOMX(node)->allocateBuffer( 299 node, port_index, size, buffer, buffer_data); 300 } 301 302 status_t MuxOMX::allocateBufferWithBackup( 303 node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms, 304 buffer_id *buffer) { 305 return getOMX(node)->allocateBufferWithBackup( 306 node, port_index, params, buffer); 307 } 308 309 status_t MuxOMX::freeBuffer( 310 node_id node, OMX_U32 port_index, buffer_id buffer) { 311 return getOMX(node)->freeBuffer(node, port_index, buffer); 312 } 313 314 status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer) { 315 return getOMX(node)->fillBuffer(node, buffer); 316 } 317 318 status_t MuxOMX::emptyBuffer( 319 node_id node, 320 buffer_id buffer, 321 OMX_U32 range_offset, OMX_U32 range_length, 322 OMX_U32 flags, OMX_TICKS timestamp) { 323 return getOMX(node)->emptyBuffer( 324 node, buffer, range_offset, range_length, flags, timestamp); 325 } 326 327 status_t MuxOMX::getExtensionIndex( 328 node_id node, 329 const char *parameter_name, 330 OMX_INDEXTYPE *index) { 331 return getOMX(node)->getExtensionIndex(node, parameter_name, index); 332 } 333 334 OMXClient::OMXClient() { 335 } 336 337 status_t OMXClient::connect() { 338 sp<IServiceManager> sm = defaultServiceManager(); 339 sp<IBinder> binder = sm->getService(String16("media.player")); 340 sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); 341 342 CHECK(service.get() != NULL); 343 344 mOMX = service->getOMX(); 345 CHECK(mOMX.get() != NULL); 346 347 if (!mOMX->livesLocally(NULL /* node */, getpid())) { 348 ALOGI("Using client-side OMX mux."); 349 mOMX = new MuxOMX(mOMX); 350 } 351 352 return OK; 353 } 354 355 void OMXClient::disconnect() { 356 if (mOMX.get() != NULL) { 357 mOMX.clear(); 358 mOMX = NULL; 359 } 360 } 361 362 } // namespace android 363