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