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