MediaPlayerFactory.cpp revision ca7b4bc40604ae4f06718cb34945fdab278987ae
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
37namespace android {
38
39Mutex MediaPlayerFactory::sLock;
40MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
41bool MediaPlayerFactory::sInitComplete = false;
42
43status_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
66static 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
82status_t MediaPlayerFactory::registerFactory(IFactory* factory,
83                                             player_type type) {
84    Mutex::Autolock lock_(&sLock);
85    return registerFactory_l(factory, type);
86}
87
88void 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
117player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
118                                              const char* url) {
119    GET_PLAYER_TYPE_IMPL(client, url);
120}
121
122player_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
129player_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
136sp<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
179class StagefrightPlayerFactory :
180    public MediaPlayerFactory::IFactory {
181  public:
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
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
221    virtual sp<MediaPlayerBase> createPlayer() {
222        ALOGV(" create StagefrightPlayer");
223        return new StagefrightPlayer();
224    }
225  private:
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
236class NuPlayerFactory : public MediaPlayerFactory::IFactory {
237  public:
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
270    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
271                               const sp<IStreamSource>& /*source*/,
272                               float /*curScore*/) {
273        return 1.0;
274    }
275
276    virtual sp<MediaPlayerBase> createPlayer() {
277        ALOGV(" create NuPlayer");
278        return new NuPlayerDriver;
279    }
280};
281
282class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
283  public:
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
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
345    virtual sp<MediaPlayerBase> createPlayer() {
346        ALOGV(" create MidiFile");
347        return new MidiFile();
348    }
349};
350
351class TestPlayerFactory : public MediaPlayerFactory::IFactory {
352  public:
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
363    virtual sp<MediaPlayerBase> createPlayer() {
364        ALOGV("Create Test Player stub");
365        return new TestPlayerStub();
366    }
367};
368
369void 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