• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_TAG "MediaPlayerFactory"
19 #include <utils/Log.h>
20 
21 #include <cutils/properties.h>
22 #include <media/IMediaPlayer.h>
23 #include <media/stagefright/foundation/ADebug.h>
24 #include <utils/Errors.h>
25 #include <utils/misc.h>
26 
27 #include "MediaPlayerFactory.h"
28 
29 #include "MidiFile.h"
30 #include "TestPlayerStub.h"
31 #include "StagefrightPlayer.h"
32 #include "nuplayer/NuPlayerDriver.h"
33 
34 namespace android {
35 
36 Mutex MediaPlayerFactory::sLock;
37 MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
38 bool MediaPlayerFactory::sInitComplete = false;
39 
registerFactory_l(IFactory * factory,player_type type)40 status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
41                                                player_type type) {
42     if (NULL == factory) {
43         ALOGE("Failed to register MediaPlayerFactory 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 MediaPlayerFactory 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 MediaPlayerFactory of type %d, failed to add"
56               " to map.", type);
57         return UNKNOWN_ERROR;
58     }
59 
60     return OK;
61 }
62 
getDefaultPlayerType()63 player_type MediaPlayerFactory::getDefaultPlayerType() {
64     char value[PROPERTY_VALUE_MAX];
65     if (property_get("media.stagefright.use-nuplayer", value, NULL)
66             && (!strcmp("1", value) || !strcasecmp("true", value))) {
67         return NU_PLAYER;
68     }
69 
70     return STAGEFRIGHT_PLAYER;
71 }
72 
registerFactory(IFactory * factory,player_type type)73 status_t MediaPlayerFactory::registerFactory(IFactory* factory,
74                                              player_type type) {
75     Mutex::Autolock lock_(&sLock);
76     return registerFactory_l(factory, type);
77 }
78 
unregisterFactory(player_type type)79 void MediaPlayerFactory::unregisterFactory(player_type type) {
80     Mutex::Autolock lock_(&sLock);
81     sFactoryMap.removeItem(type);
82 }
83 
84 #define GET_PLAYER_TYPE_IMPL(a...)                      \
85     Mutex::Autolock lock_(&sLock);                      \
86                                                         \
87     player_type ret = STAGEFRIGHT_PLAYER;               \
88     float bestScore = 0.0;                              \
89                                                         \
90     for (size_t i = 0; i < sFactoryMap.size(); ++i) {   \
91                                                         \
92         IFactory* v = sFactoryMap.valueAt(i);           \
93         float thisScore;                                \
94         CHECK(v != NULL);                               \
95         thisScore = v->scoreFactory(a, bestScore);      \
96         if (thisScore > bestScore) {                    \
97             ret = sFactoryMap.keyAt(i);                 \
98             bestScore = thisScore;                      \
99         }                                               \
100     }                                                   \
101                                                         \
102     if (0.0 == bestScore) {                             \
103         bestScore = getDefaultPlayerType();             \
104     }                                                   \
105                                                         \
106     return ret;
107 
getPlayerType(const sp<IMediaPlayer> & client,const char * url)108 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
109                                               const char* url) {
110     GET_PLAYER_TYPE_IMPL(client, url);
111 }
112 
getPlayerType(const sp<IMediaPlayer> & client,int fd,int64_t offset,int64_t length)113 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
114                                               int fd,
115                                               int64_t offset,
116                                               int64_t length) {
117     GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
118 }
119 
getPlayerType(const sp<IMediaPlayer> & client,const sp<IStreamSource> & source)120 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
121                                               const sp<IStreamSource> &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)127 sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
128         player_type playerType,
129         void* cookie,
130         notify_callback_f notifyFunc) {
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();
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(cookie, notifyFunc);
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 StagefrightPlayerFactory :
171     public MediaPlayerFactory::IFactory {
172   public:
scoreFactory(const sp<IMediaPlayer> & client,int fd,int64_t offset,int64_t length,float curScore)173     virtual float scoreFactory(const sp<IMediaPlayer>& client,
174                                int fd,
175                                int64_t offset,
176                                int64_t length,
177                                float curScore) {
178         char buf[20];
179         lseek(fd, offset, SEEK_SET);
180         read(fd, buf, sizeof(buf));
181         lseek(fd, offset, SEEK_SET);
182 
183         long ident = *((long*)buf);
184 
185         // Ogg vorbis?
186         if (ident == 0x5367674f) // 'OggS'
187             return 1.0;
188 
189         return 0.0;
190     }
191 
createPlayer()192     virtual sp<MediaPlayerBase> createPlayer() {
193         ALOGV(" create StagefrightPlayer");
194         return new StagefrightPlayer();
195     }
196 };
197 
198 class NuPlayerFactory : public MediaPlayerFactory::IFactory {
199   public:
scoreFactory(const sp<IMediaPlayer> & client,const char * url,float curScore)200     virtual float scoreFactory(const sp<IMediaPlayer>& client,
201                                const char* url,
202                                float curScore) {
203         static const float kOurScore = 0.8;
204 
205         if (kOurScore <= curScore)
206             return 0.0;
207 
208         if (!strncasecmp("http://", url, 7)
209                 || !strncasecmp("https://", url, 8)) {
210             size_t len = strlen(url);
211             if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
212                 return kOurScore;
213             }
214 
215             if (strstr(url,"m3u8")) {
216                 return kOurScore;
217             }
218         }
219 
220         if (!strncasecmp("rtsp://", url, 7)) {
221             return kOurScore;
222         }
223 
224         return 0.0;
225     }
226 
scoreFactory(const sp<IMediaPlayer> & client,const sp<IStreamSource> & source,float curScore)227     virtual float scoreFactory(const sp<IMediaPlayer>& client,
228                                const sp<IStreamSource> &source,
229                                float curScore) {
230         return 1.0;
231     }
232 
createPlayer()233     virtual sp<MediaPlayerBase> createPlayer() {
234         ALOGV(" create NuPlayer");
235         return new NuPlayerDriver;
236     }
237 };
238 
239 class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
240   public:
scoreFactory(const sp<IMediaPlayer> & client,const char * url,float curScore)241     virtual float scoreFactory(const sp<IMediaPlayer>& client,
242                                const char* url,
243                                float curScore) {
244         static const float kOurScore = 0.4;
245         static const char* const FILE_EXTS[] = { ".mid",
246                                                  ".midi",
247                                                  ".smf",
248                                                  ".xmf",
249                                                  ".mxmf",
250                                                  ".imy",
251                                                  ".rtttl",
252                                                  ".rtx",
253                                                  ".ota" };
254         if (kOurScore <= curScore)
255             return 0.0;
256 
257         // use MidiFile for MIDI extensions
258         int lenURL = strlen(url);
259         for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
260             int len = strlen(FILE_EXTS[i]);
261             int start = lenURL - len;
262             if (start > 0) {
263                 if (!strncasecmp(url + start, FILE_EXTS[i], len)) {
264                     return kOurScore;
265                 }
266             }
267         }
268 
269         return 0.0;
270     }
271 
scoreFactory(const sp<IMediaPlayer> & client,int fd,int64_t offset,int64_t length,float curScore)272     virtual float scoreFactory(const sp<IMediaPlayer>& client,
273                                int fd,
274                                int64_t offset,
275                                int64_t length,
276                                float curScore) {
277         static const float kOurScore = 0.8;
278 
279         if (kOurScore <= curScore)
280             return 0.0;
281 
282         // Some kind of MIDI?
283         EAS_DATA_HANDLE easdata;
284         if (EAS_Init(&easdata) == EAS_SUCCESS) {
285             EAS_FILE locator;
286             locator.path = NULL;
287             locator.fd = fd;
288             locator.offset = offset;
289             locator.length = length;
290             EAS_HANDLE  eashandle;
291             if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
292                 EAS_CloseFile(easdata, eashandle);
293                 EAS_Shutdown(easdata);
294                 return kOurScore;
295             }
296             EAS_Shutdown(easdata);
297         }
298 
299         return 0.0;
300     }
301 
createPlayer()302     virtual sp<MediaPlayerBase> createPlayer() {
303         ALOGV(" create MidiFile");
304         return new MidiFile();
305     }
306 };
307 
308 class TestPlayerFactory : public MediaPlayerFactory::IFactory {
309   public:
scoreFactory(const sp<IMediaPlayer> & client,const char * url,float curScore)310     virtual float scoreFactory(const sp<IMediaPlayer>& client,
311                                const char* url,
312                                float curScore) {
313         if (TestPlayerStub::canBeUsed(url)) {
314             return 1.0;
315         }
316 
317         return 0.0;
318     }
319 
createPlayer()320     virtual sp<MediaPlayerBase> createPlayer() {
321         ALOGV("Create Test Player stub");
322         return new TestPlayerStub();
323     }
324 };
325 
registerBuiltinFactories()326 void MediaPlayerFactory::registerBuiltinFactories() {
327     Mutex::Autolock lock_(&sLock);
328 
329     if (sInitComplete)
330         return;
331 
332     registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
333     registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
334     registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
335     registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
336 
337     sInitComplete = true;
338 }
339 
340 }  // namespace android
341