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 30#include "MediaPlayerFactory.h" 31 32#include "TestPlayerStub.h" 33#include "nuplayer/NuPlayerDriver.h" 34 35namespace android { 36 37Mutex MediaPlayerFactory::sLock; 38MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap; 39bool MediaPlayerFactory::sInitComplete = false; 40 41status_t MediaPlayerFactory::registerFactory_l(IFactory* factory, 42 player_type type) { 43 if (NULL == factory) { 44 ALOGE("Failed to register MediaPlayerFactory of type %d, factory is" 45 " NULL.", type); 46 return BAD_VALUE; 47 } 48 49 if (sFactoryMap.indexOfKey(type) >= 0) { 50 ALOGE("Failed to register MediaPlayerFactory of type %d, type is" 51 " already registered.", type); 52 return ALREADY_EXISTS; 53 } 54 55 if (sFactoryMap.add(type, factory) < 0) { 56 ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add" 57 " to map.", type); 58 return UNKNOWN_ERROR; 59 } 60 61 return OK; 62} 63 64static player_type getDefaultPlayerType() { 65 return NU_PLAYER; 66} 67 68status_t MediaPlayerFactory::registerFactory(IFactory* factory, 69 player_type type) { 70 Mutex::Autolock lock_(&sLock); 71 return registerFactory_l(factory, type); 72} 73 74void MediaPlayerFactory::unregisterFactory(player_type type) { 75 Mutex::Autolock lock_(&sLock); 76 sFactoryMap.removeItem(type); 77} 78 79#define GET_PLAYER_TYPE_IMPL(a...) \ 80 Mutex::Autolock lock_(&sLock); \ 81 \ 82 player_type ret = STAGEFRIGHT_PLAYER; \ 83 float bestScore = 0.0; \ 84 \ 85 for (size_t i = 0; i < sFactoryMap.size(); ++i) { \ 86 \ 87 IFactory* v = sFactoryMap.valueAt(i); \ 88 float thisScore; \ 89 CHECK(v != NULL); \ 90 thisScore = v->scoreFactory(a, bestScore); \ 91 if (thisScore > bestScore) { \ 92 ret = sFactoryMap.keyAt(i); \ 93 bestScore = thisScore; \ 94 } \ 95 } \ 96 \ 97 if (0.0 == bestScore) { \ 98 ret = getDefaultPlayerType(); \ 99 } \ 100 \ 101 return ret; 102 103player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client, 104 const char* url) { 105 GET_PLAYER_TYPE_IMPL(client, url); 106} 107 108player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client, 109 int fd, 110 int64_t offset, 111 int64_t length) { 112 GET_PLAYER_TYPE_IMPL(client, fd, offset, length); 113} 114 115player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client, 116 const sp<IStreamSource> &source) { 117 GET_PLAYER_TYPE_IMPL(client, source); 118} 119 120player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client, 121 const sp<DataSource> &source) { 122 GET_PLAYER_TYPE_IMPL(client, source); 123} 124 125#undef GET_PLAYER_TYPE_IMPL 126 127sp<MediaPlayerBase> MediaPlayerFactory::createPlayer( 128 player_type playerType, 129 void* cookie, 130 notify_callback_f notifyFunc, 131 pid_t pid) { 132 sp<MediaPlayerBase> p; 133 IFactory* factory; 134 status_t init_result; 135 Mutex::Autolock lock_(&sLock); 136 137 if (sFactoryMap.indexOfKey(playerType) < 0) { 138 ALOGE("Failed to create player object of type %d, no registered" 139 " factory", playerType); 140 return p; 141 } 142 143 factory = sFactoryMap.valueFor(playerType); 144 CHECK(NULL != factory); 145 p = factory->createPlayer(pid); 146 147 if (p == NULL) { 148 ALOGE("Failed to create player object of type %d, create failed", 149 playerType); 150 return p; 151 } 152 153 init_result = p->initCheck(); 154 if (init_result == NO_ERROR) { 155 p->setNotifyCallback(cookie, notifyFunc); 156 } else { 157 ALOGE("Failed to create player object of type %d, initCheck failed" 158 " (res = %d)", playerType, init_result); 159 p.clear(); 160 } 161 162 return p; 163} 164 165/***************************************************************************** 166 * * 167 * Built-In Factory Implementations * 168 * * 169 *****************************************************************************/ 170 171class NuPlayerFactory : public MediaPlayerFactory::IFactory { 172 public: 173 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, 174 const char* url, 175 float curScore) { 176 static const float kOurScore = 0.8; 177 178 if (kOurScore <= curScore) 179 return 0.0; 180 181 if (!strncasecmp("http://", url, 7) 182 || !strncasecmp("https://", url, 8) 183 || !strncasecmp("file://", url, 7)) { 184 size_t len = strlen(url); 185 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) { 186 return kOurScore; 187 } 188 189 if (strstr(url,"m3u8")) { 190 return kOurScore; 191 } 192 193 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) { 194 return kOurScore; 195 } 196 } 197 198 if (!strncasecmp("rtsp://", url, 7)) { 199 return kOurScore; 200 } 201 202 return 0.0; 203 } 204 205 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, 206 const sp<IStreamSource>& /*source*/, 207 float /*curScore*/) { 208 return 1.0; 209 } 210 211 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, 212 const sp<DataSource>& /*source*/, 213 float /*curScore*/) { 214 // Only NuPlayer supports setting a DataSource source directly. 215 return 1.0; 216 } 217 218 virtual sp<MediaPlayerBase> createPlayer(pid_t pid) { 219 ALOGV(" create NuPlayer"); 220 return new NuPlayerDriver(pid); 221 } 222}; 223 224class TestPlayerFactory : public MediaPlayerFactory::IFactory { 225 public: 226 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, 227 const char* url, 228 float /*curScore*/) { 229 if (TestPlayerStub::canBeUsed(url)) { 230 return 1.0; 231 } 232 233 return 0.0; 234 } 235 236 virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) { 237 ALOGV("Create Test Player stub"); 238 return new TestPlayerStub(); 239 } 240}; 241 242void MediaPlayerFactory::registerBuiltinFactories() { 243 Mutex::Autolock lock_(&sLock); 244 245 if (sInitComplete) 246 return; 247 248 registerFactory_l(new NuPlayerFactory(), NU_PLAYER); 249 registerFactory_l(new TestPlayerFactory(), TEST_PLAYER); 250 251 sInitComplete = true; 252} 253 254} // namespace android 255