blob: c68947032d08a30a96251bf0d472898ec4ec854f [file] [log] [blame]
John Grossman44a7e422012-06-21 17:29:24 -07001/*
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
Marco Nelissen08b9e2d2014-12-16 12:46:34 -080018//#define LOG_NDEBUG 0
John Grossman44a7e422012-06-21 17:29:24 -070019#define LOG_TAG "MediaPlayerFactory"
20#include <utils/Log.h>
21
22#include <cutils/properties.h>
23#include <media/IMediaPlayer.h>
Marco Nelissen08b9e2d2014-12-16 12:46:34 -080024#include <media/MidiIoWrapper.h>
Lajos Molnarca7b4bc2014-12-05 17:14:54 -080025#include <media/stagefright/DataSource.h>
26#include <media/stagefright/FileSource.h>
John Grossman44a7e422012-06-21 17:29:24 -070027#include <media/stagefright/foundation/ADebug.h>
28#include <utils/Errors.h>
29#include <utils/misc.h>
Lajos Molnarca7b4bc2014-12-05 17:14:54 -080030#include <../libstagefright/include/WVMExtractor.h>
John Grossman44a7e422012-06-21 17:29:24 -070031
32#include "MediaPlayerFactory.h"
33
34#include "MidiFile.h"
35#include "TestPlayerStub.h"
36#include "StagefrightPlayer.h"
37#include "nuplayer/NuPlayerDriver.h"
38
39namespace android {
40
John Grossman44a7e422012-06-21 17:29:24 -070041Mutex MediaPlayerFactory::sLock;
42MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
43bool MediaPlayerFactory::sInitComplete = false;
44
45status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
46 player_type type) {
47 if (NULL == factory) {
48 ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
49 " NULL.", type);
50 return BAD_VALUE;
51 }
52
53 if (sFactoryMap.indexOfKey(type) >= 0) {
54 ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
55 " already registered.", type);
56 return ALREADY_EXISTS;
57 }
58
59 if (sFactoryMap.add(type, factory) < 0) {
60 ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
61 " to map.", type);
62 return UNKNOWN_ERROR;
63 }
64
65 return OK;
66}
67
Andy Hung48f36a02014-09-03 23:28:52 +000068static player_type getDefaultPlayerType() {
John Grossman44a7e422012-06-21 17:29:24 -070069 char value[PROPERTY_VALUE_MAX];
Lajos Molnarf5bdd772014-07-27 21:22:11 -070070 if (property_get("media.stagefright.use-awesome", value, NULL)
John Grossman44a7e422012-06-21 17:29:24 -070071 && (!strcmp("1", value) || !strcasecmp("true", value))) {
Lajos Molnarf5bdd772014-07-27 21:22:11 -070072 return STAGEFRIGHT_PLAYER;
John Grossman44a7e422012-06-21 17:29:24 -070073 }
74
Lajos Molnarb47558f2014-03-28 09:53:46 -070075 // TODO: remove this EXPERIMENTAL developer settings property
Lajos Molnarf5bdd772014-07-27 21:22:11 -070076 if (property_get("persist.sys.media.use-awesome", value, NULL)
Lajos Molnarb47558f2014-03-28 09:53:46 -070077 && !strcasecmp("true", value)) {
Lajos Molnarf5bdd772014-07-27 21:22:11 -070078 return STAGEFRIGHT_PLAYER;
Lajos Molnarb47558f2014-03-28 09:53:46 -070079 }
80
Lajos Molnarf5bdd772014-07-27 21:22:11 -070081 return NU_PLAYER;
John Grossman44a7e422012-06-21 17:29:24 -070082}
83
84status_t MediaPlayerFactory::registerFactory(IFactory* factory,
85 player_type type) {
86 Mutex::Autolock lock_(&sLock);
87 return registerFactory_l(factory, type);
88}
89
90void MediaPlayerFactory::unregisterFactory(player_type type) {
91 Mutex::Autolock lock_(&sLock);
92 sFactoryMap.removeItem(type);
93}
94
95#define GET_PLAYER_TYPE_IMPL(a...) \
96 Mutex::Autolock lock_(&sLock); \
97 \
98 player_type ret = STAGEFRIGHT_PLAYER; \
99 float bestScore = 0.0; \
100 \
101 for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
102 \
103 IFactory* v = sFactoryMap.valueAt(i); \
104 float thisScore; \
105 CHECK(v != NULL); \
106 thisScore = v->scoreFactory(a, bestScore); \
107 if (thisScore > bestScore) { \
108 ret = sFactoryMap.keyAt(i); \
109 bestScore = thisScore; \
110 } \
111 } \
112 \
113 if (0.0 == bestScore) { \
Andreas Huber198a8932013-02-05 13:16:39 -0800114 ret = getDefaultPlayerType(); \
John Grossman44a7e422012-06-21 17:29:24 -0700115 } \
116 \
117 return ret;
118
119player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
120 const char* url) {
121 GET_PLAYER_TYPE_IMPL(client, url);
122}
123
124player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
125 int fd,
126 int64_t offset,
127 int64_t length) {
128 GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
129}
130
131player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
132 const sp<IStreamSource> &source) {
133 GET_PLAYER_TYPE_IMPL(client, source);
134}
135
136#undef GET_PLAYER_TYPE_IMPL
137
138sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
139 player_type playerType,
140 void* cookie,
141 notify_callback_f notifyFunc) {
142 sp<MediaPlayerBase> p;
143 IFactory* factory;
144 status_t init_result;
145 Mutex::Autolock lock_(&sLock);
146
147 if (sFactoryMap.indexOfKey(playerType) < 0) {
148 ALOGE("Failed to create player object of type %d, no registered"
149 " factory", playerType);
150 return p;
151 }
152
153 factory = sFactoryMap.valueFor(playerType);
154 CHECK(NULL != factory);
155 p = factory->createPlayer();
156
157 if (p == NULL) {
158 ALOGE("Failed to create player object of type %d, create failed",
159 playerType);
160 return p;
161 }
162
163 init_result = p->initCheck();
164 if (init_result == NO_ERROR) {
165 p->setNotifyCallback(cookie, notifyFunc);
166 } else {
167 ALOGE("Failed to create player object of type %d, initCheck failed"
168 " (res = %d)", playerType, init_result);
169 p.clear();
170 }
171
172 return p;
173}
174
175/*****************************************************************************
176 * *
177 * Built-In Factory Implementations *
178 * *
179 *****************************************************************************/
180
181class StagefrightPlayerFactory :
182 public MediaPlayerFactory::IFactory {
183 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700184 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700185 int fd,
186 int64_t offset,
Lajos Molnarca7b4bc2014-12-05 17:14:54 -0800187 int64_t length,
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700188 float /*curScore*/) {
Lajos Molnarca7b4bc2014-12-05 17:14:54 -0800189 if (legacyDrm()) {
190 sp<DataSource> source = new FileSource(dup(fd), offset, length);
191 String8 mimeType;
192 float confidence;
193 if (SniffWVM(source, &mimeType, &confidence, NULL /* format */)) {
194 return 1.0;
195 }
196 }
197
198 if (getDefaultPlayerType() == STAGEFRIGHT_PLAYER) {
Andy Hung48f36a02014-09-03 23:28:52 +0000199 char buf[20];
200 lseek(fd, offset, SEEK_SET);
201 read(fd, buf, sizeof(buf));
202 lseek(fd, offset, SEEK_SET);
John Grossman44a7e422012-06-21 17:29:24 -0700203
Andy Hung48f36a02014-09-03 23:28:52 +0000204 uint32_t ident = *((uint32_t*)buf);
John Grossman44a7e422012-06-21 17:29:24 -0700205
Andy Hung48f36a02014-09-03 23:28:52 +0000206 // Ogg vorbis?
207 if (ident == 0x5367674f) // 'OggS'
208 return 1.0;
209 }
John Grossman44a7e422012-06-21 17:29:24 -0700210
211 return 0.0;
212 }
213
Lajos Molnarca7b4bc2014-12-05 17:14:54 -0800214 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
215 const char* url,
216 float /*curScore*/) {
217 if (legacyDrm() && !strncasecmp("widevine://", url, 11)) {
218 return 1.0;
219 }
220 return 0.0;
221 }
222
John Grossman44a7e422012-06-21 17:29:24 -0700223 virtual sp<MediaPlayerBase> createPlayer() {
224 ALOGV(" create StagefrightPlayer");
225 return new StagefrightPlayer();
226 }
Lajos Molnarca7b4bc2014-12-05 17:14:54 -0800227 private:
228 bool legacyDrm() {
229 char value[PROPERTY_VALUE_MAX];
230 if (property_get("persist.sys.media.legacy-drm", value, NULL)
231 && (!strcmp("1", value) || !strcasecmp("true", value))) {
232 return true;
233 }
234 return false;
235 }
John Grossman44a7e422012-06-21 17:29:24 -0700236};
237
238class NuPlayerFactory : public MediaPlayerFactory::IFactory {
239 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700240 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700241 const char* url,
242 float curScore) {
243 static const float kOurScore = 0.8;
244
245 if (kOurScore <= curScore)
246 return 0.0;
247
248 if (!strncasecmp("http://", url, 7)
Andreas Huber99759402013-04-01 14:28:31 -0700249 || !strncasecmp("https://", url, 8)
250 || !strncasecmp("file://", url, 7)) {
John Grossman44a7e422012-06-21 17:29:24 -0700251 size_t len = strlen(url);
252 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
253 return kOurScore;
254 }
255
256 if (strstr(url,"m3u8")) {
257 return kOurScore;
258 }
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100259
260 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
261 return kOurScore;
262 }
John Grossman44a7e422012-06-21 17:29:24 -0700263 }
264
265 if (!strncasecmp("rtsp://", url, 7)) {
266 return kOurScore;
267 }
268
269 return 0.0;
270 }
271
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700272 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
273 const sp<IStreamSource>& /*source*/,
274 float /*curScore*/) {
John Grossman44a7e422012-06-21 17:29:24 -0700275 return 1.0;
276 }
277
278 virtual sp<MediaPlayerBase> createPlayer() {
279 ALOGV(" create NuPlayer");
280 return new NuPlayerDriver;
281 }
282};
283
284class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
285 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700286 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700287 const char* url,
288 float curScore) {
289 static const float kOurScore = 0.4;
290 static const char* const FILE_EXTS[] = { ".mid",
291 ".midi",
292 ".smf",
293 ".xmf",
Dongwon Kang5c5f8d92012-09-05 19:37:13 +0900294 ".mxmf",
John Grossman44a7e422012-06-21 17:29:24 -0700295 ".imy",
296 ".rtttl",
297 ".rtx",
298 ".ota" };
299 if (kOurScore <= curScore)
300 return 0.0;
301
302 // use MidiFile for MIDI extensions
303 int lenURL = strlen(url);
304 for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
305 int len = strlen(FILE_EXTS[i]);
306 int start = lenURL - len;
307 if (start > 0) {
308 if (!strncasecmp(url + start, FILE_EXTS[i], len)) {
309 return kOurScore;
310 }
311 }
312 }
John Grossman44a7e422012-06-21 17:29:24 -0700313 return 0.0;
314 }
315
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700316 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700317 int fd,
318 int64_t offset,
319 int64_t length,
320 float curScore) {
321 static const float kOurScore = 0.8;
322
323 if (kOurScore <= curScore)
324 return 0.0;
325
326 // Some kind of MIDI?
327 EAS_DATA_HANDLE easdata;
Marco Nelissen08b9e2d2014-12-16 12:46:34 -0800328 sp<MidiIoWrapper> wrapper = new MidiIoWrapper(fd, offset, length);
John Grossman44a7e422012-06-21 17:29:24 -0700329 if (EAS_Init(&easdata) == EAS_SUCCESS) {
John Grossman44a7e422012-06-21 17:29:24 -0700330 EAS_HANDLE eashandle;
Marco Nelissen08b9e2d2014-12-16 12:46:34 -0800331 if (EAS_OpenFile(easdata, wrapper->getLocator(), &eashandle) == EAS_SUCCESS) {
John Grossman44a7e422012-06-21 17:29:24 -0700332 EAS_CloseFile(easdata, eashandle);
333 EAS_Shutdown(easdata);
334 return kOurScore;
335 }
336 EAS_Shutdown(easdata);
337 }
338
339 return 0.0;
340 }
341
342 virtual sp<MediaPlayerBase> createPlayer() {
343 ALOGV(" create MidiFile");
344 return new MidiFile();
345 }
346};
347
348class TestPlayerFactory : public MediaPlayerFactory::IFactory {
349 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700350 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700351 const char* url,
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700352 float /*curScore*/) {
John Grossman44a7e422012-06-21 17:29:24 -0700353 if (TestPlayerStub::canBeUsed(url)) {
354 return 1.0;
355 }
356
357 return 0.0;
358 }
359
360 virtual sp<MediaPlayerBase> createPlayer() {
361 ALOGV("Create Test Player stub");
362 return new TestPlayerStub();
363 }
364};
365
John Grossman44a7e422012-06-21 17:29:24 -0700366void MediaPlayerFactory::registerBuiltinFactories() {
367 Mutex::Autolock lock_(&sLock);
368
369 if (sInitComplete)
370 return;
371
372 registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
373 registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
374 registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
375 registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
376
John Grossman44a7e422012-06-21 17:29:24 -0700377 sInitComplete = true;
378}
379
380} // namespace android