blob: ca33aedeedd70e957f28b0f396d1b944c2b956b3 [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>
Lajos Molnarca7b4bc2014-12-05 17:14:54 -080024#include <media/stagefright/DataSource.h>
25#include <media/stagefright/FileSource.h>
John Grossman44a7e422012-06-21 17:29:24 -070026#include <media/stagefright/foundation/ADebug.h>
27#include <utils/Errors.h>
28#include <utils/misc.h>
Lajos Molnarca7b4bc2014-12-05 17:14:54 -080029#include <../libstagefright/include/WVMExtractor.h>
John Grossman44a7e422012-06-21 17:29:24 -070030
31#include "MediaPlayerFactory.h"
32
John Grossman44a7e422012-06-21 17:29:24 -070033#include "TestPlayerStub.h"
34#include "StagefrightPlayer.h"
35#include "nuplayer/NuPlayerDriver.h"
36
37namespace android {
38
John Grossman44a7e422012-06-21 17:29:24 -070039Mutex 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
Andy Hung48f36a02014-09-03 23:28:52 +000066static player_type getDefaultPlayerType() {
John Grossman44a7e422012-06-21 17:29:24 -070067 char value[PROPERTY_VALUE_MAX];
Lajos Molnarf5bdd772014-07-27 21:22:11 -070068 if (property_get("media.stagefright.use-awesome", value, NULL)
John Grossman44a7e422012-06-21 17:29:24 -070069 && (!strcmp("1", value) || !strcasecmp("true", value))) {
Lajos Molnarf5bdd772014-07-27 21:22:11 -070070 return STAGEFRIGHT_PLAYER;
John Grossman44a7e422012-06-21 17:29:24 -070071 }
72
Lajos Molnarb47558f2014-03-28 09:53:46 -070073 // TODO: remove this EXPERIMENTAL developer settings property
Lajos Molnarf5bdd772014-07-27 21:22:11 -070074 if (property_get("persist.sys.media.use-awesome", value, NULL)
Lajos Molnarb47558f2014-03-28 09:53:46 -070075 && !strcasecmp("true", value)) {
Lajos Molnarf5bdd772014-07-27 21:22:11 -070076 return STAGEFRIGHT_PLAYER;
Lajos Molnarb47558f2014-03-28 09:53:46 -070077 }
78
Lajos Molnarf5bdd772014-07-27 21:22:11 -070079 return NU_PLAYER;
John Grossman44a7e422012-06-21 17:29:24 -070080}
81
82status_t MediaPlayerFactory::registerFactory(IFactory* factory,
83 player_type type) {
84 Mutex::Autolock lock_(&sLock);
85 return registerFactory_l(factory, type);
86}
87
88void MediaPlayerFactory::unregisterFactory(player_type type) {
89 Mutex::Autolock lock_(&sLock);
90 sFactoryMap.removeItem(type);
91}
92
93#define GET_PLAYER_TYPE_IMPL(a...) \
94 Mutex::Autolock lock_(&sLock); \
95 \
96 player_type ret = STAGEFRIGHT_PLAYER; \
97 float bestScore = 0.0; \
98 \
99 for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
100 \
101 IFactory* v = sFactoryMap.valueAt(i); \
102 float thisScore; \
103 CHECK(v != NULL); \
104 thisScore = v->scoreFactory(a, bestScore); \
105 if (thisScore > bestScore) { \
106 ret = sFactoryMap.keyAt(i); \
107 bestScore = thisScore; \
108 } \
109 } \
110 \
111 if (0.0 == bestScore) { \
Andreas Huber198a8932013-02-05 13:16:39 -0800112 ret = getDefaultPlayerType(); \
John Grossman44a7e422012-06-21 17:29:24 -0700113 } \
114 \
115 return ret;
116
117player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
118 const char* url) {
119 GET_PLAYER_TYPE_IMPL(client, url);
120}
121
122player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
123 int fd,
124 int64_t offset,
125 int64_t length) {
126 GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
127}
128
129player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
130 const sp<IStreamSource> &source) {
131 GET_PLAYER_TYPE_IMPL(client, source);
132}
133
Chris Watkins99f31602015-03-20 13:06:33 -0700134player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
135 const sp<DataSource> &source) {
136 GET_PLAYER_TYPE_IMPL(client, source);
137}
138
John Grossman44a7e422012-06-21 17:29:24 -0700139#undef GET_PLAYER_TYPE_IMPL
140
141sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
142 player_type playerType,
143 void* cookie,
144 notify_callback_f notifyFunc) {
145 sp<MediaPlayerBase> p;
146 IFactory* factory;
147 status_t init_result;
148 Mutex::Autolock lock_(&sLock);
149
150 if (sFactoryMap.indexOfKey(playerType) < 0) {
151 ALOGE("Failed to create player object of type %d, no registered"
152 " factory", playerType);
153 return p;
154 }
155
156 factory = sFactoryMap.valueFor(playerType);
157 CHECK(NULL != factory);
158 p = factory->createPlayer();
159
160 if (p == NULL) {
161 ALOGE("Failed to create player object of type %d, create failed",
162 playerType);
163 return p;
164 }
165
166 init_result = p->initCheck();
167 if (init_result == NO_ERROR) {
168 p->setNotifyCallback(cookie, notifyFunc);
169 } else {
170 ALOGE("Failed to create player object of type %d, initCheck failed"
171 " (res = %d)", playerType, init_result);
172 p.clear();
173 }
174
175 return p;
176}
177
178/*****************************************************************************
179 * *
180 * Built-In Factory Implementations *
181 * *
182 *****************************************************************************/
183
184class StagefrightPlayerFactory :
185 public MediaPlayerFactory::IFactory {
186 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700187 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700188 int fd,
189 int64_t offset,
Lajos Molnarca7b4bc2014-12-05 17:14:54 -0800190 int64_t length,
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700191 float /*curScore*/) {
Lajos Molnarca7b4bc2014-12-05 17:14:54 -0800192 if (legacyDrm()) {
193 sp<DataSource> source = new FileSource(dup(fd), offset, length);
194 String8 mimeType;
195 float confidence;
196 if (SniffWVM(source, &mimeType, &confidence, NULL /* format */)) {
197 return 1.0;
198 }
199 }
200
201 if (getDefaultPlayerType() == STAGEFRIGHT_PLAYER) {
Andy Hung48f36a02014-09-03 23:28:52 +0000202 char buf[20];
203 lseek(fd, offset, SEEK_SET);
204 read(fd, buf, sizeof(buf));
205 lseek(fd, offset, SEEK_SET);
John Grossman44a7e422012-06-21 17:29:24 -0700206
Andy Hung48f36a02014-09-03 23:28:52 +0000207 uint32_t ident = *((uint32_t*)buf);
John Grossman44a7e422012-06-21 17:29:24 -0700208
Andy Hung48f36a02014-09-03 23:28:52 +0000209 // Ogg vorbis?
210 if (ident == 0x5367674f) // 'OggS'
211 return 1.0;
212 }
John Grossman44a7e422012-06-21 17:29:24 -0700213
214 return 0.0;
215 }
216
Lajos Molnarca7b4bc2014-12-05 17:14:54 -0800217 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
218 const char* url,
219 float /*curScore*/) {
220 if (legacyDrm() && !strncasecmp("widevine://", url, 11)) {
221 return 1.0;
222 }
223 return 0.0;
224 }
225
John Grossman44a7e422012-06-21 17:29:24 -0700226 virtual sp<MediaPlayerBase> createPlayer() {
227 ALOGV(" create StagefrightPlayer");
228 return new StagefrightPlayer();
229 }
Lajos Molnarca7b4bc2014-12-05 17:14:54 -0800230 private:
231 bool legacyDrm() {
232 char value[PROPERTY_VALUE_MAX];
233 if (property_get("persist.sys.media.legacy-drm", value, NULL)
234 && (!strcmp("1", value) || !strcasecmp("true", value))) {
235 return true;
236 }
237 return false;
238 }
John Grossman44a7e422012-06-21 17:29:24 -0700239};
240
241class NuPlayerFactory : public MediaPlayerFactory::IFactory {
242 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700243 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700244 const char* url,
245 float curScore) {
246 static const float kOurScore = 0.8;
247
248 if (kOurScore <= curScore)
249 return 0.0;
250
251 if (!strncasecmp("http://", url, 7)
Andreas Huber99759402013-04-01 14:28:31 -0700252 || !strncasecmp("https://", url, 8)
253 || !strncasecmp("file://", url, 7)) {
John Grossman44a7e422012-06-21 17:29:24 -0700254 size_t len = strlen(url);
255 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
256 return kOurScore;
257 }
258
259 if (strstr(url,"m3u8")) {
260 return kOurScore;
261 }
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100262
263 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
264 return kOurScore;
265 }
John Grossman44a7e422012-06-21 17:29:24 -0700266 }
267
268 if (!strncasecmp("rtsp://", url, 7)) {
269 return kOurScore;
270 }
271
272 return 0.0;
273 }
274
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700275 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
276 const sp<IStreamSource>& /*source*/,
277 float /*curScore*/) {
John Grossman44a7e422012-06-21 17:29:24 -0700278 return 1.0;
279 }
280
Chris Watkins99f31602015-03-20 13:06:33 -0700281 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
282 const sp<DataSource>& /*source*/,
283 float /*curScore*/) {
284 // Only NuPlayer supports setting a DataSource source directly.
285 return 1.0;
286 }
287
John Grossman44a7e422012-06-21 17:29:24 -0700288 virtual sp<MediaPlayerBase> createPlayer() {
289 ALOGV(" create NuPlayer");
290 return new NuPlayerDriver;
291 }
292};
293
John Grossman44a7e422012-06-21 17:29:24 -0700294class TestPlayerFactory : public MediaPlayerFactory::IFactory {
295 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700296 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700297 const char* url,
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700298 float /*curScore*/) {
John Grossman44a7e422012-06-21 17:29:24 -0700299 if (TestPlayerStub::canBeUsed(url)) {
300 return 1.0;
301 }
302
303 return 0.0;
304 }
305
306 virtual sp<MediaPlayerBase> createPlayer() {
307 ALOGV("Create Test Player stub");
308 return new TestPlayerStub();
309 }
310};
311
John Grossman44a7e422012-06-21 17:29:24 -0700312void MediaPlayerFactory::registerBuiltinFactories() {
313 Mutex::Autolock lock_(&sLock);
314
315 if (sInitComplete)
316 return;
317
318 registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
319 registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
John Grossman44a7e422012-06-21 17:29:24 -0700320 registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
321
John Grossman44a7e422012-06-21 17:29:24 -0700322 sInitComplete = true;
323}
324
325} // namespace android