Home | History | Annotate | Download | only in libstagefright
      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 prepareForAdaptivePlayback(
     73             node_id node, OMX_U32 port_index, OMX_BOOL enable,
     74             OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight);
     75 
     76     virtual status_t enableGraphicBuffers(
     77             node_id node, OMX_U32 port_index, OMX_BOOL enable);
     78 
     79     virtual status_t getGraphicBufferUsage(
     80             node_id node, OMX_U32 port_index, OMX_U32* usage);
     81 
     82     virtual status_t useBuffer(
     83             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
     84             buffer_id *buffer);
     85 
     86     virtual status_t useGraphicBuffer(
     87             node_id node, OMX_U32 port_index,
     88             const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer);
     89 
     90     virtual status_t updateGraphicBufferInMeta(
     91             node_id node, OMX_U32 port_index,
     92             const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer);
     93 
     94     virtual status_t createInputSurface(
     95             node_id node, OMX_U32 port_index,
     96             sp<IGraphicBufferProducer> *bufferProducer);
     97 
     98     virtual status_t signalEndOfInputStream(node_id node);
     99 
    100     virtual status_t allocateBuffer(
    101             node_id node, OMX_U32 port_index, size_t size,
    102             buffer_id *buffer, void **buffer_data);
    103 
    104     virtual status_t allocateBufferWithBackup(
    105             node_id node, OMX_U32 port_index, const sp<IMemory> &params,
    106             buffer_id *buffer);
    107 
    108     virtual status_t freeBuffer(
    109             node_id node, OMX_U32 port_index, buffer_id buffer);
    110 
    111     virtual status_t fillBuffer(node_id node, buffer_id buffer);
    112 
    113     virtual status_t emptyBuffer(
    114             node_id node,
    115             buffer_id buffer,
    116             OMX_U32 range_offset, OMX_U32 range_length,
    117             OMX_U32 flags, OMX_TICKS timestamp);
    118 
    119     virtual status_t getExtensionIndex(
    120             node_id node,
    121             const char *parameter_name,
    122             OMX_INDEXTYPE *index);
    123 
    124     virtual status_t setInternalOption(
    125             node_id node,
    126             OMX_U32 port_index,
    127             InternalOptionType type,
    128             const void *data,
    129             size_t size);
    130 
    131 private:
    132     mutable Mutex mLock;
    133 
    134     sp<IOMX> mRemoteOMX;
    135     sp<IOMX> mLocalOMX;
    136 
    137     KeyedVector<node_id, bool> mIsLocalNode;
    138 
    139     bool isLocalNode(node_id node) const;
    140     bool isLocalNode_l(node_id node) const;
    141     const sp<IOMX> &getOMX(node_id node) const;
    142     const sp<IOMX> &getOMX_l(node_id node) const;
    143 
    144     static bool IsSoftwareComponent(const char *name);
    145 
    146     DISALLOW_EVIL_CONSTRUCTORS(MuxOMX);
    147 };
    148 
    149 MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
    150     : mRemoteOMX(remoteOMX) {
    151 }
    152 
    153 MuxOMX::~MuxOMX() {
    154 }
    155 
    156 bool MuxOMX::isLocalNode(node_id node) const {
    157     Mutex::Autolock autoLock(mLock);
    158 
    159     return isLocalNode_l(node);
    160 }
    161 
    162 bool MuxOMX::isLocalNode_l(node_id node) const {
    163     return mIsLocalNode.indexOfKey(node) >= 0;
    164 }
    165 
    166 // static
    167 bool MuxOMX::IsSoftwareComponent(const char *name) {
    168     return !strncasecmp(name, "OMX.google.", 11);
    169 }
    170 
    171 const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
    172     return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
    173 }
    174 
    175 const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
    176     return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
    177 }
    178 
    179 bool MuxOMX::livesLocally(node_id node, pid_t pid) {
    180     return getOMX(node)->livesLocally(node, pid);
    181 }
    182 
    183 status_t MuxOMX::listNodes(List<ComponentInfo> *list) {
    184     Mutex::Autolock autoLock(mLock);
    185 
    186     if (mLocalOMX == NULL) {
    187         mLocalOMX = new OMX;
    188     }
    189 
    190     return mLocalOMX->listNodes(list);
    191 }
    192 
    193 status_t MuxOMX::allocateNode(
    194         const char *name, const sp<IOMXObserver> &observer,
    195         node_id *node) {
    196     Mutex::Autolock autoLock(mLock);
    197 
    198     sp<IOMX> omx;
    199 
    200     if (IsSoftwareComponent(name)) {
    201         if (mLocalOMX == NULL) {
    202             mLocalOMX = new OMX;
    203         }
    204         omx = mLocalOMX;
    205     } else {
    206         omx = mRemoteOMX;
    207     }
    208 
    209     status_t err = omx->allocateNode(name, observer, node);
    210 
    211     if (err != OK) {
    212         return err;
    213     }
    214 
    215     if (omx == mLocalOMX) {
    216         mIsLocalNode.add(*node, true);
    217     }
    218 
    219     return OK;
    220 }
    221 
    222 status_t MuxOMX::freeNode(node_id node) {
    223     Mutex::Autolock autoLock(mLock);
    224 
    225     status_t err = getOMX_l(node)->freeNode(node);
    226 
    227     if (err != OK) {
    228         return err;
    229     }
    230 
    231     mIsLocalNode.removeItem(node);
    232 
    233     return OK;
    234 }
    235 
    236 status_t MuxOMX::sendCommand(
    237         node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
    238     return getOMX(node)->sendCommand(node, cmd, param);
    239 }
    240 
    241 status_t MuxOMX::getParameter(
    242         node_id node, OMX_INDEXTYPE index,
    243         void *params, size_t size) {
    244     return getOMX(node)->getParameter(node, index, params, size);
    245 }
    246 
    247 status_t MuxOMX::setParameter(
    248         node_id node, OMX_INDEXTYPE index,
    249         const void *params, size_t size) {
    250     return getOMX(node)->setParameter(node, index, params, size);
    251 }
    252 
    253 status_t MuxOMX::getConfig(
    254         node_id node, OMX_INDEXTYPE index,
    255         void *params, size_t size) {
    256     return getOMX(node)->getConfig(node, index, params, size);
    257 }
    258 
    259 status_t MuxOMX::setConfig(
    260         node_id node, OMX_INDEXTYPE index,
    261         const void *params, size_t size) {
    262     return getOMX(node)->setConfig(node, index, params, size);
    263 }
    264 
    265 status_t MuxOMX::getState(
    266         node_id node, OMX_STATETYPE* state) {
    267     return getOMX(node)->getState(node, state);
    268 }
    269 
    270 status_t MuxOMX::storeMetaDataInBuffers(
    271         node_id node, OMX_U32 port_index, OMX_BOOL enable) {
    272     return getOMX(node)->storeMetaDataInBuffers(node, port_index, enable);
    273 }
    274 
    275 status_t MuxOMX::prepareForAdaptivePlayback(
    276         node_id node, OMX_U32 port_index, OMX_BOOL enable,
    277         OMX_U32 maxFrameWidth, OMX_U32 maxFrameHeight) {
    278     return getOMX(node)->prepareForAdaptivePlayback(
    279             node, port_index, enable, maxFrameWidth, maxFrameHeight);
    280 }
    281 
    282 status_t MuxOMX::enableGraphicBuffers(
    283         node_id node, OMX_U32 port_index, OMX_BOOL enable) {
    284     return getOMX(node)->enableGraphicBuffers(node, port_index, enable);
    285 }
    286 
    287 status_t MuxOMX::getGraphicBufferUsage(
    288         node_id node, OMX_U32 port_index, OMX_U32* usage) {
    289     return getOMX(node)->getGraphicBufferUsage(node, port_index, usage);
    290 }
    291 
    292 status_t MuxOMX::useBuffer(
    293         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
    294         buffer_id *buffer) {
    295     return getOMX(node)->useBuffer(node, port_index, params, buffer);
    296 }
    297 
    298 status_t MuxOMX::useGraphicBuffer(
    299         node_id node, OMX_U32 port_index,
    300         const sp<GraphicBuffer> &graphicBuffer, buffer_id *buffer) {
    301     return getOMX(node)->useGraphicBuffer(
    302             node, port_index, graphicBuffer, buffer);
    303 }
    304 
    305 status_t MuxOMX::updateGraphicBufferInMeta(
    306         node_id node, OMX_U32 port_index,
    307         const sp<GraphicBuffer> &graphicBuffer, buffer_id buffer) {
    308     return getOMX(node)->updateGraphicBufferInMeta(
    309             node, port_index, graphicBuffer, buffer);
    310 }
    311 
    312 status_t MuxOMX::createInputSurface(
    313         node_id node, OMX_U32 port_index,
    314         sp<IGraphicBufferProducer> *bufferProducer) {
    315     status_t err = getOMX(node)->createInputSurface(
    316             node, port_index, bufferProducer);
    317     return err;
    318 }
    319 
    320 status_t MuxOMX::signalEndOfInputStream(node_id node) {
    321     return getOMX(node)->signalEndOfInputStream(node);
    322 }
    323 
    324 status_t MuxOMX::allocateBuffer(
    325         node_id node, OMX_U32 port_index, size_t size,
    326         buffer_id *buffer, void **buffer_data) {
    327     return getOMX(node)->allocateBuffer(
    328             node, port_index, size, buffer, buffer_data);
    329 }
    330 
    331 status_t MuxOMX::allocateBufferWithBackup(
    332         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
    333         buffer_id *buffer) {
    334     return getOMX(node)->allocateBufferWithBackup(
    335             node, port_index, params, buffer);
    336 }
    337 
    338 status_t MuxOMX::freeBuffer(
    339         node_id node, OMX_U32 port_index, buffer_id buffer) {
    340     return getOMX(node)->freeBuffer(node, port_index, buffer);
    341 }
    342 
    343 status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer) {
    344     return getOMX(node)->fillBuffer(node, buffer);
    345 }
    346 
    347 status_t MuxOMX::emptyBuffer(
    348         node_id node,
    349         buffer_id buffer,
    350         OMX_U32 range_offset, OMX_U32 range_length,
    351         OMX_U32 flags, OMX_TICKS timestamp) {
    352     return getOMX(node)->emptyBuffer(
    353             node, buffer, range_offset, range_length, flags, timestamp);
    354 }
    355 
    356 status_t MuxOMX::getExtensionIndex(
    357         node_id node,
    358         const char *parameter_name,
    359         OMX_INDEXTYPE *index) {
    360     return getOMX(node)->getExtensionIndex(node, parameter_name, index);
    361 }
    362 
    363 status_t MuxOMX::setInternalOption(
    364         node_id node,
    365         OMX_U32 port_index,
    366         InternalOptionType type,
    367         const void *data,
    368         size_t size) {
    369     return getOMX(node)->setInternalOption(node, port_index, type, data, size);
    370 }
    371 
    372 OMXClient::OMXClient() {
    373 }
    374 
    375 status_t OMXClient::connect() {
    376     sp<IServiceManager> sm = defaultServiceManager();
    377     sp<IBinder> binder = sm->getService(String16("media.player"));
    378     sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
    379 
    380     CHECK(service.get() != NULL);
    381 
    382     mOMX = service->getOMX();
    383     CHECK(mOMX.get() != NULL);
    384 
    385     if (!mOMX->livesLocally(NULL /* node */, getpid())) {
    386         ALOGI("Using client-side OMX mux.");
    387         mOMX = new MuxOMX(mOMX);
    388     }
    389 
    390     return OK;
    391 }
    392 
    393 void OMXClient::disconnect() {
    394     if (mOMX.get() != NULL) {
    395         mOMX.clear();
    396         mOMX = NULL;
    397     }
    398 }
    399 
    400 }  // namespace android
    401