blob: 57f674300198fda4ccf832c84aaa59ffb3792d14 [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"
Dorian Snyderf32d5702013-03-01 14:25:46 -080033#include <dlfcn.h>
John Grossman44a7e422012-06-21 17:29:24 -070034
35namespace android {
36
John Grossman44a7e422012-06-21 17:29:24 -070037Mutex MediaPlayerFactory::sLock;
38MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
39bool MediaPlayerFactory::sInitComplete = false;
40
41status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
42 player_type type) {
43 if (NULL == factory) {
44 ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
45 " NULL.", type);
46 return BAD_VALUE;
47 }
48
49 if (sFactoryMap.indexOfKey(type) >= 0) {
50 ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
51 " already registered.", type);
52 return ALREADY_EXISTS;
53 }
54
55 if (sFactoryMap.add(type, factory) < 0) {
56 ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
57 " to map.", type);
58 return UNKNOWN_ERROR;
59 }
60
61 return OK;
62}
63
64player_type MediaPlayerFactory::getDefaultPlayerType() {
65 char value[PROPERTY_VALUE_MAX];
66 if (property_get("media.stagefright.use-nuplayer", value, NULL)
67 && (!strcmp("1", value) || !strcasecmp("true", value))) {
68 return NU_PLAYER;
69 }
70
71 return STAGEFRIGHT_PLAYER;
72}
73
74status_t MediaPlayerFactory::registerFactory(IFactory* factory,
75 player_type type) {
76 Mutex::Autolock lock_(&sLock);
77 return registerFactory_l(factory, type);
78}
79
80void MediaPlayerFactory::unregisterFactory(player_type type) {
81 Mutex::Autolock lock_(&sLock);
82 sFactoryMap.removeItem(type);
83}
84
85#define GET_PLAYER_TYPE_IMPL(a...) \
86 Mutex::Autolock lock_(&sLock); \
87 \
88 player_type ret = STAGEFRIGHT_PLAYER; \
89 float bestScore = 0.0; \
90 \
91 for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
92 \
93 IFactory* v = sFactoryMap.valueAt(i); \
94 float thisScore; \
95 CHECK(v != NULL); \
96 thisScore = v->scoreFactory(a, bestScore); \
97 if (thisScore > bestScore) { \
98 ret = sFactoryMap.keyAt(i); \
99 bestScore = thisScore; \
100 } \
101 } \
102 \
103 if (0.0 == bestScore) { \
104 bestScore = getDefaultPlayerType(); \
105 } \
106 \
107 return ret;
108
109player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
110 const char* url) {
111 GET_PLAYER_TYPE_IMPL(client, url);
112}
113
114player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
115 int fd,
116 int64_t offset,
117 int64_t length) {
118 GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
119}
120
121player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
122 const sp<IStreamSource> &source) {
123 GET_PLAYER_TYPE_IMPL(client, source);
124}
125
126#undef GET_PLAYER_TYPE_IMPL
127
128sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
129 player_type playerType,
130 void* cookie,
131 notify_callback_f notifyFunc) {
132 sp<MediaPlayerBase> p;
133 IFactory* factory;
134 status_t init_result;
135 Mutex::Autolock lock_(&sLock);
136
137 if (sFactoryMap.indexOfKey(playerType) < 0) {
138 ALOGE("Failed to create player object of type %d, no registered"
139 " factory", playerType);
140 return p;
141 }
142
143 factory = sFactoryMap.valueFor(playerType);
144 CHECK(NULL != factory);
145 p = factory->createPlayer();
146
147 if (p == NULL) {
148 ALOGE("Failed to create player object of type %d, create failed",
149 playerType);
150 return p;
151 }
152
153 init_result = p->initCheck();
154 if (init_result == NO_ERROR) {
155 p->setNotifyCallback(cookie, notifyFunc);
156 } else {
157 ALOGE("Failed to create player object of type %d, initCheck failed"
158 " (res = %d)", playerType, init_result);
159 p.clear();
160 }
161
162 return p;
163}
164
165/*****************************************************************************
166 * *
167 * Built-In Factory Implementations *
168 * *
169 *****************************************************************************/
170
171class StagefrightPlayerFactory :
172 public MediaPlayerFactory::IFactory {
173 public:
174 virtual float scoreFactory(const sp<IMediaPlayer>& client,
175 int fd,
176 int64_t offset,
177 int64_t length,
178 float curScore) {
179 char buf[20];
180 lseek(fd, offset, SEEK_SET);
181 read(fd, buf, sizeof(buf));
182 lseek(fd, offset, SEEK_SET);
183
184 long ident = *((long*)buf);
185
186 // Ogg vorbis?
187 if (ident == 0x5367674f) // 'OggS'
188 return 1.0;
189
190 return 0.0;
191 }
192
193 virtual sp<MediaPlayerBase> createPlayer() {
194 ALOGV(" create StagefrightPlayer");
195 return new StagefrightPlayer();
196 }
197};
198
199class NuPlayerFactory : public MediaPlayerFactory::IFactory {
200 public:
201 virtual float scoreFactory(const sp<IMediaPlayer>& client,
202 const char* url,
203 float curScore) {
204 static const float kOurScore = 0.8;
205
206 if (kOurScore <= curScore)
207 return 0.0;
208
209 if (!strncasecmp("http://", url, 7)
210 || !strncasecmp("https://", url, 8)) {
211 size_t len = strlen(url);
212 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
213 return kOurScore;
214 }
215
216 if (strstr(url,"m3u8")) {
217 return kOurScore;
218 }
219 }
220
221 if (!strncasecmp("rtsp://", url, 7)) {
222 return kOurScore;
223 }
224
225 return 0.0;
226 }
227
228 virtual float scoreFactory(const sp<IMediaPlayer>& client,
229 const sp<IStreamSource> &source,
230 float curScore) {
231 return 1.0;
232 }
233
234 virtual sp<MediaPlayerBase> createPlayer() {
235 ALOGV(" create NuPlayer");
236 return new NuPlayerDriver;
237 }
238};
239
240class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
241 public:
242 virtual float scoreFactory(const sp<IMediaPlayer>& client,
243 const char* url,
244 float curScore) {
245 static const float kOurScore = 0.4;
246 static const char* const FILE_EXTS[] = { ".mid",
247 ".midi",
248 ".smf",
249 ".xmf",
Dongwon Kang5c5f8d92012-09-05 19:37:13 +0900250 ".mxmf",
John Grossman44a7e422012-06-21 17:29:24 -0700251 ".imy",
252 ".rtttl",
253 ".rtx",
254 ".ota" };
255 if (kOurScore <= curScore)
256 return 0.0;
257
258 // use MidiFile for MIDI extensions
259 int lenURL = strlen(url);
260 for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
261 int len = strlen(FILE_EXTS[i]);
262 int start = lenURL - len;
263 if (start > 0) {
264 if (!strncasecmp(url + start, FILE_EXTS[i], len)) {
265 return kOurScore;
266 }
267 }
268 }
269
270 return 0.0;
271 }
272
273 virtual float scoreFactory(const sp<IMediaPlayer>& client,
274 int fd,
275 int64_t offset,
276 int64_t length,
277 float curScore) {
278 static const float kOurScore = 0.8;
279
280 if (kOurScore <= curScore)
281 return 0.0;
282
283 // Some kind of MIDI?
284 EAS_DATA_HANDLE easdata;
285 if (EAS_Init(&easdata) == EAS_SUCCESS) {
286 EAS_FILE locator;
287 locator.path = NULL;
288 locator.fd = fd;
289 locator.offset = offset;
290 locator.length = length;
291 EAS_HANDLE eashandle;
292 if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
293 EAS_CloseFile(easdata, eashandle);
294 EAS_Shutdown(easdata);
295 return kOurScore;
296 }
297 EAS_Shutdown(easdata);
298 }
299
300 return 0.0;
301 }
302
303 virtual sp<MediaPlayerBase> createPlayer() {
304 ALOGV(" create MidiFile");
305 return new MidiFile();
306 }
307};
308
309class TestPlayerFactory : public MediaPlayerFactory::IFactory {
310 public:
311 virtual float scoreFactory(const sp<IMediaPlayer>& client,
312 const char* url,
313 float curScore) {
314 if (TestPlayerStub::canBeUsed(url)) {
315 return 1.0;
316 }
317
318 return 0.0;
319 }
320
321 virtual sp<MediaPlayerBase> createPlayer() {
322 ALOGV("Create Test Player stub");
323 return new TestPlayerStub();
324 }
325};
326
John Grossman44a7e422012-06-21 17:29:24 -0700327void MediaPlayerFactory::registerBuiltinFactories() {
328 Mutex::Autolock lock_(&sLock);
329
330 if (sInitComplete)
331 return;
332
333 registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
334 registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
335 registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
336 registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
337
Dorian Snyderf32d5702013-03-01 14:25:46 -0800338 const char* FACTORY_LIB = "libdashplayer.so";
339 const char* FACTORY_CREATE_FN = "CreateDASHFactory";
340
341 MediaPlayerFactory::IFactory* pFactory = NULL;
342 void* pFactoryLib = NULL;
343 typedef MediaPlayerFactory::IFactory* (*CreateDASHDriverFn)();
344
345 pFactoryLib = ::dlopen(FACTORY_LIB, RTLD_LAZY);
346 if (pFactoryLib == NULL) {
347 ALOGE("Failed to open FACTORY_LIB Error : %s ",::dlerror());
348 } else {
349 CreateDASHDriverFn pCreateFnPtr;
350 pCreateFnPtr = (CreateDASHDriverFn) dlsym(pFactoryLib, FACTORY_CREATE_FN);
351 if (pCreateFnPtr == NULL) {
352 ALOGE("Could not locate pCreateFnPtr");
353 } else {
354 pFactory = pCreateFnPtr();
355 if(pFactory == NULL) {
356 ALOGE("Failed to invoke CreateDASHDriverFn...");
357 } else {
358 registerFactory_l(pFactory,DASH_PLAYER);
359 }
360 }
361 }
John Grossman44a7e422012-06-21 17:29:24 -0700362 sInitComplete = true;
363}
364
365} // namespace android