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