• 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/DataSource.h>
24 #include <media/stagefright/FileSource.h>
25 #include <media/stagefright/foundation/ADebug.h>
26 #include <utils/Errors.h>
27 #include <utils/misc.h>
28 #include <../libstagefright/include/WVMExtractor.h>
29 
30 #include "MediaPlayerFactory.h"
31 
32 #include "MidiFile.h"
33 #include "TestPlayerStub.h"
34 #include "StagefrightPlayer.h"
35 #include "nuplayer/NuPlayerDriver.h"
36 
37 namespace android {
38 
39 Mutex MediaPlayerFactory::sLock;
40 MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
41 bool MediaPlayerFactory::sInitComplete = false;
42 
registerFactory_l(IFactory * factory,player_type type)43 status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
44                                                player_type type) {
45     if (NULL == factory) {
46         ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
47               " NULL.", type);
48         return BAD_VALUE;
49     }
50 
51     if (sFactoryMap.indexOfKey(type) >= 0) {
52         ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
53               " already registered.", type);
54         return ALREADY_EXISTS;
55     }
56 
57     if (sFactoryMap.add(type, factory) < 0) {
58         ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
59               " to map.", type);
60         return UNKNOWN_ERROR;
61     }
62 
63     return OK;
64 }
65 
getDefaultPlayerType()66 static player_type getDefaultPlayerType() {
67     char value[PROPERTY_VALUE_MAX];
68     if (property_get("media.stagefright.use-awesome", value, NULL)
69             && (!strcmp("1", value) || !strcasecmp("true", value))) {
70         return STAGEFRIGHT_PLAYER;
71     }
72 
73     // TODO: remove this EXPERIMENTAL developer settings property
74     if (property_get("persist.sys.media.use-awesome", value, NULL)
75             && !strcasecmp("true", value)) {
76         return STAGEFRIGHT_PLAYER;
77     }
78 
79     return NU_PLAYER;
80 }
81 
registerFactory(IFactory * factory,player_type type)82 status_t MediaPlayerFactory::registerFactory(IFactory* factory,
83                                              player_type type) {
84     Mutex::Autolock lock_(&sLock);
85     return registerFactory_l(factory, type);
86 }
87 
unregisterFactory(player_type type)88 void MediaPlayerFactory::unregisterFactory(player_type type) {
89     Mutex::Autolock lock_(&sLock);
90     sFactoryMap.removeItem(type);
91 }
92 
93 #define GET_PLAYER_TYPE_IMPL(a...)                      \
94     Mutex::Autolock lock_(&sLock);                      \
95                                                         \
96     player_type ret = STAGEFRIGHT_PLAYER;               \
97     float bestScore = 0.0;                              \
98                                                         \
99     for (size_t i = 0; i < sFactoryMap.size(); ++i) {   \
100                                                         \
101         IFactory* v = sFactoryMap.valueAt(i);           \
102         float thisScore;                                \
103         CHECK(v != NULL);                               \
104         thisScore = v->scoreFactory(a, bestScore);      \
105         if (thisScore > bestScore) {                    \
106             ret = sFactoryMap.keyAt(i);                 \
107             bestScore = thisScore;                      \
108         }                                               \
109     }                                                   \
110                                                         \
111     if (0.0 == bestScore) {                             \
112         ret = getDefaultPlayerType();                   \
113     }                                                   \
114                                                         \
115     return ret;
116 
getPlayerType(const sp<IMediaPlayer> & client,const char * url)117 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
118                                               const char* url) {
119     GET_PLAYER_TYPE_IMPL(client, url);
120 }
121 
getPlayerType(const sp<IMediaPlayer> & client,int fd,int64_t offset,int64_t length)122 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
123                                               int fd,
124                                               int64_t offset,
125                                               int64_t length) {
126     GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
127 }
128 
getPlayerType(const sp<IMediaPlayer> & client,const sp<IStreamSource> & source)129 player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
130                                               const sp<IStreamSource> &source) {
131     GET_PLAYER_TYPE_IMPL(client, source);
132 }
133 
134 #undef GET_PLAYER_TYPE_IMPL
135 
createPlayer(player_type playerType,void * cookie,notify_callback_f notifyFunc)136 sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
137         player_type playerType,
138         void* cookie,
139         notify_callback_f notifyFunc) {
140     sp<MediaPlayerBase> p;
141     IFactory* factory;
142     status_t init_result;
143     Mutex::Autolock lock_(&sLock);
144 
145     if (sFactoryMap.indexOfKey(playerType) < 0) {
146         ALOGE("Failed to create player object of type %d, no registered"
147               " factory", playerType);
148         return p;
149     }
150 
151     factory = sFactoryMap.valueFor(playerType);
152     CHECK(NULL != factory);
153     p = factory->createPlayer();
154 
155     if (p == NULL) {
156         ALOGE("Failed to create player object of type %d, create failed",
157                playerType);
158         return p;
159     }
160 
161     init_result = p->initCheck();
162     if (init_result == NO_ERROR) {
163         p->setNotifyCallback(cookie, notifyFunc);
164     } else {
165         ALOGE("Failed to create player object of type %d, initCheck failed"
166               " (res = %d)", playerType, init_result);
167         p.clear();
168     }
169 
170     return p;
171 }
172 
173 /*****************************************************************************
174  *                                                                           *
175  *                     Built-In Factory Implementations                      *
176  *                                                                           *
177  *****************************************************************************/
178 
179 class StagefrightPlayerFactory :
180     public MediaPlayerFactory::IFactory {
181   public:
scoreFactory(const sp<IMediaPlayer> &,int fd,int64_t offset,int64_t length,float)182     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
183                                int fd,
184                                int64_t offset,
185                                int64_t length,
186                                float /*curScore*/) {
187         if (legacyDrm()) {
188             sp<DataSource> source = new FileSource(dup(fd), offset, length);
189             String8 mimeType;
190             float confidence;
191             if (SniffWVM(source, &mimeType, &confidence, NULL /* format */)) {
192                 return 1.0;
193             }
194         }
195 
196         if (getDefaultPlayerType() == STAGEFRIGHT_PLAYER) {
197             char buf[20];
198             lseek(fd, offset, SEEK_SET);
199             read(fd, buf, sizeof(buf));
200             lseek(fd, offset, SEEK_SET);
201 
202             uint32_t ident = *((uint32_t*)buf);
203 
204             // Ogg vorbis?
205             if (ident == 0x5367674f) // 'OggS'
206                 return 1.0;
207         }
208 
209         return 0.0;
210     }
211 
scoreFactory(const sp<IMediaPlayer> &,const char * url,float)212     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
213                                const char* url,
214                                float /*curScore*/) {
215         if (legacyDrm() && !strncasecmp("widevine://", url, 11)) {
216             return 1.0;
217         }
218         return 0.0;
219     }
220 
createPlayer()221     virtual sp<MediaPlayerBase> createPlayer() {
222         ALOGV(" create StagefrightPlayer");
223         return new StagefrightPlayer();
224     }
225   private:
legacyDrm()226     bool legacyDrm() {
227         char value[PROPERTY_VALUE_MAX];
228         if (property_get("persist.sys.media.legacy-drm", value, NULL)
229                 && (!strcmp("1", value) || !strcasecmp("true", value))) {
230             return true;
231         }
232         return false;
233     }
234 };
235 
236 class NuPlayerFactory : public MediaPlayerFactory::IFactory {
237   public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float curScore)238     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
239                                const char* url,
240                                float curScore) {
241         static const float kOurScore = 0.8;
242 
243         if (kOurScore <= curScore)
244             return 0.0;
245 
246         if (!strncasecmp("http://", url, 7)
247                 || !strncasecmp("https://", url, 8)
248                 || !strncasecmp("file://", url, 7)) {
249             size_t len = strlen(url);
250             if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
251                 return kOurScore;
252             }
253 
254             if (strstr(url,"m3u8")) {
255                 return kOurScore;
256             }
257 
258             if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
259                 return kOurScore;
260             }
261         }
262 
263         if (!strncasecmp("rtsp://", url, 7)) {
264             return kOurScore;
265         }
266 
267         return 0.0;
268     }
269 
scoreFactory(const sp<IMediaPlayer> &,const sp<IStreamSource> &,float)270     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
271                                const sp<IStreamSource>& /*source*/,
272                                float /*curScore*/) {
273         return 1.0;
274     }
275 
createPlayer()276     virtual sp<MediaPlayerBase> createPlayer() {
277         ALOGV(" create NuPlayer");
278         return new NuPlayerDriver;
279     }
280 };
281 
282 class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
283   public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float curScore)284     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
285                                const char* url,
286                                float curScore) {
287         static const float kOurScore = 0.4;
288         static const char* const FILE_EXTS[] = { ".mid",
289                                                  ".midi",
290                                                  ".smf",
291                                                  ".xmf",
292                                                  ".mxmf",
293                                                  ".imy",
294                                                  ".rtttl",
295                                                  ".rtx",
296                                                  ".ota" };
297         if (kOurScore <= curScore)
298             return 0.0;
299 
300         // use MidiFile for MIDI extensions
301         int lenURL = strlen(url);
302         for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
303             int len = strlen(FILE_EXTS[i]);
304             int start = lenURL - len;
305             if (start > 0) {
306                 if (!strncasecmp(url + start, FILE_EXTS[i], len)) {
307                     return kOurScore;
308                 }
309             }
310         }
311 
312         return 0.0;
313     }
314 
scoreFactory(const sp<IMediaPlayer> &,int fd,int64_t offset,int64_t length,float curScore)315     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
316                                int fd,
317                                int64_t offset,
318                                int64_t length,
319                                float curScore) {
320         static const float kOurScore = 0.8;
321 
322         if (kOurScore <= curScore)
323             return 0.0;
324 
325         // Some kind of MIDI?
326         EAS_DATA_HANDLE easdata;
327         if (EAS_Init(&easdata) == EAS_SUCCESS) {
328             EAS_FILE locator;
329             locator.path = NULL;
330             locator.fd = fd;
331             locator.offset = offset;
332             locator.length = length;
333             EAS_HANDLE  eashandle;
334             if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
335                 EAS_CloseFile(easdata, eashandle);
336                 EAS_Shutdown(easdata);
337                 return kOurScore;
338             }
339             EAS_Shutdown(easdata);
340         }
341 
342         return 0.0;
343     }
344 
createPlayer()345     virtual sp<MediaPlayerBase> createPlayer() {
346         ALOGV(" create MidiFile");
347         return new MidiFile();
348     }
349 };
350 
351 class TestPlayerFactory : public MediaPlayerFactory::IFactory {
352   public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float)353     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
354                                const char* url,
355                                float /*curScore*/) {
356         if (TestPlayerStub::canBeUsed(url)) {
357             return 1.0;
358         }
359 
360         return 0.0;
361     }
362 
createPlayer()363     virtual sp<MediaPlayerBase> createPlayer() {
364         ALOGV("Create Test Player stub");
365         return new TestPlayerStub();
366     }
367 };
368 
registerBuiltinFactories()369 void MediaPlayerFactory::registerBuiltinFactories() {
370     Mutex::Autolock lock_(&sLock);
371 
372     if (sInitComplete)
373         return;
374 
375     registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
376     registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
377     registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
378     registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
379 
380     sInitComplete = true;
381 }
382 
383 }  // namespace android
384