blob: d149290ccfdf8a5f478406c47d574aca5a6557ac [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 Nelissenbc11e712015-01-08 12:26:36 -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 Nelissenbc11e712015-01-08 12:26:36 -080024#include <media/MidiIoWrapper.h>
25#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>
30
31#include "MediaPlayerFactory.h"
32
33#include "MidiFile.h"
34#include "TestPlayerStub.h"
35#include "StagefrightPlayer.h"
36#include "nuplayer/NuPlayerDriver.h"
37
38namespace android {
39
John Grossman44a7e422012-06-21 17:29:24 -070040Mutex MediaPlayerFactory::sLock;
41MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
42bool MediaPlayerFactory::sInitComplete = false;
43
44status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
45 player_type type) {
46 if (NULL == factory) {
47 ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
48 " NULL.", type);
49 return BAD_VALUE;
50 }
51
52 if (sFactoryMap.indexOfKey(type) >= 0) {
53 ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
54 " already registered.", type);
55 return ALREADY_EXISTS;
56 }
57
58 if (sFactoryMap.add(type, factory) < 0) {
59 ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
60 " to map.", type);
61 return UNKNOWN_ERROR;
62 }
63
64 return OK;
65}
66
Andy Hung48f36a02014-09-03 23:28:52 +000067static player_type getDefaultPlayerType() {
John Grossman44a7e422012-06-21 17:29:24 -070068 char value[PROPERTY_VALUE_MAX];
Lajos Molnarf5bdd772014-07-27 21:22:11 -070069 if (property_get("media.stagefright.use-awesome", value, NULL)
John Grossman44a7e422012-06-21 17:29:24 -070070 && (!strcmp("1", value) || !strcasecmp("true", value))) {
Lajos Molnarf5bdd772014-07-27 21:22:11 -070071 return STAGEFRIGHT_PLAYER;
John Grossman44a7e422012-06-21 17:29:24 -070072 }
73
Lajos Molnarb47558f2014-03-28 09:53:46 -070074 // TODO: remove this EXPERIMENTAL developer settings property
Lajos Molnarf5bdd772014-07-27 21:22:11 -070075 if (property_get("persist.sys.media.use-awesome", value, NULL)
Lajos Molnarb47558f2014-03-28 09:53:46 -070076 && !strcasecmp("true", value)) {
Lajos Molnarf5bdd772014-07-27 21:22:11 -070077 return STAGEFRIGHT_PLAYER;
Lajos Molnarb47558f2014-03-28 09:53:46 -070078 }
79
Lajos Molnarf5bdd772014-07-27 21:22:11 -070080 return NU_PLAYER;
John Grossman44a7e422012-06-21 17:29:24 -070081}
82
83status_t MediaPlayerFactory::registerFactory(IFactory* factory,
84 player_type type) {
85 Mutex::Autolock lock_(&sLock);
86 return registerFactory_l(factory, type);
87}
88
89void MediaPlayerFactory::unregisterFactory(player_type type) {
90 Mutex::Autolock lock_(&sLock);
91 sFactoryMap.removeItem(type);
92}
93
94#define GET_PLAYER_TYPE_IMPL(a...) \
95 Mutex::Autolock lock_(&sLock); \
96 \
97 player_type ret = STAGEFRIGHT_PLAYER; \
98 float bestScore = 0.0; \
99 \
100 for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
101 \
102 IFactory* v = sFactoryMap.valueAt(i); \
103 float thisScore; \
104 CHECK(v != NULL); \
105 thisScore = v->scoreFactory(a, bestScore); \
106 if (thisScore > bestScore) { \
107 ret = sFactoryMap.keyAt(i); \
108 bestScore = thisScore; \
109 } \
110 } \
111 \
112 if (0.0 == bestScore) { \
Andreas Huber198a8932013-02-05 13:16:39 -0800113 ret = getDefaultPlayerType(); \
John Grossman44a7e422012-06-21 17:29:24 -0700114 } \
115 \
116 return ret;
117
118player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
119 const char* url) {
120 GET_PLAYER_TYPE_IMPL(client, url);
121}
122
123player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
124 int fd,
125 int64_t offset,
126 int64_t length) {
127 GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
128}
129
130player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
131 const sp<IStreamSource> &source) {
132 GET_PLAYER_TYPE_IMPL(client, source);
133}
134
135#undef GET_PLAYER_TYPE_IMPL
136
137sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
138 player_type playerType,
139 void* cookie,
140 notify_callback_f notifyFunc) {
141 sp<MediaPlayerBase> p;
142 IFactory* factory;
143 status_t init_result;
144 Mutex::Autolock lock_(&sLock);
145
146 if (sFactoryMap.indexOfKey(playerType) < 0) {
147 ALOGE("Failed to create player object of type %d, no registered"
148 " factory", playerType);
149 return p;
150 }
151
152 factory = sFactoryMap.valueFor(playerType);
153 CHECK(NULL != factory);
154 p = factory->createPlayer();
155
156 if (p == NULL) {
157 ALOGE("Failed to create player object of type %d, create failed",
158 playerType);
159 return p;
160 }
161
162 init_result = p->initCheck();
163 if (init_result == NO_ERROR) {
164 p->setNotifyCallback(cookie, notifyFunc);
165 } else {
166 ALOGE("Failed to create player object of type %d, initCheck failed"
167 " (res = %d)", playerType, init_result);
168 p.clear();
169 }
170
171 return p;
172}
173
174/*****************************************************************************
175 * *
176 * Built-In Factory Implementations *
177 * *
178 *****************************************************************************/
179
180class StagefrightPlayerFactory :
181 public MediaPlayerFactory::IFactory {
182 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700183 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700184 int fd,
185 int64_t offset,
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700186 int64_t /*length*/,
187 float /*curScore*/) {
Andy Hung48f36a02014-09-03 23:28:52 +0000188 if (getDefaultPlayerType()
189 == STAGEFRIGHT_PLAYER) {
190 char buf[20];
191 lseek(fd, offset, SEEK_SET);
192 read(fd, buf, sizeof(buf));
193 lseek(fd, offset, SEEK_SET);
John Grossman44a7e422012-06-21 17:29:24 -0700194
Andy Hung48f36a02014-09-03 23:28:52 +0000195 uint32_t ident = *((uint32_t*)buf);
John Grossman44a7e422012-06-21 17:29:24 -0700196
Andy Hung48f36a02014-09-03 23:28:52 +0000197 // Ogg vorbis?
198 if (ident == 0x5367674f) // 'OggS'
199 return 1.0;
200 }
John Grossman44a7e422012-06-21 17:29:24 -0700201
202 return 0.0;
203 }
204
205 virtual sp<MediaPlayerBase> createPlayer() {
206 ALOGV(" create StagefrightPlayer");
207 return new StagefrightPlayer();
208 }
209};
210
211class NuPlayerFactory : public MediaPlayerFactory::IFactory {
212 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700213 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700214 const char* url,
215 float curScore) {
216 static const float kOurScore = 0.8;
217
218 if (kOurScore <= curScore)
219 return 0.0;
220
221 if (!strncasecmp("http://", url, 7)
Andreas Huber99759402013-04-01 14:28:31 -0700222 || !strncasecmp("https://", url, 8)
223 || !strncasecmp("file://", url, 7)) {
John Grossman44a7e422012-06-21 17:29:24 -0700224 size_t len = strlen(url);
225 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
226 return kOurScore;
227 }
228
229 if (strstr(url,"m3u8")) {
230 return kOurScore;
231 }
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100232
233 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
234 return kOurScore;
235 }
John Grossman44a7e422012-06-21 17:29:24 -0700236 }
237
238 if (!strncasecmp("rtsp://", url, 7)) {
239 return kOurScore;
240 }
241
242 return 0.0;
243 }
244
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700245 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
246 const sp<IStreamSource>& /*source*/,
247 float /*curScore*/) {
John Grossman44a7e422012-06-21 17:29:24 -0700248 return 1.0;
249 }
250
251 virtual sp<MediaPlayerBase> createPlayer() {
252 ALOGV(" create NuPlayer");
253 return new NuPlayerDriver;
254 }
255};
256
257class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
258 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700259 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700260 const char* url,
261 float curScore) {
262 static const float kOurScore = 0.4;
263 static const char* const FILE_EXTS[] = { ".mid",
264 ".midi",
265 ".smf",
266 ".xmf",
Dongwon Kang5c5f8d92012-09-05 19:37:13 +0900267 ".mxmf",
John Grossman44a7e422012-06-21 17:29:24 -0700268 ".imy",
269 ".rtttl",
270 ".rtx",
271 ".ota" };
272 if (kOurScore <= curScore)
273 return 0.0;
274
275 // use MidiFile for MIDI extensions
276 int lenURL = strlen(url);
277 for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
278 int len = strlen(FILE_EXTS[i]);
279 int start = lenURL - len;
280 if (start > 0) {
281 if (!strncasecmp(url + start, FILE_EXTS[i], len)) {
282 return kOurScore;
283 }
284 }
285 }
John Grossman44a7e422012-06-21 17:29:24 -0700286 return 0.0;
287 }
288
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700289 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700290 int fd,
291 int64_t offset,
292 int64_t length,
293 float curScore) {
294 static const float kOurScore = 0.8;
295
296 if (kOurScore <= curScore)
297 return 0.0;
298
299 // Some kind of MIDI?
300 EAS_DATA_HANDLE easdata;
Marco Nelissenbc11e712015-01-08 12:26:36 -0800301 sp<MidiIoWrapper> wrapper = new MidiIoWrapper(fd, offset, length);
John Grossman44a7e422012-06-21 17:29:24 -0700302 if (EAS_Init(&easdata) == EAS_SUCCESS) {
John Grossman44a7e422012-06-21 17:29:24 -0700303 EAS_HANDLE eashandle;
Marco Nelissenbc11e712015-01-08 12:26:36 -0800304 if (EAS_OpenFile(easdata, wrapper->getLocator(), &eashandle) == EAS_SUCCESS) {
John Grossman44a7e422012-06-21 17:29:24 -0700305 EAS_CloseFile(easdata, eashandle);
306 EAS_Shutdown(easdata);
307 return kOurScore;
308 }
309 EAS_Shutdown(easdata);
310 }
311
312 return 0.0;
313 }
314
315 virtual sp<MediaPlayerBase> createPlayer() {
316 ALOGV(" create MidiFile");
317 return new MidiFile();
318 }
319};
320
321class TestPlayerFactory : public MediaPlayerFactory::IFactory {
322 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700323 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700324 const char* url,
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700325 float /*curScore*/) {
John Grossman44a7e422012-06-21 17:29:24 -0700326 if (TestPlayerStub::canBeUsed(url)) {
327 return 1.0;
328 }
329
330 return 0.0;
331 }
332
333 virtual sp<MediaPlayerBase> createPlayer() {
334 ALOGV("Create Test Player stub");
335 return new TestPlayerStub();
336 }
337};
338
John Grossman44a7e422012-06-21 17:29:24 -0700339void MediaPlayerFactory::registerBuiltinFactories() {
340 Mutex::Autolock lock_(&sLock);
341
342 if (sInitComplete)
343 return;
344
345 registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
346 registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
347 registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
348 registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
349
John Grossman44a7e422012-06-21 17:29:24 -0700350 sInitComplete = true;
351}
352
353} // namespace android