blob: ac115f63747cf04ccb5fe58b80232f52f423befa [file] [log] [blame]
Wei Jia53692fa2017-12-11 10:33:46 -08001/*
2**
3** Copyright 2017, 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_NDEBUG 0
19#define LOG_TAG "MediaPlayer2Factory"
20#include <utils/Log.h>
21
22#include <cutils/properties.h>
23#include <media/DataSource.h>
24#include <media/MediaPlayer2Engine.h>
Wei Jia53692fa2017-12-11 10:33:46 -080025#include <media/stagefright/foundation/ADebug.h>
26#include <utils/Errors.h>
27#include <utils/misc.h>
28
29#include "MediaPlayer2Factory.h"
30
31#include "TestPlayerStub.h"
32#include "nuplayer2/NuPlayer2Driver.h"
33
34namespace android {
35
36Mutex MediaPlayer2Factory::sLock;
Wei Jia787ed442018-01-24 18:03:04 -080037MediaPlayer2Factory::tFactoryMap *MediaPlayer2Factory::sFactoryMap;
Wei Jia53692fa2017-12-11 10:33:46 -080038bool MediaPlayer2Factory::sInitComplete = false;
39
Wei Jia787ed442018-01-24 18:03:04 -080040// static
41bool MediaPlayer2Factory::ensureInit_l() {
42 if (sFactoryMap == NULL) {
43 sFactoryMap = new (std::nothrow) tFactoryMap();
44 }
45 return (sFactoryMap != NULL);
46}
47
Wei Jia53692fa2017-12-11 10:33:46 -080048status_t MediaPlayer2Factory::registerFactory_l(IFactory* factory,
49 player2_type type) {
50 if (NULL == factory) {
51 ALOGE("Failed to register MediaPlayer2Factory of type %d, factory is"
52 " NULL.", type);
53 return BAD_VALUE;
54 }
55
Wei Jia787ed442018-01-24 18:03:04 -080056 if (!ensureInit_l()) {
57 return NO_INIT;
58 }
59
60 if (sFactoryMap->indexOfKey(type) >= 0) {
Wei Jia53692fa2017-12-11 10:33:46 -080061 ALOGE("Failed to register MediaPlayer2Factory of type %d, type is"
62 " already registered.", type);
63 return ALREADY_EXISTS;
64 }
65
Wei Jia787ed442018-01-24 18:03:04 -080066 if (sFactoryMap->add(type, factory) < 0) {
Wei Jia53692fa2017-12-11 10:33:46 -080067 ALOGE("Failed to register MediaPlayer2Factory of type %d, failed to add"
68 " to map.", type);
69 return UNKNOWN_ERROR;
70 }
71
72 return OK;
73}
74
75static player2_type getDefaultPlayerType() {
76 return PLAYER2_NU_PLAYER2;
77}
78
Wei Jia53692fa2017-12-11 10:33:46 -080079#define GET_PLAYER_TYPE_IMPL(a...) \
80 Mutex::Autolock lock_(&sLock); \
81 \
82 player2_type ret = PLAYER2_STAGEFRIGHT_PLAYER; \
83 float bestScore = 0.0; \
84 \
Wei Jia787ed442018-01-24 18:03:04 -080085 if (!ensureInit_l()) { \
86 return ret; \
87 } \
Wei Jia53692fa2017-12-11 10:33:46 -080088 \
Wei Jia787ed442018-01-24 18:03:04 -080089 for (size_t i = 0; i < sFactoryMap->size(); ++i) { \
90 \
91 IFactory* v = sFactoryMap->valueAt(i); \
Wei Jia53692fa2017-12-11 10:33:46 -080092 float thisScore; \
93 CHECK(v != NULL); \
94 thisScore = v->scoreFactory(a, bestScore); \
95 if (thisScore > bestScore) { \
Wei Jia787ed442018-01-24 18:03:04 -080096 ret = sFactoryMap->keyAt(i); \
Wei Jia53692fa2017-12-11 10:33:46 -080097 bestScore = thisScore; \
98 } \
99 } \
100 \
101 if (0.0 == bestScore) { \
102 ret = getDefaultPlayerType(); \
103 } \
104 \
105 return ret;
106
107player2_type MediaPlayer2Factory::getPlayerType(const sp<MediaPlayer2Engine>& client,
108 const char* url) {
109 GET_PLAYER_TYPE_IMPL(client, url);
110}
111
112player2_type MediaPlayer2Factory::getPlayerType(const sp<MediaPlayer2Engine>& client,
113 int fd,
114 int64_t offset,
115 int64_t length) {
116 GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
117}
118
119player2_type MediaPlayer2Factory::getPlayerType(const sp<MediaPlayer2Engine>& client,
120 const sp<IStreamSource> &source) {
121 GET_PLAYER_TYPE_IMPL(client, source);
122}
123
124player2_type MediaPlayer2Factory::getPlayerType(const sp<MediaPlayer2Engine>& client,
125 const sp<DataSource> &source) {
126 GET_PLAYER_TYPE_IMPL(client, source);
127}
128
129#undef GET_PLAYER_TYPE_IMPL
130
131sp<MediaPlayer2Base> MediaPlayer2Factory::createPlayer(
132 player2_type playerType,
Pawin Vongmasa50963852017-12-12 06:24:42 -0800133 const wp<MediaPlayer2Engine> &client,
134 MediaPlayer2Base::NotifyCallback notifyFunc,
Wei Jia53692fa2017-12-11 10:33:46 -0800135 pid_t pid) {
136 sp<MediaPlayer2Base> p;
137 IFactory* factory;
138 status_t init_result;
139 Mutex::Autolock lock_(&sLock);
140
Wei Jia787ed442018-01-24 18:03:04 -0800141 if (!ensureInit_l()) {
142 return NULL;
143 }
144
145 if (sFactoryMap->indexOfKey(playerType) < 0) {
Wei Jia53692fa2017-12-11 10:33:46 -0800146 ALOGE("Failed to create player object of type %d, no registered"
147 " factory", playerType);
148 return p;
149 }
150
Wei Jia787ed442018-01-24 18:03:04 -0800151 factory = sFactoryMap->valueFor(playerType);
Wei Jia53692fa2017-12-11 10:33:46 -0800152 CHECK(NULL != factory);
153 p = factory->createPlayer(pid);
154
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) {
Pawin Vongmasa50963852017-12-12 06:24:42 -0800163 p->setNotifyCallback(client, notifyFunc);
Wei Jia53692fa2017-12-11 10:33:46 -0800164 } 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 NuPlayer2Factory : public MediaPlayer2Factory::IFactory {
180 public:
181 virtual float scoreFactory(const sp<MediaPlayer2Engine>& /*client*/,
182 const char* url,
183 float curScore) {
184 static const float kOurScore = 0.8;
185
186 if (kOurScore <= curScore) {
187 return 0.0;
188 }
189
190 if (!strncasecmp("http://", url, 7)
191 || !strncasecmp("https://", url, 8)
192 || !strncasecmp("file://", url, 7)) {
193 size_t len = strlen(url);
194 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
195 return kOurScore;
196 }
197
198 if (strstr(url,"m3u8")) {
199 return kOurScore;
200 }
201
202 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
203 return kOurScore;
204 }
205 }
206
207 if (!strncasecmp("rtsp://", url, 7)) {
208 return kOurScore;
209 }
210
211 return 0.0;
212 }
213
214 virtual float scoreFactory(const sp<MediaPlayer2Engine>& /*client*/,
215 const sp<IStreamSource>& /*source*/,
216 float /*curScore*/) {
217 return 1.0;
218 }
219
220 virtual float scoreFactory(const sp<MediaPlayer2Engine>& /*client*/,
221 const sp<DataSource>& /*source*/,
222 float /*curScore*/) {
223 // Only NuPlayer2 supports setting a DataSource source directly.
224 return 1.0;
225 }
226
227 virtual sp<MediaPlayer2Base> createPlayer(pid_t pid) {
228 ALOGV(" create NuPlayer2");
229 return new NuPlayer2Driver(pid);
230 }
231};
232
233class TestPlayerFactory : public MediaPlayer2Factory::IFactory {
234 public:
235 virtual float scoreFactory(const sp<MediaPlayer2Engine>& /*client*/,
236 const char* url,
237 float /*curScore*/) {
238 if (TestPlayerStub::canBeUsed(url)) {
239 return 1.0;
240 }
241
242 return 0.0;
243 }
244
245 virtual sp<MediaPlayer2Base> createPlayer(pid_t /* pid */) {
246 ALOGV("Create Test Player stub");
247 return new TestPlayerStub();
248 }
249};
250
251void MediaPlayer2Factory::registerBuiltinFactories() {
252 Mutex::Autolock lock_(&sLock);
253
254 if (sInitComplete) {
255 return;
256 }
257
258 IFactory* factory = new NuPlayer2Factory();
259 if (registerFactory_l(factory, PLAYER2_NU_PLAYER2) != OK) {
260 delete factory;
261 }
262 factory = new TestPlayerFactory();
263 if (registerFactory_l(factory, PLAYER2_TEST_PLAYER) != OK) {
264 delete factory;
265 }
266
267 sInitComplete = true;
268}
269
270} // namespace android