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