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