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