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