1bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber/* 2bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Copyright (C) 2011 The Android Open Source Project 3bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * 4bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 5bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * you may not use this file except in compliance with the License. 6bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * You may obtain a copy of the License at 7bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * 8bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 9bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * 10bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Unless required by applicable law or agreed to in writing, software 11bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 12bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * See the License for the specific language governing permissions and 14bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * limitations under the License. 15bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber */ 16bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 17bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber//#define LOG_NDEBUG 0 18bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#define LOG_TAG "SoftOMXPlugin" 19bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <utils/Log.h> 20bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 21255735a38b9d5c3755c7b819bdc8fdaf4357d860Pawin Vongmasa#include <media/stagefright/omx/SoftOMXPlugin.h> 22255735a38b9d5c3755c7b819bdc8fdaf4357d860Pawin Vongmasa#include <media/stagefright/omx/SoftOMXComponent.h> 23bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 24f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber#include <media/stagefright/foundation/ADebug.h> 25bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <media/stagefright/foundation/AString.h> 26bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 27bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <dlfcn.h> 28bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 29bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubernamespace android { 30bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 31bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberstatic const struct { 32bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const char *mName; 33bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const char *mLibNameSuffix; 34bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const char *mRole; 35bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 36bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} kComponents[] = { 37234b6925a27d5e846068a89c56de8cba8ab7f294Ray Essick // two choices for aac decoding. 38234b6925a27d5e846068a89c56de8cba8ab7f294Ray Essick // configurable in media/libstagefright/data/media_codecs_google_audio.xml 39234b6925a27d5e846068a89c56de8cba8ab7f294Ray Essick // default implementation 40bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber { "OMX.google.aac.decoder", "aacdec", "audio_decoder.aac" }, 41234b6925a27d5e846068a89c56de8cba8ab7f294Ray Essick // alternate implementation 42234b6925a27d5e846068a89c56de8cba8ab7f294Ray Essick { "OMX.google.xaac.decoder", "xaacdec", "audio_decoder.aac" }, 432b1892db4a2ab47bfc09e59a4c11751aea99e4eaAndreas Huber { "OMX.google.aac.encoder", "aacenc", "audio_encoder.aac" }, 44bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber { "OMX.google.amrnb.decoder", "amrdec", "audio_decoder.amrnb" }, 45252353088a5ebf8508fbc01439ff417805ef1417Andreas Huber { "OMX.google.amrnb.encoder", "amrnbenc", "audio_encoder.amrnb" }, 46bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber { "OMX.google.amrwb.decoder", "amrdec", "audio_decoder.amrwb" }, 4783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber { "OMX.google.amrwb.encoder", "amrwbenc", "audio_encoder.amrwb" }, 48e5b9b3db87a55d3430f881ba59ba95f7d6ae41d0Venkatarama Avadhani { "OMX.google.h264.decoder", "avcdec", "video_decoder.avc" }, 4922b3b44ae459974794403ed0f76d95ae43d92985Venkatarama Avadhani { "OMX.google.h264.encoder", "avcenc", "video_encoder.avc" }, 503b5a6b9fa6c6825a1d0b441429e2bb365b259827Harish Mahendrakar { "OMX.google.hevc.decoder", "hevcdec", "video_decoder.hevc" }, 51bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber { "OMX.google.g711.alaw.decoder", "g711dec", "audio_decoder.g711alaw" }, 52bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber { "OMX.google.g711.mlaw.decoder", "g711dec", "audio_decoder.g711mlaw" }, 538f9d9d06ed6c8447c7fd02745b2a22dd4bba8e7eVenkatarama Avadhani { "OMX.google.mpeg2.decoder", "mpeg2dec", "video_decoder.mpeg2" }, 54bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber { "OMX.google.h263.decoder", "mpeg4dec", "video_decoder.h263" }, 551700744ae0ce2fcf722816453ae0af2cd5646458James Dong { "OMX.google.h263.encoder", "mpeg4enc", "video_encoder.h263" }, 56bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber { "OMX.google.mpeg4.decoder", "mpeg4dec", "video_decoder.mpeg4" }, 571700744ae0ce2fcf722816453ae0af2cd5646458James Dong { "OMX.google.mpeg4.encoder", "mpeg4enc", "video_encoder.mpeg4" }, 58bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber { "OMX.google.mp3.decoder", "mp3dec", "audio_decoder.mp3" }, 59bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber { "OMX.google.vorbis.decoder", "vorbisdec", "audio_decoder.vorbis" }, 60bf927f8ec7979f2b64331c2b2f12a6a5dba05bcaVignesh Venkatasubramanian { "OMX.google.opus.decoder", "opusdec", "audio_decoder.opus" }, 6194705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang { "OMX.google.vp8.decoder", "vpxdec", "video_decoder.vp8" }, 6294705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang { "OMX.google.vp9.decoder", "vpxdec", "video_decoder.vp9" }, 6394705aff3c9eef58cbb72ec6fe5d2dcfd9481646hkuang { "OMX.google.vp8.encoder", "vpxenc", "video_encoder.vp8" }, 64328597abaecff9722dcfb4bb4c67964bd82a072aVignesh Venkatasubramanian { "OMX.google.vp9.encoder", "vpxenc", "video_encoder.vp9" }, 65ecdd39c5af016e2fa57cbfd837aa670b706dabd3Andreas Huber { "OMX.google.raw.decoder", "rawdec", "audio_decoder.raw" }, 66f2ddc43bf03b7a26d408e1b349b6b0c74dd6c0a3Wei Jia { "OMX.google.flac.decoder", "flacdec", "audio_decoder.flac" }, 672f74ef3cdc192f817ee1121f41765f0852c1d81eJean-Michel Trivi { "OMX.google.flac.encoder", "flacenc", "audio_encoder.flac" }, 68ba933df89521d63f75ca66af12ce9d7ae9496b9eMarco Nelissen { "OMX.google.gsm.decoder", "gsmdec", "audio_decoder.gsm" }, 69bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}; 70bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 71bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberstatic const size_t kNumComponents = 72bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber sizeof(kComponents) / sizeof(kComponents[0]); 73bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 74bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftOMXPlugin::SoftOMXPlugin() { 75bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 76bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 77bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberOMX_ERRORTYPE SoftOMXPlugin::makeComponentInstance( 78bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const char *name, 79bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const OMX_CALLBACKTYPE *callbacks, 80bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_PTR appData, 81bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_COMPONENTTYPE **component) { 823856b090cd04ba5dd4a59a12430ed724d5995909Steve Block ALOGV("makeComponentInstance '%s'", name); 83bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 84bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber for (size_t i = 0; i < kNumComponents; ++i) { 85bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber if (strcmp(name, kComponents[i].mName)) { 86bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber continue; 87bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 88bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 89bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber AString libName = "libstagefright_soft_"; 90bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber libName.append(kComponents[i].mLibNameSuffix); 91bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber libName.append(".so"); 92bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 9336cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // RTLD_NODELETE means we keep the shared library around forever. 9436cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // this eliminates thrashing during sequences like loading soundpools. 9536cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // It also leaves the rest of the logic around the dlopen()/dlclose() 9636cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // calls in this file unchanged. 9736cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // 9836cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // Implications of the change: 9936cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // -- the codec process (where this happens) will have a slightly larger 10036cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // long-term memory footprint as it accumulates the loaded shared libraries. 10136cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // This is expected to be a small amount of memory. 10236cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // -- plugin codecs can no longer (and never should have) depend on a 10336cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // free reset of any static data as the library would have crossed 10436cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // a dlclose/dlopen cycle. 10536cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick // 10636cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick 10736cc22b90543e5a11fe7eb202a81d563d970dbc8Ray Essick void *libHandle = dlopen(libName.c_str(), RTLD_NOW|RTLD_NODELETE); 108bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 109bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber if (libHandle == NULL) { 1106b4d13df54cb7eb605d259c5f3c4a37eb34857ccMarco Nelissen ALOGE("unable to dlopen %s: %s", libName.c_str(), dlerror()); 111bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 112bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return OMX_ErrorComponentNotFound; 113bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 114bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 115bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber typedef SoftOMXComponent *(*CreateSoftOMXComponentFunc)( 116bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const char *, const OMX_CALLBACKTYPE *, 117bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_PTR, OMX_COMPONENTTYPE **); 118bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 119bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber CreateSoftOMXComponentFunc createSoftOMXComponent = 120bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber (CreateSoftOMXComponentFunc)dlsym( 121bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber libHandle, 122bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber "_Z22createSoftOMXComponentPKcPK16OMX_CALLBACKTYPE" 123bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber "PvPP17OMX_COMPONENTTYPE"); 124bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 125bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber if (createSoftOMXComponent == NULL) { 126bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber dlclose(libHandle); 127bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber libHandle = NULL; 128bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 129bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return OMX_ErrorComponentNotFound; 130bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 131bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 132bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber sp<SoftOMXComponent> codec = 133bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber (*createSoftOMXComponent)(name, callbacks, appData, component); 134bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 135bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber if (codec == NULL) { 136bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber dlclose(libHandle); 137bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber libHandle = NULL; 138bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 139bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return OMX_ErrorInsufficientResources; 140bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 141bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 142bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_ERRORTYPE err = codec->initCheck(); 143bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber if (err != OMX_ErrorNone) { 144bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber dlclose(libHandle); 145bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber libHandle = NULL; 146bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 147bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return err; 148bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 149bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 150bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber codec->incStrong(this); 151bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber codec->setLibHandle(libHandle); 152bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 153bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return OMX_ErrorNone; 154bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 155bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 156bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return OMX_ErrorInvalidComponentName; 157bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 158bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 159bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberOMX_ERRORTYPE SoftOMXPlugin::destroyComponentInstance( 160bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_COMPONENTTYPE *component) { 161bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber SoftOMXComponent *me = 162bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber (SoftOMXComponent *) 163bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber ((OMX_COMPONENTTYPE *)component)->pComponentPrivate; 164bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 1655a65e30064dc8dffa4f3d868f1c46038972c40c5Andreas Huber me->prepareForDestruction(); 1665a65e30064dc8dffa4f3d868f1c46038972c40c5Andreas Huber 167bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber void *libHandle = me->libHandle(); 168bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 169f2af5a2c607e71ff4cd39da28b077c0a68b206feAndreas Huber CHECK_EQ(me->getStrongCount(), 1); 170bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber me->decStrong(this); 171bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber me = NULL; 172bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 173bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber dlclose(libHandle); 174bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber libHandle = NULL; 175bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 176bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return OMX_ErrorNone; 177bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 178bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 179bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberOMX_ERRORTYPE SoftOMXPlugin::enumerateComponents( 180bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_STRING name, 18184333e0475bc911adc16417f4ca327c975cf6c36Andreas Huber size_t /* size */, 182bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber OMX_U32 index) { 183bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber if (index >= kNumComponents) { 184bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return OMX_ErrorNoMore; 185bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 186bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 187bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber strcpy(name, kComponents[index].mName); 188bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 189bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return OMX_ErrorNone; 190bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 191bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 192bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberOMX_ERRORTYPE SoftOMXPlugin::getRolesOfComponent( 193bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber const char *name, 194bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber Vector<String8> *roles) { 195bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber for (size_t i = 0; i < kNumComponents; ++i) { 196bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber if (strcmp(name, kComponents[i].mName)) { 197bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber continue; 198bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 199bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 200bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber roles->clear(); 201bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber roles->push(String8(kComponents[i].mRole)); 202bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 203bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return OMX_ErrorNone; 204bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber } 205bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 206bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber return OMX_ErrorInvalidComponentName; 207bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} 208bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber 209bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber} // namespace android 210