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