Home | History | Annotate | Download | only in libmediaplayerservice
      1 /*
      2 **
      3 ** Copyright 2012, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 #define LOG_TAG "MediaPlayerFactory"
     19 #include <utils/Log.h>
     20 
     21 #include <cutils/properties.h>
     22 #include <media/IMediaPlayer.h>
     23 #include <media/stagefright/foundation/ADebug.h>
     24 #include <utils/Errors.h>
     25 #include <utils/misc.h>
     26 
     27 #include "MediaPlayerFactory.h"
     28 
     29 #include "MidiFile.h"
     30 #include "TestPlayerStub.h"
     31 #include "StagefrightPlayer.h"
     32 #include "nuplayer/NuPlayerDriver.h"
     33 
     34 namespace android {
     35 
     36 Mutex MediaPlayerFactory::sLock;
     37 MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
     38 bool MediaPlayerFactory::sInitComplete = false;
     39 
     40 status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
     41                                                player_type type) {
     42     if (NULL == factory) {
     43         ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
     44               " NULL.", type);
     45         return BAD_VALUE;
     46     }
     47 
     48     if (sFactoryMap.indexOfKey(type) >= 0) {
     49         ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
     50               " already registered.", type);
     51         return ALREADY_EXISTS;
     52     }
     53 
     54     if (sFactoryMap.add(type, factory) < 0) {
     55         ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
     56               " to map.", type);
     57         return UNKNOWN_ERROR;
     58     }
     59 
     60     return OK;
     61 }
     62 
     63 player_type MediaPlayerFactory::getDefaultPlayerType() {
     64     char value[PROPERTY_VALUE_MAX];
     65     if (property_get("media.stagefright.use-nuplayer", value, NULL)
     66             && (!strcmp("1", value) || !strcasecmp("true", value))) {
     67         return NU_PLAYER;
     68     }
     69 
     70     return STAGEFRIGHT_PLAYER;
     71 }
     72 
     73 status_t MediaPlayerFactory::registerFactory(IFactory* factory,
     74                                              player_type type) {
     75     Mutex::Autolock lock_(&sLock);
     76     return registerFactory_l(factory, type);
     77 }
     78 
     79 void MediaPlayerFactory::unregisterFactory(player_type type) {
     80     Mutex::Autolock lock_(&sLock);
     81     sFactoryMap.removeItem(type);
     82 }
     83 
     84 #define GET_PLAYER_TYPE_IMPL(a...)                      \
     85     Mutex::Autolock lock_(&sLock);                      \
     86                                                         \
     87     player_type ret = STAGEFRIGHT_PLAYER;               \
     88     float bestScore = 0.0;                              \
     89                                                         \
     90     for (size_t i = 0; i < sFactoryMap.size(); ++i) {   \
     91                                                         \
     92         IFactory* v = sFactoryMap.valueAt(i);           \
     93         float thisScore;                                \
     94         CHECK(v != NULL);                               \
     95         thisScore = v->scoreFactory(a, bestScore);      \
     96         if (thisScore > bestScore) {                    \
     97             ret = sFactoryMap.keyAt(i);                 \
     98             bestScore = thisScore;                      \
     99         }                                               \
    100     }                                                   \
    101                                                         \
    102     if (0.0 == bestScore) {                             \
    103         ret = getDefaultPlayerType();                   \
    104     }                                                   \
    105                                                         \
    106     return ret;
    107 
    108 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
    109                                               const char* url) {
    110     GET_PLAYER_TYPE_IMPL(client, url);
    111 }
    112 
    113 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
    114                                               int fd,
    115                                               int64_t offset,
    116                                               int64_t length) {
    117     GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
    118 }
    119 
    120 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
    121                                               const sp<IStreamSource> &source) {
    122     GET_PLAYER_TYPE_IMPL(client, source);
    123 }
    124 
    125 #undef GET_PLAYER_TYPE_IMPL
    126 
    127 sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
    128         player_type playerType,
    129         void* cookie,
    130         notify_callback_f notifyFunc) {
    131     sp<MediaPlayerBase> p;
    132     IFactory* factory;
    133     status_t init_result;
    134     Mutex::Autolock lock_(&sLock);
    135 
    136     if (sFactoryMap.indexOfKey(playerType) < 0) {
    137         ALOGE("Failed to create player object of type %d, no registered"
    138               " factory", playerType);
    139         return p;
    140     }
    141 
    142     factory = sFactoryMap.valueFor(playerType);
    143     CHECK(NULL != factory);
    144     p = factory->createPlayer();
    145 
    146     if (p == NULL) {
    147         ALOGE("Failed to create player object of type %d, create failed",
    148                playerType);
    149         return p;
    150     }
    151 
    152     init_result = p->initCheck();
    153     if (init_result == NO_ERROR) {
    154         p->setNotifyCallback(cookie, notifyFunc);
    155     } else {
    156         ALOGE("Failed to create player object of type %d, initCheck failed"
    157               " (res = %d)", playerType, init_result);
    158         p.clear();
    159     }
    160 
    161     return p;
    162 }
    163 
    164 /*****************************************************************************
    165  *                                                                           *
    166  *                     Built-In Factory Implementations                      *
    167  *                                                                           *
    168  *****************************************************************************/
    169 
    170 class StagefrightPlayerFactory :
    171     public MediaPlayerFactory::IFactory {
    172   public:
    173     virtual float scoreFactory(const sp<IMediaPlayer>& client,
    174                                int fd,
    175                                int64_t offset,
    176                                int64_t length,
    177                                float curScore) {
    178         char buf[20];
    179         lseek(fd, offset, SEEK_SET);
    180         read(fd, buf, sizeof(buf));
    181         lseek(fd, offset, SEEK_SET);
    182 
    183         long ident = *((long*)buf);
    184 
    185         // Ogg vorbis?
    186         if (ident == 0x5367674f) // 'OggS'
    187             return 1.0;
    188 
    189         return 0.0;
    190     }
    191 
    192     virtual sp<MediaPlayerBase> createPlayer() {
    193         ALOGV(" create StagefrightPlayer");
    194         return new StagefrightPlayer();
    195     }
    196 };
    197 
    198 class NuPlayerFactory : public MediaPlayerFactory::IFactory {
    199   public:
    200     virtual float scoreFactory(const sp<IMediaPlayer>& client,
    201                                const char* url,
    202                                float curScore) {
    203         static const float kOurScore = 0.8;
    204 
    205         if (kOurScore <= curScore)
    206             return 0.0;
    207 
    208         if (!strncasecmp("http://", url, 7)
    209                 || !strncasecmp("https://", url, 8)
    210                 || !strncasecmp("file://", url, 7)) {
    211             size_t len = strlen(url);
    212             if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
    213                 return kOurScore;
    214             }
    215 
    216             if (strstr(url,"m3u8")) {
    217                 return kOurScore;
    218             }
    219 
    220             if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
    221                 return kOurScore;
    222             }
    223         }
    224 
    225         if (!strncasecmp("rtsp://", url, 7)) {
    226             return kOurScore;
    227         }
    228 
    229         return 0.0;
    230     }
    231 
    232     virtual float scoreFactory(const sp<IMediaPlayer>& client,
    233                                const sp<IStreamSource> &source,
    234                                float curScore) {
    235         return 1.0;
    236     }
    237 
    238     virtual sp<MediaPlayerBase> createPlayer() {
    239         ALOGV(" create NuPlayer");
    240         return new NuPlayerDriver;
    241     }
    242 };
    243 
    244 class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
    245   public:
    246     virtual float scoreFactory(const sp<IMediaPlayer>& client,
    247                                const char* url,
    248                                float curScore) {
    249         static const float kOurScore = 0.4;
    250         static const char* const FILE_EXTS[] = { ".mid",
    251                                                  ".midi",
    252                                                  ".smf",
    253                                                  ".xmf",
    254                                                  ".mxmf",
    255                                                  ".imy",
    256                                                  ".rtttl",
    257                                                  ".rtx",
    258                                                  ".ota" };
    259         if (kOurScore <= curScore)
    260             return 0.0;
    261 
    262         // use MidiFile for MIDI extensions
    263         int lenURL = strlen(url);
    264         for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
    265             int len = strlen(FILE_EXTS[i]);
    266             int start = lenURL - len;
    267             if (start > 0) {
    268                 if (!strncasecmp(url + start, FILE_EXTS[i], len)) {
    269                     return kOurScore;
    270                 }
    271             }
    272         }
    273 
    274         return 0.0;
    275     }
    276 
    277     virtual float scoreFactory(const sp<IMediaPlayer>& client,
    278                                int fd,
    279                                int64_t offset,
    280                                int64_t length,
    281                                float curScore) {
    282         static const float kOurScore = 0.8;
    283 
    284         if (kOurScore <= curScore)
    285             return 0.0;
    286 
    287         // Some kind of MIDI?
    288         EAS_DATA_HANDLE easdata;
    289         if (EAS_Init(&easdata) == EAS_SUCCESS) {
    290             EAS_FILE locator;
    291             locator.path = NULL;
    292             locator.fd = fd;
    293             locator.offset = offset;
    294             locator.length = length;
    295             EAS_HANDLE  eashandle;
    296             if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
    297                 EAS_CloseFile(easdata, eashandle);
    298                 EAS_Shutdown(easdata);
    299                 return kOurScore;
    300             }
    301             EAS_Shutdown(easdata);
    302         }
    303 
    304         return 0.0;
    305     }
    306 
    307     virtual sp<MediaPlayerBase> createPlayer() {
    308         ALOGV(" create MidiFile");
    309         return new MidiFile();
    310     }
    311 };
    312 
    313 class TestPlayerFactory : public MediaPlayerFactory::IFactory {
    314   public:
    315     virtual float scoreFactory(const sp<IMediaPlayer>& client,
    316                                const char* url,
    317                                float curScore) {
    318         if (TestPlayerStub::canBeUsed(url)) {
    319             return 1.0;
    320         }
    321 
    322         return 0.0;
    323     }
    324 
    325     virtual sp<MediaPlayerBase> createPlayer() {
    326         ALOGV("Create Test Player stub");
    327         return new TestPlayerStub();
    328     }
    329 };
    330 
    331 void MediaPlayerFactory::registerBuiltinFactories() {
    332     Mutex::Autolock lock_(&sLock);
    333 
    334     if (sInitComplete)
    335         return;
    336 
    337     registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
    338     registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
    339     registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
    340     registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
    341 
    342     sInitComplete = true;
    343 }
    344 
    345 }  // namespace android
    346