1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker **
3*ec779b8eSAndroid Build Coastguard Worker ** Copyright 2012, The Android Open Source Project
4*ec779b8eSAndroid Build Coastguard Worker **
5*ec779b8eSAndroid Build Coastguard Worker ** Licensed under the Apache License, Version 2.0 (the "License");
6*ec779b8eSAndroid Build Coastguard Worker ** you may not use this file except in compliance with the License.
7*ec779b8eSAndroid Build Coastguard Worker ** You may obtain a copy of the License at
8*ec779b8eSAndroid Build Coastguard Worker **
9*ec779b8eSAndroid Build Coastguard Worker ** http://www.apache.org/licenses/LICENSE-2.0
10*ec779b8eSAndroid Build Coastguard Worker **
11*ec779b8eSAndroid Build Coastguard Worker ** Unless required by applicable law or agreed to in writing, software
12*ec779b8eSAndroid Build Coastguard Worker ** distributed under the License is distributed on an "AS IS" BASIS,
13*ec779b8eSAndroid Build Coastguard Worker ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*ec779b8eSAndroid Build Coastguard Worker ** See the License for the specific language governing permissions and
15*ec779b8eSAndroid Build Coastguard Worker ** limitations under the License.
16*ec779b8eSAndroid Build Coastguard Worker */
17*ec779b8eSAndroid Build Coastguard Worker
18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "MediaPlayerFactory"
20*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
21*ec779b8eSAndroid Build Coastguard Worker
22*ec779b8eSAndroid Build Coastguard Worker #include <cutils/properties.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <datasource/FileSource.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <media/DataSource.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/IMediaPlayer.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <utils/Errors.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <utils/misc.h>
29*ec779b8eSAndroid Build Coastguard Worker
30*ec779b8eSAndroid Build Coastguard Worker #include "MediaPlayerFactory.h"
31*ec779b8eSAndroid Build Coastguard Worker
32*ec779b8eSAndroid Build Coastguard Worker #include "TestPlayerStub.h"
33*ec779b8eSAndroid Build Coastguard Worker #include <nuplayer/NuPlayerDriver.h>
34*ec779b8eSAndroid Build Coastguard Worker
35*ec779b8eSAndroid Build Coastguard Worker namespace android {
36*ec779b8eSAndroid Build Coastguard Worker
37*ec779b8eSAndroid Build Coastguard Worker Mutex MediaPlayerFactory::sLock;
38*ec779b8eSAndroid Build Coastguard Worker MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
39*ec779b8eSAndroid Build Coastguard Worker bool MediaPlayerFactory::sInitComplete = false;
40*ec779b8eSAndroid Build Coastguard Worker
registerFactory_l(IFactory * factory,player_type type)41*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
42*ec779b8eSAndroid Build Coastguard Worker player_type type) {
43*ec779b8eSAndroid Build Coastguard Worker if (NULL == factory) {
44*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
45*ec779b8eSAndroid Build Coastguard Worker " NULL.", type);
46*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
47*ec779b8eSAndroid Build Coastguard Worker }
48*ec779b8eSAndroid Build Coastguard Worker
49*ec779b8eSAndroid Build Coastguard Worker if (sFactoryMap.indexOfKey(type) >= 0) {
50*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
51*ec779b8eSAndroid Build Coastguard Worker " already registered.", type);
52*ec779b8eSAndroid Build Coastguard Worker return ALREADY_EXISTS;
53*ec779b8eSAndroid Build Coastguard Worker }
54*ec779b8eSAndroid Build Coastguard Worker
55*ec779b8eSAndroid Build Coastguard Worker if (sFactoryMap.add(type, factory) < 0) {
56*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
57*ec779b8eSAndroid Build Coastguard Worker " to map.", type);
58*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
59*ec779b8eSAndroid Build Coastguard Worker }
60*ec779b8eSAndroid Build Coastguard Worker
61*ec779b8eSAndroid Build Coastguard Worker return OK;
62*ec779b8eSAndroid Build Coastguard Worker }
63*ec779b8eSAndroid Build Coastguard Worker
getDefaultPlayerType()64*ec779b8eSAndroid Build Coastguard Worker static player_type getDefaultPlayerType() {
65*ec779b8eSAndroid Build Coastguard Worker return NU_PLAYER;
66*ec779b8eSAndroid Build Coastguard Worker }
67*ec779b8eSAndroid Build Coastguard Worker
registerFactory(IFactory * factory,player_type type)68*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerFactory::registerFactory(IFactory* factory,
69*ec779b8eSAndroid Build Coastguard Worker player_type type) {
70*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock_(&sLock);
71*ec779b8eSAndroid Build Coastguard Worker return registerFactory_l(factory, type);
72*ec779b8eSAndroid Build Coastguard Worker }
73*ec779b8eSAndroid Build Coastguard Worker
unregisterFactory(player_type type)74*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerFactory::unregisterFactory(player_type type) {
75*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock_(&sLock);
76*ec779b8eSAndroid Build Coastguard Worker sFactoryMap.removeItem(type);
77*ec779b8eSAndroid Build Coastguard Worker }
78*ec779b8eSAndroid Build Coastguard Worker
79*ec779b8eSAndroid Build Coastguard Worker #define GET_PLAYER_TYPE_IMPL(a...) \
80*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock_(&sLock); \
81*ec779b8eSAndroid Build Coastguard Worker \
82*ec779b8eSAndroid Build Coastguard Worker player_type ret = STAGEFRIGHT_PLAYER; \
83*ec779b8eSAndroid Build Coastguard Worker float bestScore = 0.0; \
84*ec779b8eSAndroid Build Coastguard Worker \
85*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
86*ec779b8eSAndroid Build Coastguard Worker \
87*ec779b8eSAndroid Build Coastguard Worker IFactory* v = sFactoryMap.valueAt(i); \
88*ec779b8eSAndroid Build Coastguard Worker float thisScore; \
89*ec779b8eSAndroid Build Coastguard Worker CHECK(v != NULL); \
90*ec779b8eSAndroid Build Coastguard Worker thisScore = v->scoreFactory(a, bestScore); \
91*ec779b8eSAndroid Build Coastguard Worker if (thisScore > bestScore) { \
92*ec779b8eSAndroid Build Coastguard Worker ret = sFactoryMap.keyAt(i); \
93*ec779b8eSAndroid Build Coastguard Worker bestScore = thisScore; \
94*ec779b8eSAndroid Build Coastguard Worker } \
95*ec779b8eSAndroid Build Coastguard Worker } \
96*ec779b8eSAndroid Build Coastguard Worker \
97*ec779b8eSAndroid Build Coastguard Worker if (0.0 == bestScore) { \
98*ec779b8eSAndroid Build Coastguard Worker ret = getDefaultPlayerType(); \
99*ec779b8eSAndroid Build Coastguard Worker } \
100*ec779b8eSAndroid Build Coastguard Worker \
101*ec779b8eSAndroid Build Coastguard Worker return ret;
102*ec779b8eSAndroid Build Coastguard Worker
getPlayerType(const sp<IMediaPlayer> & client,const char * url)103*ec779b8eSAndroid Build Coastguard Worker player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
104*ec779b8eSAndroid Build Coastguard Worker const char* url) {
105*ec779b8eSAndroid Build Coastguard Worker GET_PLAYER_TYPE_IMPL(client, url);
106*ec779b8eSAndroid Build Coastguard Worker }
107*ec779b8eSAndroid Build Coastguard Worker
getPlayerType(const sp<IMediaPlayer> & client,int fd,int64_t offset,int64_t length)108*ec779b8eSAndroid Build Coastguard Worker player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
109*ec779b8eSAndroid Build Coastguard Worker int fd,
110*ec779b8eSAndroid Build Coastguard Worker int64_t offset,
111*ec779b8eSAndroid Build Coastguard Worker int64_t length) {
112*ec779b8eSAndroid Build Coastguard Worker GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
113*ec779b8eSAndroid Build Coastguard Worker }
114*ec779b8eSAndroid Build Coastguard Worker
getPlayerType(const sp<IMediaPlayer> & client,const sp<IStreamSource> & source)115*ec779b8eSAndroid Build Coastguard Worker player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
116*ec779b8eSAndroid Build Coastguard Worker const sp<IStreamSource> &source) {
117*ec779b8eSAndroid Build Coastguard Worker GET_PLAYER_TYPE_IMPL(client, source);
118*ec779b8eSAndroid Build Coastguard Worker }
119*ec779b8eSAndroid Build Coastguard Worker
getPlayerType(const sp<IMediaPlayer> & client,const sp<DataSource> & source)120*ec779b8eSAndroid Build Coastguard Worker player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
121*ec779b8eSAndroid Build Coastguard Worker const sp<DataSource> &source) {
122*ec779b8eSAndroid Build Coastguard Worker GET_PLAYER_TYPE_IMPL(client, source);
123*ec779b8eSAndroid Build Coastguard Worker }
124*ec779b8eSAndroid Build Coastguard Worker
125*ec779b8eSAndroid Build Coastguard Worker #undef GET_PLAYER_TYPE_IMPL
126*ec779b8eSAndroid Build Coastguard Worker
createPlayer(player_type playerType,const sp<MediaPlayerBase::Listener> & listener,pid_t pid)127*ec779b8eSAndroid Build Coastguard Worker sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
128*ec779b8eSAndroid Build Coastguard Worker player_type playerType,
129*ec779b8eSAndroid Build Coastguard Worker const sp<MediaPlayerBase::Listener> &listener,
130*ec779b8eSAndroid Build Coastguard Worker pid_t pid) {
131*ec779b8eSAndroid Build Coastguard Worker sp<MediaPlayerBase> p;
132*ec779b8eSAndroid Build Coastguard Worker IFactory* factory;
133*ec779b8eSAndroid Build Coastguard Worker status_t init_result;
134*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock_(&sLock);
135*ec779b8eSAndroid Build Coastguard Worker
136*ec779b8eSAndroid Build Coastguard Worker if (sFactoryMap.indexOfKey(playerType) < 0) {
137*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to create player object of type %d, no registered"
138*ec779b8eSAndroid Build Coastguard Worker " factory", playerType);
139*ec779b8eSAndroid Build Coastguard Worker return p;
140*ec779b8eSAndroid Build Coastguard Worker }
141*ec779b8eSAndroid Build Coastguard Worker
142*ec779b8eSAndroid Build Coastguard Worker factory = sFactoryMap.valueFor(playerType);
143*ec779b8eSAndroid Build Coastguard Worker CHECK(NULL != factory);
144*ec779b8eSAndroid Build Coastguard Worker p = factory->createPlayer(pid);
145*ec779b8eSAndroid Build Coastguard Worker
146*ec779b8eSAndroid Build Coastguard Worker if (p == NULL) {
147*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to create player object of type %d, create failed",
148*ec779b8eSAndroid Build Coastguard Worker playerType);
149*ec779b8eSAndroid Build Coastguard Worker return p;
150*ec779b8eSAndroid Build Coastguard Worker }
151*ec779b8eSAndroid Build Coastguard Worker
152*ec779b8eSAndroid Build Coastguard Worker init_result = p->initCheck();
153*ec779b8eSAndroid Build Coastguard Worker if (init_result == NO_ERROR) {
154*ec779b8eSAndroid Build Coastguard Worker p->setNotifyCallback(listener);
155*ec779b8eSAndroid Build Coastguard Worker } else {
156*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to create player object of type %d, initCheck failed"
157*ec779b8eSAndroid Build Coastguard Worker " (res = %d)", playerType, init_result);
158*ec779b8eSAndroid Build Coastguard Worker p.clear();
159*ec779b8eSAndroid Build Coastguard Worker }
160*ec779b8eSAndroid Build Coastguard Worker
161*ec779b8eSAndroid Build Coastguard Worker return p;
162*ec779b8eSAndroid Build Coastguard Worker }
163*ec779b8eSAndroid Build Coastguard Worker
164*ec779b8eSAndroid Build Coastguard Worker /*****************************************************************************
165*ec779b8eSAndroid Build Coastguard Worker * *
166*ec779b8eSAndroid Build Coastguard Worker * Built-In Factory Implementations *
167*ec779b8eSAndroid Build Coastguard Worker * *
168*ec779b8eSAndroid Build Coastguard Worker *****************************************************************************/
169*ec779b8eSAndroid Build Coastguard Worker
170*ec779b8eSAndroid Build Coastguard Worker class NuPlayerFactory : public MediaPlayerFactory::IFactory {
171*ec779b8eSAndroid Build Coastguard Worker public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float curScore)172*ec779b8eSAndroid Build Coastguard Worker virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
173*ec779b8eSAndroid Build Coastguard Worker const char* url,
174*ec779b8eSAndroid Build Coastguard Worker float curScore) {
175*ec779b8eSAndroid Build Coastguard Worker static const float kOurScore = 0.8;
176*ec779b8eSAndroid Build Coastguard Worker
177*ec779b8eSAndroid Build Coastguard Worker if (kOurScore <= curScore)
178*ec779b8eSAndroid Build Coastguard Worker return 0.0;
179*ec779b8eSAndroid Build Coastguard Worker
180*ec779b8eSAndroid Build Coastguard Worker if (!strncasecmp("http://", url, 7)
181*ec779b8eSAndroid Build Coastguard Worker || !strncasecmp("https://", url, 8)
182*ec779b8eSAndroid Build Coastguard Worker || !strncasecmp("file://", url, 7)) {
183*ec779b8eSAndroid Build Coastguard Worker size_t len = strlen(url);
184*ec779b8eSAndroid Build Coastguard Worker if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
185*ec779b8eSAndroid Build Coastguard Worker return kOurScore;
186*ec779b8eSAndroid Build Coastguard Worker }
187*ec779b8eSAndroid Build Coastguard Worker
188*ec779b8eSAndroid Build Coastguard Worker if (strstr(url,"m3u8")) {
189*ec779b8eSAndroid Build Coastguard Worker return kOurScore;
190*ec779b8eSAndroid Build Coastguard Worker }
191*ec779b8eSAndroid Build Coastguard Worker
192*ec779b8eSAndroid Build Coastguard Worker if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
193*ec779b8eSAndroid Build Coastguard Worker return kOurScore;
194*ec779b8eSAndroid Build Coastguard Worker }
195*ec779b8eSAndroid Build Coastguard Worker }
196*ec779b8eSAndroid Build Coastguard Worker
197*ec779b8eSAndroid Build Coastguard Worker if (!strncasecmp("rtsp://", url, 7)) {
198*ec779b8eSAndroid Build Coastguard Worker return kOurScore;
199*ec779b8eSAndroid Build Coastguard Worker }
200*ec779b8eSAndroid Build Coastguard Worker
201*ec779b8eSAndroid Build Coastguard Worker return 0.0;
202*ec779b8eSAndroid Build Coastguard Worker }
203*ec779b8eSAndroid Build Coastguard Worker
scoreFactory(const sp<IMediaPlayer> &,const sp<IStreamSource> &,float)204*ec779b8eSAndroid Build Coastguard Worker virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
205*ec779b8eSAndroid Build Coastguard Worker const sp<IStreamSource>& /*source*/,
206*ec779b8eSAndroid Build Coastguard Worker float /*curScore*/) {
207*ec779b8eSAndroid Build Coastguard Worker return 1.0;
208*ec779b8eSAndroid Build Coastguard Worker }
209*ec779b8eSAndroid Build Coastguard Worker
scoreFactory(const sp<IMediaPlayer> &,const sp<DataSource> &,float)210*ec779b8eSAndroid Build Coastguard Worker virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
211*ec779b8eSAndroid Build Coastguard Worker const sp<DataSource>& /*source*/,
212*ec779b8eSAndroid Build Coastguard Worker float /*curScore*/) {
213*ec779b8eSAndroid Build Coastguard Worker // Only NuPlayer supports setting a DataSource source directly.
214*ec779b8eSAndroid Build Coastguard Worker return 1.0;
215*ec779b8eSAndroid Build Coastguard Worker }
216*ec779b8eSAndroid Build Coastguard Worker
createPlayer(pid_t pid)217*ec779b8eSAndroid Build Coastguard Worker virtual sp<MediaPlayerBase> createPlayer(pid_t pid) {
218*ec779b8eSAndroid Build Coastguard Worker ALOGV(" create NuPlayer");
219*ec779b8eSAndroid Build Coastguard Worker return new NuPlayerDriver(pid);
220*ec779b8eSAndroid Build Coastguard Worker }
221*ec779b8eSAndroid Build Coastguard Worker };
222*ec779b8eSAndroid Build Coastguard Worker
223*ec779b8eSAndroid Build Coastguard Worker class TestPlayerFactory : public MediaPlayerFactory::IFactory {
224*ec779b8eSAndroid Build Coastguard Worker public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float)225*ec779b8eSAndroid Build Coastguard Worker virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
226*ec779b8eSAndroid Build Coastguard Worker const char* url,
227*ec779b8eSAndroid Build Coastguard Worker float /*curScore*/) {
228*ec779b8eSAndroid Build Coastguard Worker if (TestPlayerStub::canBeUsed(url)) {
229*ec779b8eSAndroid Build Coastguard Worker return 1.0;
230*ec779b8eSAndroid Build Coastguard Worker }
231*ec779b8eSAndroid Build Coastguard Worker
232*ec779b8eSAndroid Build Coastguard Worker return 0.0;
233*ec779b8eSAndroid Build Coastguard Worker }
234*ec779b8eSAndroid Build Coastguard Worker
createPlayer(pid_t)235*ec779b8eSAndroid Build Coastguard Worker virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) {
236*ec779b8eSAndroid Build Coastguard Worker ALOGV("Create Test Player stub");
237*ec779b8eSAndroid Build Coastguard Worker return new TestPlayerStub();
238*ec779b8eSAndroid Build Coastguard Worker }
239*ec779b8eSAndroid Build Coastguard Worker };
240*ec779b8eSAndroid Build Coastguard Worker
registerBuiltinFactories()241*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerFactory::registerBuiltinFactories() {
242*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock_(&sLock);
243*ec779b8eSAndroid Build Coastguard Worker
244*ec779b8eSAndroid Build Coastguard Worker if (sInitComplete)
245*ec779b8eSAndroid Build Coastguard Worker return;
246*ec779b8eSAndroid Build Coastguard Worker
247*ec779b8eSAndroid Build Coastguard Worker IFactory* factory = new NuPlayerFactory();
248*ec779b8eSAndroid Build Coastguard Worker if (registerFactory_l(factory, NU_PLAYER) != OK)
249*ec779b8eSAndroid Build Coastguard Worker delete factory;
250*ec779b8eSAndroid Build Coastguard Worker factory = new TestPlayerFactory();
251*ec779b8eSAndroid Build Coastguard Worker if (registerFactory_l(factory, TEST_PLAYER) != OK)
252*ec779b8eSAndroid Build Coastguard Worker delete factory;
253*ec779b8eSAndroid Build Coastguard Worker
254*ec779b8eSAndroid Build Coastguard Worker sInitComplete = true;
255*ec779b8eSAndroid Build Coastguard Worker }
256*ec779b8eSAndroid Build Coastguard Worker
257*ec779b8eSAndroid Build Coastguard Worker } // namespace android
258