blob: 89a9ddf845772984e80746d71148ecd78b0d6779 [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 Nelissenbc11e712015-01-08 12:26:36 -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>
Marco Nelissenbc11e712015-01-08 12:26:36 -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>
29
30#include "MediaPlayerFactory.h"
31
John Grossman44a7e422012-06-21 17:29:24 -070032#include "TestPlayerStub.h"
33#include "StagefrightPlayer.h"
34#include "nuplayer/NuPlayerDriver.h"
35
36namespace android {
37
John Grossman44a7e422012-06-21 17:29:24 -070038Mutex MediaPlayerFactory::sLock;
39MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
40bool MediaPlayerFactory::sInitComplete = false;
41
42status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
43 player_type type) {
44 if (NULL == factory) {
45 ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
46 " NULL.", type);
47 return BAD_VALUE;
48 }
49
50 if (sFactoryMap.indexOfKey(type) >= 0) {
51 ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
52 " already registered.", type);
53 return ALREADY_EXISTS;
54 }
55
56 if (sFactoryMap.add(type, factory) < 0) {
57 ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
58 " to map.", type);
59 return UNKNOWN_ERROR;
60 }
61
62 return OK;
63}
64
Andy Hung48f36a02014-09-03 23:28:52 +000065static player_type getDefaultPlayerType() {
John Grossman44a7e422012-06-21 17:29:24 -070066 char value[PROPERTY_VALUE_MAX];
Lajos Molnarf5bdd772014-07-27 21:22:11 -070067 if (property_get("media.stagefright.use-awesome", value, NULL)
John Grossman44a7e422012-06-21 17:29:24 -070068 && (!strcmp("1", value) || !strcasecmp("true", value))) {
Lajos Molnarf5bdd772014-07-27 21:22:11 -070069 return STAGEFRIGHT_PLAYER;
John Grossman44a7e422012-06-21 17:29:24 -070070 }
71
Lajos Molnarb47558f2014-03-28 09:53:46 -070072 // TODO: remove this EXPERIMENTAL developer settings property
Lajos Molnarf5bdd772014-07-27 21:22:11 -070073 if (property_get("persist.sys.media.use-awesome", value, NULL)
Lajos Molnarb47558f2014-03-28 09:53:46 -070074 && !strcasecmp("true", value)) {
Lajos Molnarf5bdd772014-07-27 21:22:11 -070075 return STAGEFRIGHT_PLAYER;
Lajos Molnarb47558f2014-03-28 09:53:46 -070076 }
77
Lajos Molnarf5bdd772014-07-27 21:22:11 -070078 return NU_PLAYER;
John Grossman44a7e422012-06-21 17:29:24 -070079}
80
81status_t MediaPlayerFactory::registerFactory(IFactory* factory,
82 player_type type) {
83 Mutex::Autolock lock_(&sLock);
84 return registerFactory_l(factory, type);
85}
86
87void MediaPlayerFactory::unregisterFactory(player_type type) {
88 Mutex::Autolock lock_(&sLock);
89 sFactoryMap.removeItem(type);
90}
91
92#define GET_PLAYER_TYPE_IMPL(a...) \
93 Mutex::Autolock lock_(&sLock); \
94 \
95 player_type ret = STAGEFRIGHT_PLAYER; \
96 float bestScore = 0.0; \
97 \
98 for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
99 \
100 IFactory* v = sFactoryMap.valueAt(i); \
101 float thisScore; \
102 CHECK(v != NULL); \
103 thisScore = v->scoreFactory(a, bestScore); \
104 if (thisScore > bestScore) { \
105 ret = sFactoryMap.keyAt(i); \
106 bestScore = thisScore; \
107 } \
108 } \
109 \
110 if (0.0 == bestScore) { \
Andreas Huber198a8932013-02-05 13:16:39 -0800111 ret = getDefaultPlayerType(); \
John Grossman44a7e422012-06-21 17:29:24 -0700112 } \
113 \
114 return ret;
115
116player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
117 const char* url) {
118 GET_PLAYER_TYPE_IMPL(client, url);
119}
120
121player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
122 int fd,
123 int64_t offset,
124 int64_t length) {
125 GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
126}
127
128player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
129 const sp<IStreamSource> &source) {
130 GET_PLAYER_TYPE_IMPL(client, source);
131}
132
133#undef GET_PLAYER_TYPE_IMPL
134
135sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
136 player_type playerType,
137 void* cookie,
138 notify_callback_f notifyFunc) {
139 sp<MediaPlayerBase> p;
140 IFactory* factory;
141 status_t init_result;
142 Mutex::Autolock lock_(&sLock);
143
144 if (sFactoryMap.indexOfKey(playerType) < 0) {
145 ALOGE("Failed to create player object of type %d, no registered"
146 " factory", playerType);
147 return p;
148 }
149
150 factory = sFactoryMap.valueFor(playerType);
151 CHECK(NULL != factory);
152 p = factory->createPlayer();
153
154 if (p == NULL) {
155 ALOGE("Failed to create player object of type %d, create failed",
156 playerType);
157 return p;
158 }
159
160 init_result = p->initCheck();
161 if (init_result == NO_ERROR) {
162 p->setNotifyCallback(cookie, notifyFunc);
163 } else {
164 ALOGE("Failed to create player object of type %d, initCheck failed"
165 " (res = %d)", playerType, init_result);
166 p.clear();
167 }
168
169 return p;
170}
171
172/*****************************************************************************
173 * *
174 * Built-In Factory Implementations *
175 * *
176 *****************************************************************************/
177
178class StagefrightPlayerFactory :
179 public MediaPlayerFactory::IFactory {
180 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700181 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700182 int fd,
183 int64_t offset,
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700184 int64_t /*length*/,
185 float /*curScore*/) {
Andy Hung48f36a02014-09-03 23:28:52 +0000186 if (getDefaultPlayerType()
187 == STAGEFRIGHT_PLAYER) {
188 char buf[20];
189 lseek(fd, offset, SEEK_SET);
190 read(fd, buf, sizeof(buf));
191 lseek(fd, offset, SEEK_SET);
John Grossman44a7e422012-06-21 17:29:24 -0700192
Andy Hung48f36a02014-09-03 23:28:52 +0000193 uint32_t ident = *((uint32_t*)buf);
John Grossman44a7e422012-06-21 17:29:24 -0700194
Andy Hung48f36a02014-09-03 23:28:52 +0000195 // Ogg vorbis?
196 if (ident == 0x5367674f) // 'OggS'
197 return 1.0;
198 }
John Grossman44a7e422012-06-21 17:29:24 -0700199
200 return 0.0;
201 }
202
203 virtual sp<MediaPlayerBase> createPlayer() {
204 ALOGV(" create StagefrightPlayer");
205 return new StagefrightPlayer();
206 }
207};
208
209class NuPlayerFactory : public MediaPlayerFactory::IFactory {
210 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700211 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700212 const char* url,
213 float curScore) {
214 static const float kOurScore = 0.8;
215
216 if (kOurScore <= curScore)
217 return 0.0;
218
219 if (!strncasecmp("http://", url, 7)
Andreas Huber99759402013-04-01 14:28:31 -0700220 || !strncasecmp("https://", url, 8)
221 || !strncasecmp("file://", url, 7)) {
John Grossman44a7e422012-06-21 17:29:24 -0700222 size_t len = strlen(url);
223 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
224 return kOurScore;
225 }
226
227 if (strstr(url,"m3u8")) {
228 return kOurScore;
229 }
Oscar Rydhé7a33b772012-02-20 10:15:48 +0100230
231 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
232 return kOurScore;
233 }
John Grossman44a7e422012-06-21 17:29:24 -0700234 }
235
236 if (!strncasecmp("rtsp://", url, 7)) {
237 return kOurScore;
238 }
239
240 return 0.0;
241 }
242
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700243 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
244 const sp<IStreamSource>& /*source*/,
245 float /*curScore*/) {
John Grossman44a7e422012-06-21 17:29:24 -0700246 return 1.0;
247 }
248
249 virtual sp<MediaPlayerBase> createPlayer() {
250 ALOGV(" create NuPlayer");
251 return new NuPlayerDriver;
252 }
253};
254
John Grossman44a7e422012-06-21 17:29:24 -0700255class TestPlayerFactory : public MediaPlayerFactory::IFactory {
256 public:
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700257 virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
John Grossman44a7e422012-06-21 17:29:24 -0700258 const char* url,
Mark Salyzyn247d9eb2014-06-23 14:14:40 -0700259 float /*curScore*/) {
John Grossman44a7e422012-06-21 17:29:24 -0700260 if (TestPlayerStub::canBeUsed(url)) {
261 return 1.0;
262 }
263
264 return 0.0;
265 }
266
267 virtual sp<MediaPlayerBase> createPlayer() {
268 ALOGV("Create Test Player stub");
269 return new TestPlayerStub();
270 }
271};
272
John Grossman44a7e422012-06-21 17:29:24 -0700273void MediaPlayerFactory::registerBuiltinFactories() {
274 Mutex::Autolock lock_(&sLock);
275
276 if (sInitComplete)
277 return;
278
279 registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
280 registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
John Grossman44a7e422012-06-21 17:29:24 -0700281 registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
282
John Grossman44a7e422012-06-21 17:29:24 -0700283 sInitComplete = true;
284}
285
286} // namespace android