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/DataSource.h>
24 #include <media/stagefright/FileSource.h>
25 #include <media/stagefright/foundation/ADebug.h>
26 #include <utils/Errors.h>
27 #include <utils/misc.h>
28 #include <../libstagefright/include/WVMExtractor.h>
29
30 #include "MediaPlayerFactory.h"
31
32 #include "MidiFile.h"
33 #include "TestPlayerStub.h"
34 #include "StagefrightPlayer.h"
35 #include "nuplayer/NuPlayerDriver.h"
36
37 namespace android {
38
39 Mutex MediaPlayerFactory::sLock;
40 MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
41 bool MediaPlayerFactory::sInitComplete = false;
42
registerFactory_l(IFactory * factory,player_type type)43 status_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
getDefaultPlayerType()66 static 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
registerFactory(IFactory * factory,player_type type)82 status_t MediaPlayerFactory::registerFactory(IFactory* factory,
83 player_type type) {
84 Mutex::Autolock lock_(&sLock);
85 return registerFactory_l(factory, type);
86 }
87
unregisterFactory(player_type type)88 void 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
getPlayerType(const sp<IMediaPlayer> & client,const char * url)117 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
118 const char* url) {
119 GET_PLAYER_TYPE_IMPL(client, url);
120 }
121
getPlayerType(const sp<IMediaPlayer> & client,int fd,int64_t offset,int64_t length)122 player_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
getPlayerType(const sp<IMediaPlayer> & client,const sp<IStreamSource> & source)129 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
130 const sp<IStreamSource> &source) {
131 GET_PLAYER_TYPE_IMPL(client, source);
132 }
133
134 #undef GET_PLAYER_TYPE_IMPL
135
createPlayer(player_type playerType,void * cookie,notify_callback_f notifyFunc)136 sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
137 player_type playerType,
138 void* cookie,
139 notify_callback_f notifyFunc) {
140 sp<MediaPlayerBase> p;
141 IFactory* factory;
142 status_t init_result;
143 Mutex::Autolock lock_(&sLock);
144
145 if (sFactoryMap.indexOfKey(playerType) < 0) {
146 ALOGE("Failed to create player object of type %d, no registered"
147 " factory", playerType);
148 return p;
149 }
150
151 factory = sFactoryMap.valueFor(playerType);
152 CHECK(NULL != factory);
153 p = factory->createPlayer();
154
155 if (p == NULL) {
156 ALOGE("Failed to create player object of type %d, create failed",
157 playerType);
158 return p;
159 }
160
161 init_result = p->initCheck();
162 if (init_result == NO_ERROR) {
163 p->setNotifyCallback(cookie, notifyFunc);
164 } else {
165 ALOGE("Failed to create player object of type %d, initCheck failed"
166 " (res = %d)", playerType, init_result);
167 p.clear();
168 }
169
170 return p;
171 }
172
173 /*****************************************************************************
174 * *
175 * Built-In Factory Implementations *
176 * *
177 *****************************************************************************/
178
179 class StagefrightPlayerFactory :
180 public MediaPlayerFactory::IFactory {
181 public:
scoreFactory(const sp<IMediaPlayer> &,int fd,int64_t offset,int64_t length,float)182 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
183 int fd,
184 int64_t offset,
185 int64_t length,
186 float /*curScore*/) {
187 if (legacyDrm()) {
188 sp<DataSource> source = new FileSource(dup(fd), offset, length);
189 String8 mimeType;
190 float confidence;
191 if (SniffWVM(source, &mimeType, &confidence, NULL /* format */)) {
192 return 1.0;
193 }
194 }
195
196 if (getDefaultPlayerType() == STAGEFRIGHT_PLAYER) {
197 char buf[20];
198 lseek(fd, offset, SEEK_SET);
199 read(fd, buf, sizeof(buf));
200 lseek(fd, offset, SEEK_SET);
201
202 uint32_t ident = *((uint32_t*)buf);
203
204 // Ogg vorbis?
205 if (ident == 0x5367674f) // 'OggS'
206 return 1.0;
207 }
208
209 return 0.0;
210 }
211
scoreFactory(const sp<IMediaPlayer> &,const char * url,float)212 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
213 const char* url,
214 float /*curScore*/) {
215 if (legacyDrm() && !strncasecmp("widevine://", url, 11)) {
216 return 1.0;
217 }
218 return 0.0;
219 }
220
createPlayer()221 virtual sp<MediaPlayerBase> createPlayer() {
222 ALOGV(" create StagefrightPlayer");
223 return new StagefrightPlayer();
224 }
225 private:
legacyDrm()226 bool legacyDrm() {
227 char value[PROPERTY_VALUE_MAX];
228 if (property_get("persist.sys.media.legacy-drm", value, NULL)
229 && (!strcmp("1", value) || !strcasecmp("true", value))) {
230 return true;
231 }
232 return false;
233 }
234 };
235
236 class NuPlayerFactory : public MediaPlayerFactory::IFactory {
237 public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float curScore)238 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
239 const char* url,
240 float curScore) {
241 static const float kOurScore = 0.8;
242
243 if (kOurScore <= curScore)
244 return 0.0;
245
246 if (!strncasecmp("http://", url, 7)
247 || !strncasecmp("https://", url, 8)
248 || !strncasecmp("file://", url, 7)) {
249 size_t len = strlen(url);
250 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
251 return kOurScore;
252 }
253
254 if (strstr(url,"m3u8")) {
255 return kOurScore;
256 }
257
258 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
259 return kOurScore;
260 }
261 }
262
263 if (!strncasecmp("rtsp://", url, 7)) {
264 return kOurScore;
265 }
266
267 return 0.0;
268 }
269
scoreFactory(const sp<IMediaPlayer> &,const sp<IStreamSource> &,float)270 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
271 const sp<IStreamSource>& /*source*/,
272 float /*curScore*/) {
273 return 1.0;
274 }
275
createPlayer()276 virtual sp<MediaPlayerBase> createPlayer() {
277 ALOGV(" create NuPlayer");
278 return new NuPlayerDriver;
279 }
280 };
281
282 class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
283 public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float curScore)284 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
285 const char* url,
286 float curScore) {
287 static const float kOurScore = 0.4;
288 static const char* const FILE_EXTS[] = { ".mid",
289 ".midi",
290 ".smf",
291 ".xmf",
292 ".mxmf",
293 ".imy",
294 ".rtttl",
295 ".rtx",
296 ".ota" };
297 if (kOurScore <= curScore)
298 return 0.0;
299
300 // use MidiFile for MIDI extensions
301 int lenURL = strlen(url);
302 for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
303 int len = strlen(FILE_EXTS[i]);
304 int start = lenURL - len;
305 if (start > 0) {
306 if (!strncasecmp(url + start, FILE_EXTS[i], len)) {
307 return kOurScore;
308 }
309 }
310 }
311
312 return 0.0;
313 }
314
scoreFactory(const sp<IMediaPlayer> &,int fd,int64_t offset,int64_t length,float curScore)315 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
316 int fd,
317 int64_t offset,
318 int64_t length,
319 float curScore) {
320 static const float kOurScore = 0.8;
321
322 if (kOurScore <= curScore)
323 return 0.0;
324
325 // Some kind of MIDI?
326 EAS_DATA_HANDLE easdata;
327 if (EAS_Init(&easdata) == EAS_SUCCESS) {
328 EAS_FILE locator;
329 locator.path = NULL;
330 locator.fd = fd;
331 locator.offset = offset;
332 locator.length = length;
333 EAS_HANDLE eashandle;
334 if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
335 EAS_CloseFile(easdata, eashandle);
336 EAS_Shutdown(easdata);
337 return kOurScore;
338 }
339 EAS_Shutdown(easdata);
340 }
341
342 return 0.0;
343 }
344
createPlayer()345 virtual sp<MediaPlayerBase> createPlayer() {
346 ALOGV(" create MidiFile");
347 return new MidiFile();
348 }
349 };
350
351 class TestPlayerFactory : public MediaPlayerFactory::IFactory {
352 public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float)353 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
354 const char* url,
355 float /*curScore*/) {
356 if (TestPlayerStub::canBeUsed(url)) {
357 return 1.0;
358 }
359
360 return 0.0;
361 }
362
createPlayer()363 virtual sp<MediaPlayerBase> createPlayer() {
364 ALOGV("Create Test Player stub");
365 return new TestPlayerStub();
366 }
367 };
368
registerBuiltinFactories()369 void MediaPlayerFactory::registerBuiltinFactories() {
370 Mutex::Autolock lock_(&sLock);
371
372 if (sInitComplete)
373 return;
374
375 registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
376 registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
377 registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
378 registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
379
380 sInitComplete = true;
381 }
382
383 } // namespace android
384