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/DataSource.h>
24#include <media/IMediaPlayer.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 "nuplayer/NuPlayerDriver.h"
34
35namespace android {
36
37Mutex MediaPlayerFactory::sLock;
38MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
39bool MediaPlayerFactory::sInitComplete = false;
40
41status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
42                                               player_type type) {
43    if (NULL == factory) {
44        ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
45              " NULL.", type);
46        return BAD_VALUE;
47    }
48
49    if (sFactoryMap.indexOfKey(type) >= 0) {
50        ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
51              " already registered.", type);
52        return ALREADY_EXISTS;
53    }
54
55    if (sFactoryMap.add(type, factory) < 0) {
56        ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
57              " to map.", type);
58        return UNKNOWN_ERROR;
59    }
60
61    return OK;
62}
63
64static player_type getDefaultPlayerType() {
65    return NU_PLAYER;
66}
67
68status_t MediaPlayerFactory::registerFactory(IFactory* factory,
69                                             player_type type) {
70    Mutex::Autolock lock_(&sLock);
71    return registerFactory_l(factory, type);
72}
73
74void MediaPlayerFactory::unregisterFactory(player_type type) {
75    Mutex::Autolock lock_(&sLock);
76    sFactoryMap.removeItem(type);
77}
78
79#define GET_PLAYER_TYPE_IMPL(a...)                      \
80    Mutex::Autolock lock_(&sLock);                      \
81                                                        \
82    player_type ret = STAGEFRIGHT_PLAYER;               \
83    float bestScore = 0.0;                              \
84                                                        \
85    for (size_t i = 0; i < sFactoryMap.size(); ++i) {   \
86                                                        \
87        IFactory* v = sFactoryMap.valueAt(i);           \
88        float thisScore;                                \
89        CHECK(v != NULL);                               \
90        thisScore = v->scoreFactory(a, bestScore);      \
91        if (thisScore > bestScore) {                    \
92            ret = sFactoryMap.keyAt(i);                 \
93            bestScore = thisScore;                      \
94        }                                               \
95    }                                                   \
96                                                        \
97    if (0.0 == bestScore) {                             \
98        ret = getDefaultPlayerType();                   \
99    }                                                   \
100                                                        \
101    return ret;
102
103player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
104                                              const char* url) {
105    GET_PLAYER_TYPE_IMPL(client, url);
106}
107
108player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
109                                              int fd,
110                                              int64_t offset,
111                                              int64_t length) {
112    GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
113}
114
115player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
116                                              const sp<IStreamSource> &source) {
117    GET_PLAYER_TYPE_IMPL(client, source);
118}
119
120player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
121                                              const sp<DataSource> &source) {
122    GET_PLAYER_TYPE_IMPL(client, source);
123}
124
125#undef GET_PLAYER_TYPE_IMPL
126
127sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
128        player_type playerType,
129        const sp<MediaPlayerBase::Listener> &listener,
130        pid_t pid) {
131    sp<MediaPlayerBase> p;
132    IFactory* factory;
133    status_t init_result;
134    Mutex::Autolock lock_(&sLock);
135
136    if (sFactoryMap.indexOfKey(playerType) < 0) {
137        ALOGE("Failed to create player object of type %d, no registered"
138              " factory", playerType);
139        return p;
140    }
141
142    factory = sFactoryMap.valueFor(playerType);
143    CHECK(NULL != factory);
144    p = factory->createPlayer(pid);
145
146    if (p == NULL) {
147        ALOGE("Failed to create player object of type %d, create failed",
148               playerType);
149        return p;
150    }
151
152    init_result = p->initCheck();
153    if (init_result == NO_ERROR) {
154        p->setNotifyCallback(listener);
155    } else {
156        ALOGE("Failed to create player object of type %d, initCheck failed"
157              " (res = %d)", playerType, init_result);
158        p.clear();
159    }
160
161    return p;
162}
163
164/*****************************************************************************
165 *                                                                           *
166 *                     Built-In Factory Implementations                      *
167 *                                                                           *
168 *****************************************************************************/
169
170class NuPlayerFactory : public MediaPlayerFactory::IFactory {
171  public:
172    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
173                               const char* url,
174                               float curScore) {
175        static const float kOurScore = 0.8;
176
177        if (kOurScore <= curScore)
178            return 0.0;
179
180        if (!strncasecmp("http://", url, 7)
181                || !strncasecmp("https://", url, 8)
182                || !strncasecmp("file://", url, 7)) {
183            size_t len = strlen(url);
184            if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
185                return kOurScore;
186            }
187
188            if (strstr(url,"m3u8")) {
189                return kOurScore;
190            }
191
192            if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
193                return kOurScore;
194            }
195        }
196
197        if (!strncasecmp("rtsp://", url, 7)) {
198            return kOurScore;
199        }
200
201        return 0.0;
202    }
203
204    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
205                               const sp<IStreamSource>& /*source*/,
206                               float /*curScore*/) {
207        return 1.0;
208    }
209
210    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
211                               const sp<DataSource>& /*source*/,
212                               float /*curScore*/) {
213        // Only NuPlayer supports setting a DataSource source directly.
214        return 1.0;
215    }
216
217    virtual sp<MediaPlayerBase> createPlayer(pid_t pid) {
218        ALOGV(" create NuPlayer");
219        return new NuPlayerDriver(pid);
220    }
221};
222
223class TestPlayerFactory : public MediaPlayerFactory::IFactory {
224  public:
225    virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
226                               const char* url,
227                               float /*curScore*/) {
228        if (TestPlayerStub::canBeUsed(url)) {
229            return 1.0;
230        }
231
232        return 0.0;
233    }
234
235    virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) {
236        ALOGV("Create Test Player stub");
237        return new TestPlayerStub();
238    }
239};
240
241void MediaPlayerFactory::registerBuiltinFactories() {
242    Mutex::Autolock lock_(&sLock);
243
244    if (sInitComplete)
245        return;
246
247    IFactory* factory = new NuPlayerFactory();
248    if (registerFactory_l(factory, NU_PLAYER) != OK)
249        delete factory;
250    factory = new TestPlayerFactory();
251    if (registerFactory_l(factory, TEST_PLAYER) != OK)
252        delete factory;
253
254    sInitComplete = true;
255}
256
257}  // namespace android
258