MediaPlayerFactory.cpp revision 701d342f785e407c8e6bcb046658f84ac56d989a
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/stagefright/DataSource.h>
25#include <media/stagefright/FileSource.h>
26#include <media/stagefright/foundation/ADebug.h>
27#include <utils/Errors.h>
28#include <utils/misc.h>
29#include <../libstagefright/include/WVMExtractor.h>
30
31#include "MediaPlayerFactory.h"
32
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    return NU_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        ret = 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
128player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
129                                              const sp<DataSource> &source) {
130    GET_PLAYER_TYPE_IMPL(client, source);
131}
132
133#undef GET_PLAYER_TYPE_IMPL
134
135sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
136        player_type playerType,
137        void* cookie,
138        notify_callback_f notifyFunc) {
139    sp<MediaPlayerBase> p;
140    IFactory* factory;
141    status_t init_result;
142    Mutex::Autolock lock_(&sLock);
143
144    if (sFactoryMap.indexOfKey(playerType) < 0) {
145        ALOGE("Failed to create player object of type %d, no registered"
146              " factory", playerType);
147        return p;
148    }
149
150    factory = sFactoryMap.valueFor(playerType);
151    CHECK(NULL != factory);
152    p = factory->createPlayer();
153
154    if (p == NULL) {
155        ALOGE("Failed to create player object of type %d, create failed",
156               playerType);
157        return p;
158    }
159
160    init_result = p->initCheck();
161    if (init_result == NO_ERROR) {
162        p->setNotifyCallback(cookie, notifyFunc);
163    } else {
164        ALOGE("Failed to create player object of type %d, initCheck failed"
165              " (res = %d)", playerType, init_result);
166        p.clear();
167    }
168
169    return p;
170}
171
172/*****************************************************************************
173 *                                                                           *
174 *                     Built-In Factory Implementations                      *
175 *                                                                           *
176 *****************************************************************************/
177
178class StagefrightPlayerFactory :
179    public MediaPlayerFactory::IFactory {
180  public:
181    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
182                               int fd,
183                               int64_t offset,
184                               int64_t length,
185                               float /*curScore*/) {
186        if (legacyDrm()) {
187            sp<DataSource> source = new FileSource(dup(fd), offset, length);
188            String8 mimeType;
189            float confidence;
190            if (SniffWVM(source, &mimeType, &confidence, NULL /* format */)) {
191                return 1.0;
192            }
193        }
194
195        if (getDefaultPlayerType() == STAGEFRIGHT_PLAYER) {
196            char buf[20];
197            lseek(fd, offset, SEEK_SET);
198            read(fd, buf, sizeof(buf));
199            lseek(fd, offset, SEEK_SET);
200
201            uint32_t ident = *((uint32_t*)buf);
202
203            // Ogg vorbis?
204            if (ident == 0x5367674f) // 'OggS'
205                return 1.0;
206        }
207
208        return 0.0;
209    }
210
211    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
212                               const char* url,
213                               float /*curScore*/) {
214        if (legacyDrm() && !strncasecmp("widevine://", url, 11)) {
215            return 1.0;
216        }
217        return 0.0;
218    }
219
220    virtual sp<MediaPlayerBase> createPlayer() {
221        ALOGV(" create StagefrightPlayer");
222        return new StagefrightPlayer();
223    }
224  private:
225    bool legacyDrm() {
226        char value[PROPERTY_VALUE_MAX];
227        if (property_get("persist.sys.media.legacy-drm", value, NULL)
228                && (!strcmp("1", value) || !strcasecmp("true", value))) {
229            return true;
230        }
231        return false;
232    }
233};
234
235class NuPlayerFactory : public MediaPlayerFactory::IFactory {
236  public:
237    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
238                               const char* url,
239                               float curScore) {
240        static const float kOurScore = 0.8;
241
242        if (kOurScore <= curScore)
243            return 0.0;
244
245        if (!strncasecmp("http://", url, 7)
246                || !strncasecmp("https://", url, 8)
247                || !strncasecmp("file://", url, 7)) {
248            size_t len = strlen(url);
249            if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
250                return kOurScore;
251            }
252
253            if (strstr(url,"m3u8")) {
254                return kOurScore;
255            }
256
257            if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
258                return kOurScore;
259            }
260        }
261
262        if (!strncasecmp("rtsp://", url, 7)) {
263            return kOurScore;
264        }
265
266        return 0.0;
267    }
268
269    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
270                               const sp<IStreamSource>& /*source*/,
271                               float /*curScore*/) {
272        return 1.0;
273    }
274
275    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
276                               const sp<DataSource>& /*source*/,
277                               float /*curScore*/) {
278        // Only NuPlayer supports setting a DataSource source directly.
279        return 1.0;
280    }
281
282    virtual sp<MediaPlayerBase> createPlayer() {
283        ALOGV(" create NuPlayer");
284        return new NuPlayerDriver;
285    }
286};
287
288class TestPlayerFactory : public MediaPlayerFactory::IFactory {
289  public:
290    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
291                               const char* url,
292                               float /*curScore*/) {
293        if (TestPlayerStub::canBeUsed(url)) {
294            return 1.0;
295        }
296
297        return 0.0;
298    }
299
300    virtual sp<MediaPlayerBase> createPlayer() {
301        ALOGV("Create Test Player stub");
302        return new TestPlayerStub();
303    }
304};
305
306void MediaPlayerFactory::registerBuiltinFactories() {
307    Mutex::Autolock lock_(&sLock);
308
309    if (sInitComplete)
310        return;
311
312    registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
313    registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
314    registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
315
316    sInitComplete = true;
317}
318
319}  // namespace android
320