MediaPlayerFactory.cpp revision 0e8928bf4f2b01b783f6da97d15e8f1abb0fd7d7
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
30#include "MediaPlayerFactory.h"
31
32#include "TestPlayerStub.h"
33#include "StagefrightPlayer.h"
34#include "nuplayer/NuPlayerDriver.h"
35
36namespace android {
37
38Mutex MediaPlayerFactory::sLock;
39MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
40bool MediaPlayerFactory::sInitComplete = false;
41
42status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
43                                               player_type type) {
44    if (NULL == factory) {
45        ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
46              " NULL.", type);
47        return BAD_VALUE;
48    }
49
50    if (sFactoryMap.indexOfKey(type) >= 0) {
51        ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
52              " already registered.", type);
53        return ALREADY_EXISTS;
54    }
55
56    if (sFactoryMap.add(type, factory) < 0) {
57        ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
58              " to map.", type);
59        return UNKNOWN_ERROR;
60    }
61
62    return OK;
63}
64
65static player_type getDefaultPlayerType() {
66    char value[PROPERTY_VALUE_MAX];
67    if (property_get("media.stagefright.use-awesome", value, NULL)
68            && (!strcmp("1", value) || !strcasecmp("true", value))) {
69        return STAGEFRIGHT_PLAYER;
70    }
71
72    // TODO: remove this EXPERIMENTAL developer settings property
73    if (property_get("persist.sys.media.use-awesome", value, NULL)
74            && !strcasecmp("true", value)) {
75        return STAGEFRIGHT_PLAYER;
76    }
77
78    return NU_PLAYER;
79}
80
81status_t MediaPlayerFactory::registerFactory(IFactory* factory,
82                                             player_type type) {
83    Mutex::Autolock lock_(&sLock);
84    return registerFactory_l(factory, type);
85}
86
87void MediaPlayerFactory::unregisterFactory(player_type type) {
88    Mutex::Autolock lock_(&sLock);
89    sFactoryMap.removeItem(type);
90}
91
92#define GET_PLAYER_TYPE_IMPL(a...)                      \
93    Mutex::Autolock lock_(&sLock);                      \
94                                                        \
95    player_type ret = STAGEFRIGHT_PLAYER;               \
96    float bestScore = 0.0;                              \
97                                                        \
98    for (size_t i = 0; i < sFactoryMap.size(); ++i) {   \
99                                                        \
100        IFactory* v = sFactoryMap.valueAt(i);           \
101        float thisScore;                                \
102        CHECK(v != NULL);                               \
103        thisScore = v->scoreFactory(a, bestScore);      \
104        if (thisScore > bestScore) {                    \
105            ret = sFactoryMap.keyAt(i);                 \
106            bestScore = thisScore;                      \
107        }                                               \
108    }                                                   \
109                                                        \
110    if (0.0 == bestScore) {                             \
111        ret = getDefaultPlayerType();                   \
112    }                                                   \
113                                                        \
114    return ret;
115
116player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
117                                              const char* url) {
118    GET_PLAYER_TYPE_IMPL(client, url);
119}
120
121player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
122                                              int fd,
123                                              int64_t offset,
124                                              int64_t length) {
125    GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
126}
127
128player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
129                                              const sp<IStreamSource> &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 (getDefaultPlayerType()
187                == STAGEFRIGHT_PLAYER) {
188            char buf[20];
189            lseek(fd, offset, SEEK_SET);
190            read(fd, buf, sizeof(buf));
191            lseek(fd, offset, SEEK_SET);
192
193            uint32_t ident = *((uint32_t*)buf);
194
195            // Ogg vorbis?
196            if (ident == 0x5367674f) // 'OggS'
197                return 1.0;
198        }
199
200        return 0.0;
201    }
202
203    virtual sp<MediaPlayerBase> createPlayer() {
204        ALOGV(" create StagefrightPlayer");
205        return new StagefrightPlayer();
206    }
207};
208
209class NuPlayerFactory : public MediaPlayerFactory::IFactory {
210  public:
211    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
212                               const char* url,
213                               float curScore) {
214        static const float kOurScore = 0.8;
215
216        if (kOurScore <= curScore)
217            return 0.0;
218
219        if (!strncasecmp("http://", url, 7)
220                || !strncasecmp("https://", url, 8)
221                || !strncasecmp("file://", url, 7)) {
222            size_t len = strlen(url);
223            if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
224                return kOurScore;
225            }
226
227            if (strstr(url,"m3u8")) {
228                return kOurScore;
229            }
230
231            if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
232                return kOurScore;
233            }
234        }
235
236        if (!strncasecmp("rtsp://", url, 7)) {
237            return kOurScore;
238        }
239
240        return 0.0;
241    }
242
243    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
244                               const sp<IStreamSource>& /*source*/,
245                               float /*curScore*/) {
246        return 1.0;
247    }
248
249    virtual sp<MediaPlayerBase> createPlayer() {
250        ALOGV(" create NuPlayer");
251        return new NuPlayerDriver;
252    }
253};
254
255class TestPlayerFactory : public MediaPlayerFactory::IFactory {
256  public:
257    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
258                               const char* url,
259                               float /*curScore*/) {
260        if (TestPlayerStub::canBeUsed(url)) {
261            return 1.0;
262        }
263
264        return 0.0;
265    }
266
267    virtual sp<MediaPlayerBase> createPlayer() {
268        ALOGV("Create Test Player stub");
269        return new TestPlayerStub();
270    }
271};
272
273void MediaPlayerFactory::registerBuiltinFactories() {
274    Mutex::Autolock lock_(&sLock);
275
276    if (sInitComplete)
277        return;
278
279    registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
280    registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
281    registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
282
283    sInitComplete = true;
284}
285
286}  // namespace android
287