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