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