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/DataSource.h> 24#include <media/IMediaPlayer.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 const sp<MediaPlayerBase::Listener> &listener, 130 pid_t pid) { 131 sp<MediaPlayerBase> p; 132 IFactory* factory; 133 status_t init_result; 134 Mutex::Autolock lock_(&sLock); 135 136 if (sFactoryMap.indexOfKey(playerType) < 0) { 137 ALOGE("Failed to create player object of type %d, no registered" 138 " factory", playerType); 139 return p; 140 } 141 142 factory = sFactoryMap.valueFor(playerType); 143 CHECK(NULL != factory); 144 p = factory->createPlayer(pid); 145 146 if (p == NULL) { 147 ALOGE("Failed to create player object of type %d, create failed", 148 playerType); 149 return p; 150 } 151 152 init_result = p->initCheck(); 153 if (init_result == NO_ERROR) { 154 p->setNotifyCallback(listener); 155 } else { 156 ALOGE("Failed to create player object of type %d, initCheck failed" 157 " (res = %d)", playerType, init_result); 158 p.clear(); 159 } 160 161 return p; 162} 163 164/***************************************************************************** 165 * * 166 * Built-In Factory Implementations * 167 * * 168 *****************************************************************************/ 169 170class NuPlayerFactory : public MediaPlayerFactory::IFactory { 171 public: 172 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, 173 const char* url, 174 float curScore) { 175 static const float kOurScore = 0.8; 176 177 if (kOurScore <= curScore) 178 return 0.0; 179 180 if (!strncasecmp("http://", url, 7) 181 || !strncasecmp("https://", url, 8) 182 || !strncasecmp("file://", url, 7)) { 183 size_t len = strlen(url); 184 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) { 185 return kOurScore; 186 } 187 188 if (strstr(url,"m3u8")) { 189 return kOurScore; 190 } 191 192 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) { 193 return kOurScore; 194 } 195 } 196 197 if (!strncasecmp("rtsp://", url, 7)) { 198 return kOurScore; 199 } 200 201 return 0.0; 202 } 203 204 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, 205 const sp<IStreamSource>& /*source*/, 206 float /*curScore*/) { 207 return 1.0; 208 } 209 210 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, 211 const sp<DataSource>& /*source*/, 212 float /*curScore*/) { 213 // Only NuPlayer supports setting a DataSource source directly. 214 return 1.0; 215 } 216 217 virtual sp<MediaPlayerBase> createPlayer(pid_t pid) { 218 ALOGV(" create NuPlayer"); 219 return new NuPlayerDriver(pid); 220 } 221}; 222 223class TestPlayerFactory : public MediaPlayerFactory::IFactory { 224 public: 225 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, 226 const char* url, 227 float /*curScore*/) { 228 if (TestPlayerStub::canBeUsed(url)) { 229 return 1.0; 230 } 231 232 return 0.0; 233 } 234 235 virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) { 236 ALOGV("Create Test Player stub"); 237 return new TestPlayerStub(); 238 } 239}; 240 241void MediaPlayerFactory::registerBuiltinFactories() { 242 Mutex::Autolock lock_(&sLock); 243 244 if (sInitComplete) 245 return; 246 247 IFactory* factory = new NuPlayerFactory(); 248 if (registerFactory_l(factory, NU_PLAYER) != OK) 249 delete factory; 250 factory = new TestPlayerFactory(); 251 if (registerFactory_l(factory, TEST_PLAYER) != OK) 252 delete factory; 253 254 sInitComplete = true; 255} 256 257} // namespace android 258