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