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 
     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 
     34 namespace android {
     35 
     36 struct 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> &params,
     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> &params,
    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 
    140 private:
    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 
    158 MuxOMX::MuxOMX(const sp<IOMX> &remoteOMX)
    159     : mRemoteOMX(remoteOMX) {
    160 }
    161 
    162 MuxOMX::~MuxOMX() {
    163 }
    164 
    165 bool MuxOMX::isLocalNode(node_id node) const {
    166     Mutex::Autolock autoLock(mLock);
    167 
    168     return isLocalNode_l(node);
    169 }
    170 
    171 bool MuxOMX::isLocalNode_l(node_id node) const {
    172     return mIsLocalNode.indexOfKey(node) >= 0;
    173 }
    174 
    175 // static
    176 bool 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 
    187 const sp<IOMX> &MuxOMX::getOMX(node_id node) const {
    188     return isLocalNode(node) ? mLocalOMX : mRemoteOMX;
    189 }
    190 
    191 const sp<IOMX> &MuxOMX::getOMX_l(node_id node) const {
    192     return isLocalNode_l(node) ? mLocalOMX : mRemoteOMX;
    193 }
    194 
    195 bool MuxOMX::livesLocally(node_id node, pid_t pid) {
    196     return getOMX(node)->livesLocally(node, pid);
    197 }
    198 
    199 status_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 
    209 status_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 
    238 status_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 
    252 status_t MuxOMX::sendCommand(
    253         node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
    254     return getOMX(node)->sendCommand(node, cmd, param);
    255 }
    256 
    257 status_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 
    263 status_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 
    269 status_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 
    275 status_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 
    281 status_t MuxOMX::getState(
    282         node_id node, OMX_STATETYPE* state) {
    283     return getOMX(node)->getState(node, state);
    284 }
    285 
    286 status_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 
    291 status_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 
    298 status_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 
    305 status_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 
    310 status_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 
    315 status_t MuxOMX::useBuffer(
    316         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
    317         buffer_id *buffer) {
    318     return getOMX(node)->useBuffer(node, port_index, params, buffer);
    319 }
    320 
    321 status_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 
    328 status_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 
    335 status_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 
    343 status_t MuxOMX::signalEndOfInputStream(node_id node) {
    344     return getOMX(node)->signalEndOfInputStream(node);
    345 }
    346 
    347 status_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 
    354 status_t MuxOMX::allocateBufferWithBackup(
    355         node_id node, OMX_U32 port_index, const sp<IMemory> &params,
    356         buffer_id *buffer) {
    357     return getOMX(node)->allocateBufferWithBackup(
    358             node, port_index, params, buffer);
    359 }
    360 
    361 status_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 
    366 status_t MuxOMX::fillBuffer(node_id node, buffer_id buffer) {
    367     return getOMX(node)->fillBuffer(node, buffer);
    368 }
    369 
    370 status_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 
    379 status_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 
    386 status_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 
    395 OMXClient::OMXClient() {
    396 }
    397 
    398 status_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 
    416 void OMXClient::disconnect() {
    417     if (mOMX.get() != NULL) {
    418         mOMX.clear();
    419         mOMX = NULL;
    420     }
    421 }
    422 
    423 }  // namespace android
    424