blob: dcb347feecc4da418ebe9bf6341783014798aa4d [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
36extern sp<MediaPlayerBase> createAAH_TXPlayer();
37extern sp<MediaPlayerBase> createAAH_RXPlayer();
38
39Mutex MediaPlayerFactory::sLock;
40MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
41bool MediaPlayerFactory::sInitComplete = false;
42
43status_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
66player_type MediaPlayerFactory::getDefaultPlayerType() {
67 char value[PROPERTY_VALUE_MAX];
68 if (property_get("media.stagefright.use-nuplayer", value, NULL)
69 && (!strcmp("1", value) || !strcasecmp("true", value))) {
70 return NU_PLAYER;
71 }
72
73 return STAGEFRIGHT_PLAYER;
74}
75
76status_t MediaPlayerFactory::registerFactory(IFactory* factory,
77 player_type type) {
78 Mutex::Autolock lock_(&sLock);
79 return registerFactory_l(factory, type);
80}
81
82void MediaPlayerFactory::unregisterFactory(player_type type) {
83 Mutex::Autolock lock_(&sLock);
84 sFactoryMap.removeItem(type);
85}
86
87#define GET_PLAYER_TYPE_IMPL(a...) \
88 Mutex::Autolock lock_(&sLock); \
89 \
90 player_type ret = STAGEFRIGHT_PLAYER; \
91 float bestScore = 0.0; \
92 \
93 for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
94 \
95 IFactory* v = sFactoryMap.valueAt(i); \
96 float thisScore; \
97 CHECK(v != NULL); \
98 thisScore = v->scoreFactory(a, bestScore); \
99 if (thisScore > bestScore) { \
100 ret = sFactoryMap.keyAt(i); \
101 bestScore = thisScore; \
102 } \
103 } \
104 \
105 if (0.0 == bestScore) { \
106 bestScore = getDefaultPlayerType(); \
107 } \
108 \
109 return ret;
110
111player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
112 const char* url) {
113 GET_PLAYER_TYPE_IMPL(client, url);
114}
115
116player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
117 int fd,
118 int64_t offset,
119 int64_t length) {
120 GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
121}
122
123player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
124 const sp<IStreamSource> &source) {
125 GET_PLAYER_TYPE_IMPL(client, source);
126}
127
128#undef GET_PLAYER_TYPE_IMPL
129
130sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
131 player_type playerType,
132 void* cookie,
133 notify_callback_f notifyFunc) {
134 sp<MediaPlayerBase> p;
135 IFactory* factory;
136 status_t init_result;
137 Mutex::Autolock lock_(&sLock);
138
139 if (sFactoryMap.indexOfKey(playerType) < 0) {
140 ALOGE("Failed to create player object of type %d, no registered"
141 " factory", playerType);
142 return p;
143 }
144
145 factory = sFactoryMap.valueFor(playerType);
146 CHECK(NULL != factory);
147 p = factory->createPlayer();
148
149 if (p == NULL) {
150 ALOGE("Failed to create player object of type %d, create failed",
151 playerType);
152 return p;
153 }
154
155 init_result = p->initCheck();
156 if (init_result == NO_ERROR) {
157 p->setNotifyCallback(cookie, notifyFunc);
158 } else {
159 ALOGE("Failed to create player object of type %d, initCheck failed"
160 " (res = %d)", playerType, init_result);
161 p.clear();
162 }
163
164 return p;
165}
166
167/*****************************************************************************
168 * *
169 * Built-In Factory Implementations *
170 * *
171 *****************************************************************************/
172
173class StagefrightPlayerFactory :
174 public MediaPlayerFactory::IFactory {
175 public:
176 virtual float scoreFactory(const sp<IMediaPlayer>& client,
177 int fd,
178 int64_t offset,
179 int64_t length,
180 float curScore) {
181 char buf[20];
182 lseek(fd, offset, SEEK_SET);
183 read(fd, buf, sizeof(buf));
184 lseek(fd, offset, SEEK_SET);
185
186 long ident = *((long*)buf);
187
188 // Ogg vorbis?
189 if (ident == 0x5367674f) // 'OggS'
190 return 1.0;
191
192 return 0.0;
193 }
194
195 virtual sp<MediaPlayerBase> createPlayer() {
196 ALOGV(" create StagefrightPlayer");
197 return new StagefrightPlayer();
198 }
199};
200
201class NuPlayerFactory : public MediaPlayerFactory::IFactory {
202 public:
203 virtual float scoreFactory(const sp<IMediaPlayer>& client,
204 const char* url,
205 float curScore) {
206 static const float kOurScore = 0.8;
207
208 if (kOurScore <= curScore)
209 return 0.0;
210
211 if (!strncasecmp("http://", url, 7)
212 || !strncasecmp("https://", url, 8)) {
213 size_t len = strlen(url);
214 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
215 return kOurScore;
216 }
217
218 if (strstr(url,"m3u8")) {
219 return kOurScore;
220 }
221 }
222
223 if (!strncasecmp("rtsp://", url, 7)) {
224 return kOurScore;
225 }
226
227 return 0.0;
228 }
229
230 virtual float scoreFactory(const sp<IMediaPlayer>& client,
231 const sp<IStreamSource> &source,
232 float curScore) {
233 return 1.0;
234 }
235
236 virtual sp<MediaPlayerBase> createPlayer() {
237 ALOGV(" create NuPlayer");
238 return new NuPlayerDriver;
239 }
240};
241
242class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
243 public:
244 virtual float scoreFactory(const sp<IMediaPlayer>& client,
245 const char* url,
246 float curScore) {
247 static const float kOurScore = 0.4;
248 static const char* const FILE_EXTS[] = { ".mid",
249 ".midi",
250 ".smf",
251 ".xmf",
252 ".imy",
253 ".rtttl",
254 ".rtx",
255 ".ota" };
256 if (kOurScore <= curScore)
257 return 0.0;
258
259 // use MidiFile for MIDI extensions
260 int lenURL = strlen(url);
261 for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
262 int len = strlen(FILE_EXTS[i]);
263 int start = lenURL - len;
264 if (start > 0) {
265 if (!strncasecmp(url + start, FILE_EXTS[i], len)) {
266 return kOurScore;
267 }
268 }
269 }
270
271 return 0.0;
272 }
273
274 virtual float scoreFactory(const sp<IMediaPlayer>& client,
275 int fd,
276 int64_t offset,
277 int64_t length,
278 float curScore) {
279 static const float kOurScore = 0.8;
280
281 if (kOurScore <= curScore)
282 return 0.0;
283
284 // Some kind of MIDI?
285 EAS_DATA_HANDLE easdata;
286 if (EAS_Init(&easdata) == EAS_SUCCESS) {
287 EAS_FILE locator;
288 locator.path = NULL;
289 locator.fd = fd;
290 locator.offset = offset;
291 locator.length = length;
292 EAS_HANDLE eashandle;
293 if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
294 EAS_CloseFile(easdata, eashandle);
295 EAS_Shutdown(easdata);
296 return kOurScore;
297 }
298 EAS_Shutdown(easdata);
299 }
300
301 return 0.0;
302 }
303
304 virtual sp<MediaPlayerBase> createPlayer() {
305 ALOGV(" create MidiFile");
306 return new MidiFile();
307 }
308};
309
310class TestPlayerFactory : public MediaPlayerFactory::IFactory {
311 public:
312 virtual float scoreFactory(const sp<IMediaPlayer>& client,
313 const char* url,
314 float curScore) {
315 if (TestPlayerStub::canBeUsed(url)) {
316 return 1.0;
317 }
318
319 return 0.0;
320 }
321
322 virtual sp<MediaPlayerBase> createPlayer() {
323 ALOGV("Create Test Player stub");
324 return new TestPlayerStub();
325 }
326};
327
328class AAH_RX_PlayerFactory : public MediaPlayerFactory::IFactory {
329 public:
330 virtual float scoreFactory(const sp<IMediaPlayer>& client,
331 const char* url,
332 float curScore) {
333 static const float kOurScore = 0.6;
334
335 if (kOurScore <= curScore)
336 return 0.0;
337
338 if (!strncasecmp("aahRX://", url, 8)) {
339 return kOurScore;
340 }
341
342 return 0.0;
343 }
344
345 virtual sp<MediaPlayerBase> createPlayer() {
346 ALOGV(" create A@H RX Player");
347 return createAAH_RXPlayer();
348 }
349};
350
351class AAH_TX_PlayerFactory : public MediaPlayerFactory::IFactory {
352 public:
353 virtual float scoreFactory(const sp<IMediaPlayer>& client,
354 const char* url,
355 float curScore) {
356 return checkRetransmitEndpoint(client) ? 1.1 : 0.0;
357 }
358
359 virtual float scoreFactory(const sp<IMediaPlayer>& client,
360 int fd,
361 int64_t offset,
362 int64_t length,
363 float curScore) {
364 return checkRetransmitEndpoint(client) ? 1.1 : 0.0;
365 }
366
367 virtual sp<MediaPlayerBase> createPlayer() {
368 ALOGV(" create A@H TX Player");
369 return createAAH_TXPlayer();
370 }
371
372 private:
373 bool checkRetransmitEndpoint(const sp<IMediaPlayer>& client) {
374 if (client == NULL)
375 return false;
376
377 struct sockaddr_in junk;
378 if (OK != client->getRetransmitEndpoint(&junk))
379 return false;
380
381 return true;
382 }
383};
384
385void MediaPlayerFactory::registerBuiltinFactories() {
386 Mutex::Autolock lock_(&sLock);
387
388 if (sInitComplete)
389 return;
390
391 registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
392 registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
393 registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
394 registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
395
396 // TODO: remove this once AAH players have been relocated from
397 // framework/base and into vendor/google_devices/phantasm
398 registerFactory_l(new AAH_RX_PlayerFactory(), AAH_RX_PLAYER);
399 registerFactory_l(new AAH_TX_PlayerFactory(), AAH_TX_PLAYER);
400
401 sInitComplete = true;
402}
403
404} // namespace android