1 /*
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 
18 //#define LOG_NDEBUG 0
19 #define LOG_TAG "MediaPlayerFactory"
20 #include <utils/Log.h>
21 
22 #include <cutils/properties.h>
23 #include <media/IMediaPlayer.h>
24 #include <media/stagefright/DataSource.h>
25 #include <media/stagefright/FileSource.h>
26 #include <media/stagefright/foundation/ADebug.h>
27 #include <utils/Errors.h>
28 #include <utils/misc.h>
29 
30 #include "MediaPlayerFactory.h"
31 
32 #include "TestPlayerStub.h"
33 #include "nuplayer/NuPlayerDriver.h"
34 
35 namespace android {
36 
37 Mutex MediaPlayerFactory::sLock;
38 MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
39 bool MediaPlayerFactory::sInitComplete = false;
40 
registerFactory_l(IFactory * factory,player_type type)41 status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
42                                                player_type type) {
43     if (NULL == factory) {
44         ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
45               " NULL.", type);
46         return BAD_VALUE;
47     }
48 
49     if (sFactoryMap.indexOfKey(type) >= 0) {
50         ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
51               " already registered.", type);
52         return ALREADY_EXISTS;
53     }
54 
55     if (sFactoryMap.add(type, factory) < 0) {
56         ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
57               " to map.", type);
58         return UNKNOWN_ERROR;
59     }
60 
61     return OK;
62 }
63 
getDefaultPlayerType()64 static player_type getDefaultPlayerType() {
65     return NU_PLAYER;
66 }
67 
registerFactory(IFactory * factory,player_type type)68 status_t MediaPlayerFactory::registerFactory(IFactory* factory,
69                                              player_type type) {
70     Mutex::Autolock lock_(&sLock);
71     return registerFactory_l(factory, type);
72 }
73 
unregisterFactory(player_type type)74 void MediaPlayerFactory::unregisterFactory(player_type type) {
75     Mutex::Autolock lock_(&sLock);
76     sFactoryMap.removeItem(type);
77 }
78 
79 #define GET_PLAYER_TYPE_IMPL(a...)                      \
80     Mutex::Autolock lock_(&sLock);                      \
81                                                         \
82     player_type ret = STAGEFRIGHT_PLAYER;               \
83     float bestScore = 0.0;                              \
84                                                         \
85     for (size_t i = 0; i < sFactoryMap.size(); ++i) {   \
86                                                         \
87         IFactory* v = sFactoryMap.valueAt(i);           \
88         float thisScore;                                \
89         CHECK(v != NULL);                               \
90         thisScore = v->scoreFactory(a, bestScore);      \
91         if (thisScore > bestScore) {                    \
92             ret = sFactoryMap.keyAt(i);                 \
93             bestScore = thisScore;                      \
94         }                                               \
95     }                                                   \
96                                                         \
97     if (0.0 == bestScore) {                             \
98         ret = getDefaultPlayerType();                   \
99     }                                                   \
100                                                         \
101     return ret;
102 
getPlayerType(const sp<IMediaPlayer> & client,const char * url)103 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
104                                               const char* url) {
105     GET_PLAYER_TYPE_IMPL(client, url);
106 }
107 
getPlayerType(const sp<IMediaPlayer> & client,int fd,int64_t offset,int64_t length)108 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
109                                               int fd,
110                                               int64_t offset,
111                                               int64_t length) {
112     GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
113 }
114 
getPlayerType(const sp<IMediaPlayer> & client,const sp<IStreamSource> & source)115 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
116                                               const sp<IStreamSource> &source) {
117     GET_PLAYER_TYPE_IMPL(client, source);
118 }
119 
getPlayerType(const sp<IMediaPlayer> & client,const sp<DataSource> & source)120 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
121                                               const sp<DataSource> &source) {
122     GET_PLAYER_TYPE_IMPL(client, source);
123 }
124 
125 #undef GET_PLAYER_TYPE_IMPL
126 
createPlayer(player_type playerType,void * cookie,notify_callback_f notifyFunc,pid_t pid)127 sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
128         player_type playerType,
129         void* cookie,
130         notify_callback_f notifyFunc,
131         pid_t pid) {
132     sp<MediaPlayerBase> p;
133     IFactory* factory;
134     status_t init_result;
135     Mutex::Autolock lock_(&sLock);
136 
137     if (sFactoryMap.indexOfKey(playerType) < 0) {
138         ALOGE("Failed to create player object of type %d, no registered"
139               " factory", playerType);
140         return p;
141     }
142 
143     factory = sFactoryMap.valueFor(playerType);
144     CHECK(NULL != factory);
145     p = factory->createPlayer(pid);
146 
147     if (p == NULL) {
148         ALOGE("Failed to create player object of type %d, create failed",
149                playerType);
150         return p;
151     }
152 
153     init_result = p->initCheck();
154     if (init_result == NO_ERROR) {
155         p->setNotifyCallback(cookie, notifyFunc);
156     } else {
157         ALOGE("Failed to create player object of type %d, initCheck failed"
158               " (res = %d)", playerType, init_result);
159         p.clear();
160     }
161 
162     return p;
163 }
164 
165 /*****************************************************************************
166  *                                                                           *
167  *                     Built-In Factory Implementations                      *
168  *                                                                           *
169  *****************************************************************************/
170 
171 class NuPlayerFactory : public MediaPlayerFactory::IFactory {
172   public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float curScore)173     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
174                                const char* url,
175                                float curScore) {
176         static const float kOurScore = 0.8;
177 
178         if (kOurScore <= curScore)
179             return 0.0;
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 
scoreFactory(const sp<IMediaPlayer> &,const sp<IStreamSource> &,float)205     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
206                                const sp<IStreamSource>& /*source*/,
207                                float /*curScore*/) {
208         return 1.0;
209     }
210 
scoreFactory(const sp<IMediaPlayer> &,const sp<DataSource> &,float)211     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
212                                const sp<DataSource>& /*source*/,
213                                float /*curScore*/) {
214         // Only NuPlayer supports setting a DataSource source directly.
215         return 1.0;
216     }
217 
createPlayer(pid_t pid)218     virtual sp<MediaPlayerBase> createPlayer(pid_t pid) {
219         ALOGV(" create NuPlayer");
220         return new NuPlayerDriver(pid);
221     }
222 };
223 
224 class TestPlayerFactory : public MediaPlayerFactory::IFactory {
225   public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float)226     virtual float scoreFactory(const sp<IMediaPlayer>& /*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 
createPlayer(pid_t)236     virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) {
237         ALOGV("Create Test Player stub");
238         return new TestPlayerStub();
239     }
240 };
241 
registerBuiltinFactories()242 void MediaPlayerFactory::registerBuiltinFactories() {
243     Mutex::Autolock lock_(&sLock);
244 
245     if (sInitComplete)
246         return;
247 
248     registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
249     registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
250 
251     sInitComplete = true;
252 }
253 
254 }  // namespace android
255