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