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 <datasource/FileSource.h>
24 #include <media/DataSource.h>
25 #include <media/IMediaPlayer.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,const sp<MediaPlayerBase::Listener> & listener,pid_t pid)127 sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
128         player_type playerType,
129         const sp<MediaPlayerBase::Listener> &listener,
130         pid_t pid) {
131     sp<MediaPlayerBase> 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) {
154         p->setNotifyCallback(listener);
155     } 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 
170 class NuPlayerFactory : public MediaPlayerFactory::IFactory {
171   public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float curScore)172     virtual float scoreFactory(const sp<IMediaPlayer>& /*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         if (!strncasecmp("http://", url, 7)
181                 || !strncasecmp("https://", url, 8)
182                 || !strncasecmp("file://", url, 7)) {
183             size_t len = strlen(url);
184             if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
185                 return kOurScore;
186             }
187 
188             if (strstr(url,"m3u8")) {
189                 return kOurScore;
190             }
191 
192             if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
193                 return kOurScore;
194             }
195         }
196 
197         if (!strncasecmp("rtsp://", url, 7)) {
198             return kOurScore;
199         }
200 
201         return 0.0;
202     }
203 
scoreFactory(const sp<IMediaPlayer> &,const sp<IStreamSource> &,float)204     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
205                                const sp<IStreamSource>& /*source*/,
206                                float /*curScore*/) {
207         return 1.0;
208     }
209 
scoreFactory(const sp<IMediaPlayer> &,const sp<DataSource> &,float)210     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
211                                const sp<DataSource>& /*source*/,
212                                float /*curScore*/) {
213         // Only NuPlayer supports setting a DataSource source directly.
214         return 1.0;
215     }
216 
createPlayer(pid_t pid)217     virtual sp<MediaPlayerBase> createPlayer(pid_t pid) {
218         ALOGV(" create NuPlayer");
219         return new NuPlayerDriver(pid);
220     }
221 };
222 
223 class TestPlayerFactory : public MediaPlayerFactory::IFactory {
224   public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float)225     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
226                                const char* url,
227                                float /*curScore*/) {
228         if (TestPlayerStub::canBeUsed(url)) {
229             return 1.0;
230         }
231 
232         return 0.0;
233     }
234 
createPlayer(pid_t)235     virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) {
236         ALOGV("Create Test Player stub");
237         return new TestPlayerStub();
238     }
239 };
240 
registerBuiltinFactories()241 void MediaPlayerFactory::registerBuiltinFactories() {
242     Mutex::Autolock lock_(&sLock);
243 
244     if (sInitComplete)
245         return;
246 
247     IFactory* factory = new NuPlayerFactory();
248     if (registerFactory_l(factory, NU_PLAYER) != OK)
249         delete factory;
250     factory = new TestPlayerFactory();
251     if (registerFactory_l(factory, TEST_PLAYER) != OK)
252         delete factory;
253 
254     sInitComplete = true;
255 }
256 
257 }  // namespace android
258