blob: df567cee6189c8f0b43eccb2f696d0d198550629 [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;
37MediaPlayer2Factory::tFactoryMap MediaPlayer2Factory::sFactoryMap;
38bool MediaPlayer2Factory::sInitComplete = false;
39
40status_t MediaPlayer2Factory::registerFactory_l(IFactory* factory,
41 player2_type type) {
42 if (NULL == factory) {
43 ALOGE("Failed to register MediaPlayer2Factory of type %d, factory is"
44 " NULL.", type);
45 return BAD_VALUE;
46 }
47
48 if (sFactoryMap.indexOfKey(type) >= 0) {
49 ALOGE("Failed to register MediaPlayer2Factory of type %d, type is"
50 " already registered.", type);
51 return ALREADY_EXISTS;
52 }
53
54 if (sFactoryMap.add(type, factory) < 0) {
55 ALOGE("Failed to register MediaPlayer2Factory of type %d, failed to add"
56 " to map.", type);
57 return UNKNOWN_ERROR;
58 }
59
60 return OK;
61}
62
63static player2_type getDefaultPlayerType() {
64 return PLAYER2_NU_PLAYER2;
65}
66
67status_t MediaPlayer2Factory::registerFactory(IFactory* factory,
68 player2_type type) {
69 Mutex::Autolock lock_(&sLock);
70 return registerFactory_l(factory, type);
71}
72
73void MediaPlayer2Factory::unregisterFactory(player2_type type) {
74 Mutex::Autolock lock_(&sLock);
75 sFactoryMap.removeItem(type);
76}
77
78#define GET_PLAYER_TYPE_IMPL(a...) \
79 Mutex::Autolock lock_(&sLock); \
80 \
81 player2_type ret = PLAYER2_STAGEFRIGHT_PLAYER; \
82 float bestScore = 0.0; \
83 \
84 for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
85 \
86 IFactory* v = sFactoryMap.valueAt(i); \
87 float thisScore; \
88 CHECK(v != NULL); \
89 thisScore = v->scoreFactory(a, bestScore); \
90 if (thisScore > bestScore) { \
91 ret = sFactoryMap.keyAt(i); \
92 bestScore = thisScore; \
93 } \
94 } \
95 \
96 if (0.0 == bestScore) { \
97 ret = getDefaultPlayerType(); \
98 } \
99 \
100 return ret;
101
102player2_type MediaPlayer2Factory::getPlayerType(const sp<MediaPlayer2Engine>& client,
103 const char* url) {
104 GET_PLAYER_TYPE_IMPL(client, url);
105}
106
107player2_type MediaPlayer2Factory::getPlayerType(const sp<MediaPlayer2Engine>& client,
108 int fd,
109 int64_t offset,
110 int64_t length) {
111 GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
112}
113
114player2_type MediaPlayer2Factory::getPlayerType(const sp<MediaPlayer2Engine>& client,
115 const sp<IStreamSource> &source) {
116 GET_PLAYER_TYPE_IMPL(client, source);
117}
118
119player2_type MediaPlayer2Factory::getPlayerType(const sp<MediaPlayer2Engine>& client,
120 const sp<DataSource> &source) {
121 GET_PLAYER_TYPE_IMPL(client, source);
122}
123
124#undef GET_PLAYER_TYPE_IMPL
125
126sp<MediaPlayer2Base> MediaPlayer2Factory::createPlayer(
127 player2_type playerType,
Pawin Vongmasa50963852017-12-12 06:24:42 -0800128 const wp<MediaPlayer2Engine> &client,
129 MediaPlayer2Base::NotifyCallback notifyFunc,
Wei Jia53692fa2017-12-11 10:33:46 -0800130 pid_t pid) {
131 sp<MediaPlayer2Base> p;
132 IFactory* factory;
133 status_t init_result;
134 Mutex::Autolock lock_(&sLock);
135
136 if (sFactoryMap.indexOfKey(playerType) < 0) {
137 ALOGE("Failed to create player object of type %d, no registered"
138 " factory", playerType);
139 return p;
140 }
141
142 factory = sFactoryMap.valueFor(playerType);
143 CHECK(NULL != factory);
144 p = factory->createPlayer(pid);
145
146 if (p == NULL) {
147 ALOGE("Failed to create player object of type %d, create failed",
148 playerType);
149 return p;
150 }
151
152 init_result = p->initCheck();
153 if (init_result == NO_ERROR) {
Pawin Vongmasa50963852017-12-12 06:24:42 -0800154 p->setNotifyCallback(client, notifyFunc);
Wei Jia53692fa2017-12-11 10:33:46 -0800155 } else {
156 ALOGE("Failed to create player object of type %d, initCheck failed"
157 " (res = %d)", playerType, init_result);
158 p.clear();
159 }
160
161 return p;
162}
163
164/*****************************************************************************
165 * *
166 * Built-In Factory Implementations *
167 * *
168 *****************************************************************************/
169
170class NuPlayer2Factory : public MediaPlayer2Factory::IFactory {
171 public:
172 virtual float scoreFactory(const sp<MediaPlayer2Engine>& /*client*/,
173 const char* url,
174 float curScore) {
175 static const float kOurScore = 0.8;
176
177 if (kOurScore <= curScore) {
178 return 0.0;
179 }
180
181 if (!strncasecmp("http://", url, 7)
182 || !strncasecmp("https://", url, 8)
183 || !strncasecmp("file://", url, 7)) {
184 size_t len = strlen(url);
185 if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
186 return kOurScore;
187 }
188
189 if (strstr(url,"m3u8")) {
190 return kOurScore;
191 }
192
193 if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
194 return kOurScore;
195 }
196 }
197
198 if (!strncasecmp("rtsp://", url, 7)) {
199 return kOurScore;
200 }
201
202 return 0.0;
203 }
204
205 virtual float scoreFactory(const sp<MediaPlayer2Engine>& /*client*/,
206 const sp<IStreamSource>& /*source*/,
207 float /*curScore*/) {
208 return 1.0;
209 }
210
211 virtual float scoreFactory(const sp<MediaPlayer2Engine>& /*client*/,
212 const sp<DataSource>& /*source*/,
213 float /*curScore*/) {
214 // Only NuPlayer2 supports setting a DataSource source directly.
215 return 1.0;
216 }
217
218 virtual sp<MediaPlayer2Base> createPlayer(pid_t pid) {
219 ALOGV(" create NuPlayer2");
220 return new NuPlayer2Driver(pid);
221 }
222};
223
224class TestPlayerFactory : public MediaPlayer2Factory::IFactory {
225 public:
226 virtual float scoreFactory(const sp<MediaPlayer2Engine>& /*client*/,
227 const char* url,
228 float /*curScore*/) {
229 if (TestPlayerStub::canBeUsed(url)) {
230 return 1.0;
231 }
232
233 return 0.0;
234 }
235
236 virtual sp<MediaPlayer2Base> createPlayer(pid_t /* pid */) {
237 ALOGV("Create Test Player stub");
238 return new TestPlayerStub();
239 }
240};
241
242void MediaPlayer2Factory::registerBuiltinFactories() {
243 Mutex::Autolock lock_(&sLock);
244
245 if (sInitComplete) {
246 return;
247 }
248
249 IFactory* factory = new NuPlayer2Factory();
250 if (registerFactory_l(factory, PLAYER2_NU_PLAYER2) != OK) {
251 delete factory;
252 }
253 factory = new TestPlayerFactory();
254 if (registerFactory_l(factory, PLAYER2_TEST_PLAYER) != OK) {
255 delete factory;
256 }
257
258 sInitComplete = true;
259}
260
261} // namespace android