blob: d5d12f7bcc69c736c639447f065ab7b33bb2f8ca [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 Molnarf5bdd772014-07-27 21:22:11 -070073 return NU_PLAYER;
John Grossman44a7e422012-06-21 17:29:24 -070074}
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) { \
Andreas Huber198a8932013-02-05 13:16:39 -0800106 ret = getDefaultPlayerType(); \
John Grossman44a7e422012-06-21 17:29:24 -0700107 } \
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
Chris Watkins99f31602015-03-20 13:06:33 -0700128player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
129 const sp<DataSource> &source) {
130 GET_PLAYER_TYPE_IMPL(client, source);
131}
132
John Grossman44a7e422012-06-21 17:29:24 -0700133#undef GET_PLAYER_TYPE_IMPL
134
135sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
136 player_type playerType,
137 void* cookie,
Ronghua Wu68845c12015-07-21 09:50:48 -0700138 notify_callback_f notifyFunc,
139 pid_t pid) {
John Grossman44a7e422012-06-21 17:29:24 -0700140 sp<MediaPlayerBase> p;
141 IFactory* factory;
142 status_t init_result;
143 Mutex::Autolock lock_(&sLock);
144
145 if (sFactoryMap.indexOfKey(playerType) < 0) {
146 ALOGE("Failed to create player object of type %d, no registered"
147 " factory", playerType);
148 return p;
149 }
150
151 factory = sFactoryMap.valueFor(playerType);
152 CHECK(NULL != factory);
Ronghua Wu68845c12015-07-21 09:50:48 -0700153 p = factory->createPlayer(pid);
John Grossman44a7e422012-06-21 17:29:24 -0700154
155 if (p == NULL) {
156 ALOGE("Failed to create player object of type %d, create failed",
157 playerType);
158 return p;
159 }
160
161 init_result = p->initCheck();
162 if (init_result == NO_ERROR) {
163 p->setNotifyCallback(cookie, notifyFunc);
164 } else {
165 ALOGE("Failed to create player object of type %d, initCheck failed"
166 " (res = %d)", playerType, init_result);
167 p.clear();
168 }
169
170 return p;
171}
172
173/*****************************************************************************
174 * *
175 * Built-In Factory Implementations *
176 * *
177 *****************************************************************************/
178
179class StagefrightPlayerFactory :
180 public MediaPlayerFactory::IFactory {
181 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700182 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700183 int fd,
184 int64_t offset,
Lajos Molnarca7b4bc2014-12-05 17:14:54 -0800185 int64_t length,
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700186 float /*curScore*/) {
Lajos Molnarca7b4bc2014-12-05 17:14:54 -0800187 if (legacyDrm()) {
188 sp<DataSource> source = new FileSource(dup(fd), offset, length);
189 String8 mimeType;
190 float confidence;
191 if (SniffWVM(source, &mimeType, &confidence, NULL /* format */)) {
192 return 1.0;
193 }
194 }
195
196 if (getDefaultPlayerType() == STAGEFRIGHT_PLAYER) {
Andy Hung48f36a02014-09-03 23:28:52 +0000197 char buf[20];
198 lseek(fd, offset, SEEK_SET);
199 read(fd, buf, sizeof(buf));
200 lseek(fd, offset, SEEK_SET);
John Grossman44a7e422012-06-21 17:29:24 -0700201
Andy Hung48f36a02014-09-03 23:28:52 +0000202 uint32_t ident = *((uint32_t*)buf);
John Grossman44a7e422012-06-21 17:29:24 -0700203
Andy Hung48f36a02014-09-03 23:28:52 +0000204 // Ogg vorbis?
205 if (ident == 0x5367674f) // 'OggS'
206 return 1.0;
207 }
John Grossman44a7e422012-06-21 17:29:24 -0700208
209 return 0.0;
210 }
211
Lajos Molnarca7b4bc2014-12-05 17:14:54 -0800212 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
213 const char* url,
214 float /*curScore*/) {
215 if (legacyDrm() && !strncasecmp("widevine://", url, 11)) {
216 return 1.0;
217 }
218 return 0.0;
219 }
220
Ronghua Wu68845c12015-07-21 09:50:48 -0700221 virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) {
John Grossman44a7e422012-06-21 17:29:24 -0700222 ALOGV(" create StagefrightPlayer");
223 return new StagefrightPlayer();
224 }
Lajos Molnarca7b4bc2014-12-05 17:14:54 -0800225 private:
226 bool legacyDrm() {
227 char value[PROPERTY_VALUE_MAX];
228 if (property_get("persist.sys.media.legacy-drm", value, NULL)
229 && (!strcmp("1", value) || !strcasecmp("true", value))) {
230 return true;
231 }
232 return false;
233 }
John Grossman44a7e422012-06-21 17:29:24 -0700234};
235
236class NuPlayerFactory : public MediaPlayerFactory::IFactory {
237 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700238 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700239 const char* url,
240 float curScore) {
241 static const float kOurScore = 0.8;
242
243 if (kOurScore <= curScore)
244 return 0.0;
245
246 if (!strncasecmp("http://", url, 7)
Andreas Huber99759402013-04-01 14:28:31 -0700247 || !strncasecmp("https://", url, 8)
248 || !strncasecmp("file://", url, 7)) {
John Grossman44a7e422012-06-21 17:29:24 -0700249 size_t len = strlen(url);
250 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
251 return kOurScore;
252 }
253
254 if (strstr(url,"m3u8")) {
255 return kOurScore;
256 }
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100257
258 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
259 return kOurScore;
260 }
John Grossman44a7e422012-06-21 17:29:24 -0700261 }
262
263 if (!strncasecmp("rtsp://", url, 7)) {
264 return kOurScore;
265 }
266
267 return 0.0;
268 }
269
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700270 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
271 const sp<IStreamSource>& /*source*/,
272 float /*curScore*/) {
John Grossman44a7e422012-06-21 17:29:24 -0700273 return 1.0;
274 }
275
Chris Watkins99f31602015-03-20 13:06:33 -0700276 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
277 const sp<DataSource>& /*source*/,
278 float /*curScore*/) {
279 // Only NuPlayer supports setting a DataSource source directly.
280 return 1.0;
281 }
282
Ronghua Wu68845c12015-07-21 09:50:48 -0700283 virtual sp<MediaPlayerBase> createPlayer(pid_t pid) {
John Grossman44a7e422012-06-21 17:29:24 -0700284 ALOGV(" create NuPlayer");
Ronghua Wu68845c12015-07-21 09:50:48 -0700285 return new NuPlayerDriver(pid);
John Grossman44a7e422012-06-21 17:29:24 -0700286 }
287};
288
John Grossman44a7e422012-06-21 17:29:24 -0700289class TestPlayerFactory : public MediaPlayerFactory::IFactory {
290 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700291 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700292 const char* url,
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700293 float /*curScore*/) {
John Grossman44a7e422012-06-21 17:29:24 -0700294 if (TestPlayerStub::canBeUsed(url)) {
295 return 1.0;
296 }
297
298 return 0.0;
299 }
300
Ronghua Wu68845c12015-07-21 09:50:48 -0700301 virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) {
John Grossman44a7e422012-06-21 17:29:24 -0700302 ALOGV("Create Test Player stub");
303 return new TestPlayerStub();
304 }
305};
306
John Grossman44a7e422012-06-21 17:29:24 -0700307void MediaPlayerFactory::registerBuiltinFactories() {
308 Mutex::Autolock lock_(&sLock);
309
310 if (sInitComplete)
311 return;
312
313 registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
314 registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
John Grossman44a7e422012-06-21 17:29:24 -0700315 registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
316
John Grossman44a7e422012-06-21 17:29:24 -0700317 sInitComplete = true;
318}
319
320} // namespace android