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