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/DataSource.h>
     24 #include <media/stagefright/FileSource.h>
     25 #include <media/stagefright/foundation/ADebug.h>
     26 #include <utils/Errors.h>
     27 #include <utils/misc.h>
     28 #include <../libstagefright/include/WVMExtractor.h>
     29 
     30 #include "MediaPlayerFactory.h"
     31 
     32 #include "MidiFile.h"
     33 #include "TestPlayerStub.h"
     34 #include "StagefrightPlayer.h"
     35 #include "nuplayer/NuPlayerDriver.h"
     36 
     37 namespace android {
     38 
     39 Mutex MediaPlayerFactory::sLock;
     40 MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
     41 bool MediaPlayerFactory::sInitComplete = false;
     42 
     43 status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
     44                                                player_type type) {
     45     if (NULL == factory) {
     46         ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
     47               " NULL.", type);
     48         return BAD_VALUE;
     49     }
     50 
     51     if (sFactoryMap.indexOfKey(type) >= 0) {
     52         ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
     53               " already registered.", type);
     54         return ALREADY_EXISTS;
     55     }
     56 
     57     if (sFactoryMap.add(type, factory) < 0) {
     58         ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
     59               " to map.", type);
     60         return UNKNOWN_ERROR;
     61     }
     62 
     63     return OK;
     64 }
     65 
     66 static player_type getDefaultPlayerType() {
     67     char value[PROPERTY_VALUE_MAX];
     68     if (property_get("media.stagefright.use-awesome", value, NULL)
     69             && (!strcmp("1", value) || !strcasecmp("true", value))) {
     70         return STAGEFRIGHT_PLAYER;
     71     }
     72 
     73     // TODO: remove this EXPERIMENTAL developer settings property
     74     if (property_get("persist.sys.media.use-awesome", value, NULL)
     75             && !strcasecmp("true", value)) {
     76         return STAGEFRIGHT_PLAYER;
     77     }
     78 
     79     return NU_PLAYER;
     80 }
     81 
     82 status_t MediaPlayerFactory::registerFactory(IFactory* factory,
     83                                              player_type type) {
     84     Mutex::Autolock lock_(&sLock);
     85     return registerFactory_l(factory, type);
     86 }
     87 
     88 void MediaPlayerFactory::unregisterFactory(player_type type) {
     89     Mutex::Autolock lock_(&sLock);
     90     sFactoryMap.removeItem(type);
     91 }
     92 
     93 #define GET_PLAYER_TYPE_IMPL(a...)                      \
     94     Mutex::Autolock lock_(&sLock);                      \
     95                                                         \
     96     player_type ret = STAGEFRIGHT_PLAYER;               \
     97     float bestScore = 0.0;                              \
     98                                                         \
     99     for (size_t i = 0; i < sFactoryMap.size(); ++i) {   \
    100                                                         \
    101         IFactory* v = sFactoryMap.valueAt(i);           \
    102         float thisScore;                                \
    103         CHECK(v != NULL);                               \
    104         thisScore = v->scoreFactory(a, bestScore);      \
    105         if (thisScore > bestScore) {                    \
    106             ret = sFactoryMap.keyAt(i);                 \
    107             bestScore = thisScore;                      \
    108         }                                               \
    109     }                                                   \
    110                                                         \
    111     if (0.0 == bestScore) {                             \
    112         ret = getDefaultPlayerType();                   \
    113     }                                                   \
    114                                                         \
    115     return ret;
    116 
    117 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
    118                                               const char* url) {
    119     GET_PLAYER_TYPE_IMPL(client, url);
    120 }
    121 
    122 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
    123                                               int fd,
    124                                               int64_t offset,
    125                                               int64_t length) {
    126     GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
    127 }
    128 
    129 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
    130                                               const sp<IStreamSource> &source) {
    131     GET_PLAYER_TYPE_IMPL(client, source);
    132 }
    133 
    134 #undef GET_PLAYER_TYPE_IMPL
    135 
    136 sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
    137         player_type playerType,
    138         void* cookie,
    139         notify_callback_f notifyFunc) {
    140     sp<MediaPlayerBase> p;
    141     IFactory* factory;
    142     status_t init_result;
    143     Mutex::Autolock lock_(&sLock);
    144 
    145     if (sFactoryMap.indexOfKey(playerType) < 0) {
    146         ALOGE("Failed to create player object of type %d, no registered"
    147               " factory", playerType);
    148         return p;
    149     }
    150 
    151     factory = sFactoryMap.valueFor(playerType);
    152     CHECK(NULL != factory);
    153     p = factory->createPlayer();
    154 
    155     if (p == NULL) {
    156         ALOGE("Failed to create player object of type %d, create failed",
    157                playerType);
    158         return p;
    159     }
    160 
    161     init_result = p->initCheck();
    162     if (init_result == NO_ERROR) {
    163         p->setNotifyCallback(cookie, notifyFunc);
    164     } else {
    165         ALOGE("Failed to create player object of type %d, initCheck failed"
    166               " (res = %d)", playerType, init_result);
    167         p.clear();
    168     }
    169 
    170     return p;
    171 }
    172 
    173 /*****************************************************************************
    174  *                                                                           *
    175  *                     Built-In Factory Implementations                      *
    176  *                                                                           *
    177  *****************************************************************************/
    178 
    179 class StagefrightPlayerFactory :
    180     public MediaPlayerFactory::IFactory {
    181   public:
    182     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
    183                                int fd,
    184                                int64_t offset,
    185                                int64_t length,
    186                                float /*curScore*/) {
    187         if (legacyDrm()) {
    188             sp<DataSource> source = new FileSource(dup(fd), offset, length);
    189             String8 mimeType;
    190             float confidence;
    191             if (SniffWVM(source, &mimeType, &confidence, NULL /* format */)) {
    192                 return 1.0;
    193             }
    194         }
    195 
    196         if (getDefaultPlayerType() == STAGEFRIGHT_PLAYER) {
    197             char buf[20];
    198             lseek(fd, offset, SEEK_SET);
    199             read(fd, buf, sizeof(buf));
    200             lseek(fd, offset, SEEK_SET);
    201 
    202             uint32_t ident = *((uint32_t*)buf);
    203 
    204             // Ogg vorbis?
    205             if (ident == 0x5367674f) // 'OggS'
    206                 return 1.0;
    207         }
    208 
    209         return 0.0;
    210     }
    211 
    212     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
    213                                const char* url,
    214                                float /*curScore*/) {
    215         if (legacyDrm() && !strncasecmp("widevine://", url, 11)) {
    216             return 1.0;
    217         }
    218         return 0.0;
    219     }
    220 
    221     virtual sp<MediaPlayerBase> createPlayer() {
    222         ALOGV(" create StagefrightPlayer");
    223         return new StagefrightPlayer();
    224     }
    225   private:
    226     bool legacyDrm() {
    227         char value[PROPERTY_VALUE_MAX];
    228         if (property_get("persist.sys.media.legacy-drm", value, NULL)
    229                 && (!strcmp("1", value) || !strcasecmp("true", value))) {
    230             return true;
    231         }
    232         return false;
    233     }
    234 };
    235 
    236 class NuPlayerFactory : public MediaPlayerFactory::IFactory {
    237   public:
    238     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
    239                                const char* url,
    240                                float curScore) {
    241         static const float kOurScore = 0.8;
    242 
    243         if (kOurScore <= curScore)
    244             return 0.0;
    245 
    246         if (!strncasecmp("http://", url, 7)
    247                 || !strncasecmp("https://", url, 8)
    248                 || !strncasecmp("file://", url, 7)) {
    249             size_t len = strlen(url);
    250             if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
    251                 return kOurScore;
    252             }
    253 
    254             if (strstr(url,"m3u8")) {
    255                 return kOurScore;
    256             }
    257 
    258             if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
    259                 return kOurScore;
    260             }
    261         }
    262 
    263         if (!strncasecmp("rtsp://", url, 7)) {
    264             return kOurScore;
    265         }
    266 
    267         return 0.0;
    268     }
    269 
    270     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
    271                                const sp<IStreamSource>& /*source*/,
    272                                float /*curScore*/) {
    273         return 1.0;
    274     }
    275 
    276     virtual sp<MediaPlayerBase> createPlayer() {
    277         ALOGV(" create NuPlayer");
    278         return new NuPlayerDriver;
    279     }
    280 };
    281 
    282 class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
    283   public:
    284     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
    285                                const char* url,
    286                                float curScore) {
    287         static const float kOurScore = 0.4;
    288         static const char* const FILE_EXTS[] = { ".mid",
    289                                                  ".midi",
    290                                                  ".smf",
    291                                                  ".xmf",
    292                                                  ".mxmf",
    293                                                  ".imy",
    294                                                  ".rtttl",
    295                                                  ".rtx",
    296                                                  ".ota" };
    297         if (kOurScore <= curScore)
    298             return 0.0;
    299 
    300         // use MidiFile for MIDI extensions
    301         int lenURL = strlen(url);
    302         for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
    303             int len = strlen(FILE_EXTS[i]);
    304             int start = lenURL - len;
    305             if (start > 0) {
    306                 if (!strncasecmp(url + start, FILE_EXTS[i], len)) {
    307                     return kOurScore;
    308                 }
    309             }
    310         }
    311 
    312         return 0.0;
    313     }
    314 
    315     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
    316                                int fd,
    317                                int64_t offset,
    318                                int64_t length,
    319                                float curScore) {
    320         static const float kOurScore = 0.8;
    321 
    322         if (kOurScore <= curScore)
    323             return 0.0;
    324 
    325         // Some kind of MIDI?
    326         EAS_DATA_HANDLE easdata;
    327         if (EAS_Init(&easdata) == EAS_SUCCESS) {
    328             EAS_FILE locator;
    329             locator.path = NULL;
    330             locator.fd = fd;
    331             locator.offset = offset;
    332             locator.length = length;
    333             EAS_HANDLE  eashandle;
    334             if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
    335                 EAS_CloseFile(easdata, eashandle);
    336                 EAS_Shutdown(easdata);
    337                 return kOurScore;
    338             }
    339             EAS_Shutdown(easdata);
    340         }
    341 
    342         return 0.0;
    343     }
    344 
    345     virtual sp<MediaPlayerBase> createPlayer() {
    346         ALOGV(" create MidiFile");
    347         return new MidiFile();
    348     }
    349 };
    350 
    351 class TestPlayerFactory : public MediaPlayerFactory::IFactory {
    352   public:
    353     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
    354                                const char* url,
    355                                float /*curScore*/) {
    356         if (TestPlayerStub::canBeUsed(url)) {
    357             return 1.0;
    358         }
    359 
    360         return 0.0;
    361     }
    362 
    363     virtual sp<MediaPlayerBase> createPlayer() {
    364         ALOGV("Create Test Player stub");
    365         return new TestPlayerStub();
    366     }
    367 };
    368 
    369 void MediaPlayerFactory::registerBuiltinFactories() {
    370     Mutex::Autolock lock_(&sLock);
    371 
    372     if (sInitComplete)
    373         return;
    374 
    375     registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
    376     registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
    377     registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
    378     registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
    379 
    380     sInitComplete = true;
    381 }
    382 
    383 }  // namespace android
    384