Andreas Huber | 20111aa | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 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 | |
Andreas Huber | 20111aa | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 21 | #include <binder/IServiceManager.h> |
| 22 | #include <media/IMediaPlayerService.h> |
Andreas Huber | e9c52da | 2012-01-30 11:48:02 -0800 | [diff] [blame] | 23 | #include <media/stagefright/foundation/ADebug.h> |
Andreas Huber | 20111aa | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 24 | #include <media/stagefright/OMXClient.h> |
Andreas Huber | e9c52da | 2012-01-30 11:48:02 -0800 | [diff] [blame] | 25 | #include <utils/KeyedVector.h> |
| 26 | |
| 27 | #include "include/OMX.h" |
Andreas Huber | 20111aa | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 28 | |
| 29 | namespace android { |
| 30 | |
Andreas Huber | e9c52da | 2012-01-30 11:48:02 -0800 | [diff] [blame] | 31 | struct MuxOMX : public IOMX { |
| 32 | MuxOMX(const sp<IOMX> &remoteOMX); |
| 33 | virtual ~MuxOMX(); |
| 34 | |
| 35 | virtual IBinder *onAsBinder() { return NULL; } |
| 36 | |
Andreas Huber | d459b48 | 2012-01-31 11:16:24 -0800 | [diff] [blame] | 37 | virtual bool livesLocally(node_id node, pid_t pid); |
Andreas Huber | e9c52da | 2012-01-30 11:48:02 -0800 | [diff] [blame] | 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 | |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 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 | |
Andreas Huber | e9c52da | 2012-01-30 11:48:02 -0800 | [diff] [blame] | 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 | |
Andreas Huber | d459b48 | 2012-01-31 11:16:24 -0800 | [diff] [blame] | 164 | bool MuxOMX::livesLocally(node_id node, pid_t pid) { |
| 165 | return getOMX(node)->livesLocally(node, pid); |
Andreas Huber | e9c52da | 2012-01-30 11:48:02 -0800 | [diff] [blame] | 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 | |
Andy McFadden | f779bb5 | 2013-02-19 07:28:30 -0800 | [diff] [blame] | 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 | |
Andreas Huber | e9c52da | 2012-01-30 11:48:02 -0800 | [diff] [blame] | 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 | |
Andreas Huber | 408b8e1 | 2009-08-07 13:45:06 -0700 | [diff] [blame] | 334 | OMXClient::OMXClient() { |
Andreas Huber | 20111aa | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 335 | } |
| 336 | |
Andreas Huber | 20111aa | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 337 | status_t OMXClient::connect() { |
Andreas Huber | 20111aa | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 338 | sp<IServiceManager> sm = defaultServiceManager(); |
| 339 | sp<IBinder> binder = sm->getService(String16("media.player")); |
| 340 | sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); |
| 341 | |
Andreas Huber | 0c89199 | 2009-08-26 14:48:20 -0700 | [diff] [blame] | 342 | CHECK(service.get() != NULL); |
Andreas Huber | 20111aa | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 343 | |
Andreas Huber | 318ad9c | 2009-10-15 13:46:54 -0700 | [diff] [blame] | 344 | mOMX = service->getOMX(); |
Andreas Huber | 0c89199 | 2009-08-26 14:48:20 -0700 | [diff] [blame] | 345 | CHECK(mOMX.get() != NULL); |
Andreas Huber | 20111aa | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 346 | |
Andreas Huber | d459b48 | 2012-01-31 11:16:24 -0800 | [diff] [blame] | 347 | if (!mOMX->livesLocally(NULL /* node */, getpid())) { |
Andreas Huber | e9c52da | 2012-01-30 11:48:02 -0800 | [diff] [blame] | 348 | ALOGI("Using client-side OMX mux."); |
| 349 | mOMX = new MuxOMX(mOMX); |
| 350 | } |
| 351 | |
Andreas Huber | 20111aa | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 352 | return OK; |
| 353 | } |
| 354 | |
| 355 | void OMXClient::disconnect() { |
James Dong | 04394b1 | 2012-02-23 12:23:57 -0800 | [diff] [blame] | 356 | if (mOMX.get() != NULL) { |
| 357 | mOMX.clear(); |
| 358 | mOMX = NULL; |
| 359 | } |
Andreas Huber | 20111aa | 2009-07-14 16:56:47 -0700 | [diff] [blame] | 360 | } |
| 361 | |
| 362 | } // namespace android |