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