blob: 3e0fc0d2623396e4c4793294f3b4adbf4d7fe161 [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
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/foundation/ADebug.h>
24#include <utils/Errors.h>
25#include <utils/misc.h>
26
27#include "MediaPlayerFactory.h"
28
29#include "MidiFile.h"
30#include "TestPlayerStub.h"
31#include "StagefrightPlayer.h"
32#include "nuplayer/NuPlayerDriver.h"
33
34namespace android {
35
John Grossman44a7e422012-06-21 17:29:24 -070036Mutex MediaPlayerFactory::sLock;
37MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
38bool MediaPlayerFactory::sInitComplete = false;
39
40status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
41 player_type type) {
42 if (NULL == factory) {
43 ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
44 " NULL.", type);
45 return BAD_VALUE;
46 }
47
48 if (sFactoryMap.indexOfKey(type) >= 0) {
49 ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
50 " already registered.", type);
51 return ALREADY_EXISTS;
52 }
53
54 if (sFactoryMap.add(type, factory) < 0) {
55 ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
56 " to map.", type);
57 return UNKNOWN_ERROR;
58 }
59
60 return OK;
61}
62
Andy Hung48f36a02014-09-03 23:28:52 +000063static player_type getDefaultPlayerType() {
John Grossman44a7e422012-06-21 17:29:24 -070064 char value[PROPERTY_VALUE_MAX];
Lajos Molnarf5bdd772014-07-27 21:22:11 -070065 if (property_get("media.stagefright.use-awesome", value, NULL)
John Grossman44a7e422012-06-21 17:29:24 -070066 && (!strcmp("1", value) || !strcasecmp("true", value))) {
Lajos Molnarf5bdd772014-07-27 21:22:11 -070067 return STAGEFRIGHT_PLAYER;
John Grossman44a7e422012-06-21 17:29:24 -070068 }
69
Lajos Molnarb47558f2014-03-28 09:53:46 -070070 // TODO: remove this EXPERIMENTAL developer settings property
Lajos Molnarf5bdd772014-07-27 21:22:11 -070071 if (property_get("persist.sys.media.use-awesome", value, NULL)
Lajos Molnarb47558f2014-03-28 09:53:46 -070072 && !strcasecmp("true", value)) {
Lajos Molnarf5bdd772014-07-27 21:22:11 -070073 return STAGEFRIGHT_PLAYER;
Lajos Molnarb47558f2014-03-28 09:53:46 -070074 }
75
Lajos Molnarf5bdd772014-07-27 21:22:11 -070076 return NU_PLAYER;
John Grossman44a7e422012-06-21 17:29:24 -070077}
78
79status_t MediaPlayerFactory::registerFactory(IFactory* factory,
80 player_type type) {
81 Mutex::Autolock lock_(&sLock);
82 return registerFactory_l(factory, type);
83}
84
85void MediaPlayerFactory::unregisterFactory(player_type type) {
86 Mutex::Autolock lock_(&sLock);
87 sFactoryMap.removeItem(type);
88}
89
90#define GET_PLAYER_TYPE_IMPL(a...) \
91 Mutex::Autolock lock_(&sLock); \
92 \
93 player_type ret = STAGEFRIGHT_PLAYER; \
94 float bestScore = 0.0; \
95 \
96 for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
97 \
98 IFactory* v = sFactoryMap.valueAt(i); \
99 float thisScore; \
100 CHECK(v != NULL); \
101 thisScore = v->scoreFactory(a, bestScore); \
102 if (thisScore > bestScore) { \
103 ret = sFactoryMap.keyAt(i); \
104 bestScore = thisScore; \
105 } \
106 } \
107 \
108 if (0.0 == bestScore) { \
Andreas Huber198a8932013-02-05 13:16:39 -0800109 ret = getDefaultPlayerType(); \
John Grossman44a7e422012-06-21 17:29:24 -0700110 } \
111 \
112 return ret;
113
114player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
115 const char* url) {
116 GET_PLAYER_TYPE_IMPL(client, url);
117}
118
119player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
120 int fd,
121 int64_t offset,
122 int64_t length) {
123 GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
124}
125
126player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
127 const sp<IStreamSource> &source) {
128 GET_PLAYER_TYPE_IMPL(client, source);
129}
130
131#undef GET_PLAYER_TYPE_IMPL
132
133sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
134 player_type playerType,
135 void* cookie,
136 notify_callback_f notifyFunc) {
137 sp<MediaPlayerBase> p;
138 IFactory* factory;
139 status_t init_result;
140 Mutex::Autolock lock_(&sLock);
141
142 if (sFactoryMap.indexOfKey(playerType) < 0) {
143 ALOGE("Failed to create player object of type %d, no registered"
144 " factory", playerType);
145 return p;
146 }
147
148 factory = sFactoryMap.valueFor(playerType);
149 CHECK(NULL != factory);
150 p = factory->createPlayer();
151
152 if (p == NULL) {
153 ALOGE("Failed to create player object of type %d, create failed",
154 playerType);
155 return p;
156 }
157
158 init_result = p->initCheck();
159 if (init_result == NO_ERROR) {
160 p->setNotifyCallback(cookie, notifyFunc);
161 } else {
162 ALOGE("Failed to create player object of type %d, initCheck failed"
163 " (res = %d)", playerType, init_result);
164 p.clear();
165 }
166
167 return p;
168}
169
170/*****************************************************************************
171 * *
172 * Built-In Factory Implementations *
173 * *
174 *****************************************************************************/
175
176class StagefrightPlayerFactory :
177 public MediaPlayerFactory::IFactory {
178 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700179 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700180 int fd,
181 int64_t offset,
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700182 int64_t /*length*/,
183 float /*curScore*/) {
Andy Hung48f36a02014-09-03 23:28:52 +0000184 if (getDefaultPlayerType()
185 == STAGEFRIGHT_PLAYER) {
186 char buf[20];
187 lseek(fd, offset, SEEK_SET);
188 read(fd, buf, sizeof(buf));
189 lseek(fd, offset, SEEK_SET);
John Grossman44a7e422012-06-21 17:29:24 -0700190
Andy Hung48f36a02014-09-03 23:28:52 +0000191 uint32_t ident = *((uint32_t*)buf);
John Grossman44a7e422012-06-21 17:29:24 -0700192
Andy Hung48f36a02014-09-03 23:28:52 +0000193 // Ogg vorbis?
194 if (ident == 0x5367674f) // 'OggS'
195 return 1.0;
196 }
John Grossman44a7e422012-06-21 17:29:24 -0700197
198 return 0.0;
199 }
200
201 virtual sp<MediaPlayerBase> createPlayer() {
202 ALOGV(" create StagefrightPlayer");
203 return new StagefrightPlayer();
204 }
205};
206
207class NuPlayerFactory : public MediaPlayerFactory::IFactory {
208 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700209 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700210 const char* url,
211 float curScore) {
212 static const float kOurScore = 0.8;
213
214 if (kOurScore <= curScore)
215 return 0.0;
216
217 if (!strncasecmp("http://", url, 7)
Andreas Huber99759402013-04-01 14:28:31 -0700218 || !strncasecmp("https://", url, 8)
219 || !strncasecmp("file://", url, 7)) {
John Grossman44a7e422012-06-21 17:29:24 -0700220 size_t len = strlen(url);
221 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
222 return kOurScore;
223 }
224
225 if (strstr(url,"m3u8")) {
226 return kOurScore;
227 }
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100228
229 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
230 return kOurScore;
231 }
John Grossman44a7e422012-06-21 17:29:24 -0700232 }
233
234 if (!strncasecmp("rtsp://", url, 7)) {
235 return kOurScore;
236 }
237
238 return 0.0;
239 }
240
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700241 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
242 const sp<IStreamSource>& /*source*/,
243 float /*curScore*/) {
John Grossman44a7e422012-06-21 17:29:24 -0700244 return 1.0;
245 }
246
247 virtual sp<MediaPlayerBase> createPlayer() {
248 ALOGV(" create NuPlayer");
249 return new NuPlayerDriver;
250 }
251};
252
253class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
254 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700255 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700256 const char* url,
257 float curScore) {
258 static const float kOurScore = 0.4;
259 static const char* const FILE_EXTS[] = { ".mid",
260 ".midi",
261 ".smf",
262 ".xmf",
Dongwon Kang5c5f8d92012-09-05 19:37:13 +0900263 ".mxmf",
John Grossman44a7e422012-06-21 17:29:24 -0700264 ".imy",
265 ".rtttl",
266 ".rtx",
267 ".ota" };
268 if (kOurScore <= curScore)
269 return 0.0;
270
271 // use MidiFile for MIDI extensions
272 int lenURL = strlen(url);
273 for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
274 int len = strlen(FILE_EXTS[i]);
275 int start = lenURL - len;
276 if (start > 0) {
277 if (!strncasecmp(url + start, FILE_EXTS[i], len)) {
278 return kOurScore;
279 }
280 }
281 }
282
283 return 0.0;
284 }
285
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700286 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700287 int fd,
288 int64_t offset,
289 int64_t length,
290 float curScore) {
291 static const float kOurScore = 0.8;
292
293 if (kOurScore <= curScore)
294 return 0.0;
295
296 // Some kind of MIDI?
297 EAS_DATA_HANDLE easdata;
298 if (EAS_Init(&easdata) == EAS_SUCCESS) {
299 EAS_FILE locator;
300 locator.path = NULL;
301 locator.fd = fd;
302 locator.offset = offset;
303 locator.length = length;
304 EAS_HANDLE eashandle;
305 if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
306 EAS_CloseFile(easdata, eashandle);
307 EAS_Shutdown(easdata);
308 return kOurScore;
309 }
310 EAS_Shutdown(easdata);
311 }
312
313 return 0.0;
314 }
315
316 virtual sp<MediaPlayerBase> createPlayer() {
317 ALOGV(" create MidiFile");
318 return new MidiFile();
319 }
320};
321
322class TestPlayerFactory : public MediaPlayerFactory::IFactory {
323 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700324 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700325 const char* url,
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700326 float /*curScore*/) {
John Grossman44a7e422012-06-21 17:29:24 -0700327 if (TestPlayerStub::canBeUsed(url)) {
328 return 1.0;
329 }
330
331 return 0.0;
332 }
333
334 virtual sp<MediaPlayerBase> createPlayer() {
335 ALOGV("Create Test Player stub");
336 return new TestPlayerStub();
337 }
338};
339
John Grossman44a7e422012-06-21 17:29:24 -0700340void MediaPlayerFactory::registerBuiltinFactories() {
341 Mutex::Autolock lock_(&sLock);
342
343 if (sInitComplete)
344 return;
345
346 registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
347 registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
348 registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
349 registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
350
John Grossman44a7e422012-06-21 17:29:24 -0700351 sInitComplete = true;
352}
353
354} // namespace android