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