xref: /aosp_15_r20/frameworks/av/media/libmediaplayerservice/MediaPlayerFactory.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker **
3*ec779b8eSAndroid Build Coastguard Worker ** Copyright 2012, The Android Open Source Project
4*ec779b8eSAndroid Build Coastguard Worker **
5*ec779b8eSAndroid Build Coastguard Worker ** Licensed under the Apache License, Version 2.0 (the "License");
6*ec779b8eSAndroid Build Coastguard Worker ** you may not use this file except in compliance with the License.
7*ec779b8eSAndroid Build Coastguard Worker ** You may obtain a copy of the License at
8*ec779b8eSAndroid Build Coastguard Worker **
9*ec779b8eSAndroid Build Coastguard Worker **     http://www.apache.org/licenses/LICENSE-2.0
10*ec779b8eSAndroid Build Coastguard Worker **
11*ec779b8eSAndroid Build Coastguard Worker ** Unless required by applicable law or agreed to in writing, software
12*ec779b8eSAndroid Build Coastguard Worker ** distributed under the License is distributed on an "AS IS" BASIS,
13*ec779b8eSAndroid Build Coastguard Worker ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*ec779b8eSAndroid Build Coastguard Worker ** See the License for the specific language governing permissions and
15*ec779b8eSAndroid Build Coastguard Worker ** limitations under the License.
16*ec779b8eSAndroid Build Coastguard Worker */
17*ec779b8eSAndroid Build Coastguard Worker 
18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "MediaPlayerFactory"
20*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
21*ec779b8eSAndroid Build Coastguard Worker 
22*ec779b8eSAndroid Build Coastguard Worker #include <cutils/properties.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <datasource/FileSource.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <media/DataSource.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/IMediaPlayer.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <utils/Errors.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <utils/misc.h>
29*ec779b8eSAndroid Build Coastguard Worker 
30*ec779b8eSAndroid Build Coastguard Worker #include "MediaPlayerFactory.h"
31*ec779b8eSAndroid Build Coastguard Worker 
32*ec779b8eSAndroid Build Coastguard Worker #include "TestPlayerStub.h"
33*ec779b8eSAndroid Build Coastguard Worker #include <nuplayer/NuPlayerDriver.h>
34*ec779b8eSAndroid Build Coastguard Worker 
35*ec779b8eSAndroid Build Coastguard Worker namespace android {
36*ec779b8eSAndroid Build Coastguard Worker 
37*ec779b8eSAndroid Build Coastguard Worker Mutex MediaPlayerFactory::sLock;
38*ec779b8eSAndroid Build Coastguard Worker MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
39*ec779b8eSAndroid Build Coastguard Worker bool MediaPlayerFactory::sInitComplete = false;
40*ec779b8eSAndroid Build Coastguard Worker 
registerFactory_l(IFactory * factory,player_type type)41*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
42*ec779b8eSAndroid Build Coastguard Worker                                                player_type type) {
43*ec779b8eSAndroid Build Coastguard Worker     if (NULL == factory) {
44*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
45*ec779b8eSAndroid Build Coastguard Worker               " NULL.", type);
46*ec779b8eSAndroid Build Coastguard Worker         return BAD_VALUE;
47*ec779b8eSAndroid Build Coastguard Worker     }
48*ec779b8eSAndroid Build Coastguard Worker 
49*ec779b8eSAndroid Build Coastguard Worker     if (sFactoryMap.indexOfKey(type) >= 0) {
50*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
51*ec779b8eSAndroid Build Coastguard Worker               " already registered.", type);
52*ec779b8eSAndroid Build Coastguard Worker         return ALREADY_EXISTS;
53*ec779b8eSAndroid Build Coastguard Worker     }
54*ec779b8eSAndroid Build Coastguard Worker 
55*ec779b8eSAndroid Build Coastguard Worker     if (sFactoryMap.add(type, factory) < 0) {
56*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
57*ec779b8eSAndroid Build Coastguard Worker               " to map.", type);
58*ec779b8eSAndroid Build Coastguard Worker         return UNKNOWN_ERROR;
59*ec779b8eSAndroid Build Coastguard Worker     }
60*ec779b8eSAndroid Build Coastguard Worker 
61*ec779b8eSAndroid Build Coastguard Worker     return OK;
62*ec779b8eSAndroid Build Coastguard Worker }
63*ec779b8eSAndroid Build Coastguard Worker 
getDefaultPlayerType()64*ec779b8eSAndroid Build Coastguard Worker static player_type getDefaultPlayerType() {
65*ec779b8eSAndroid Build Coastguard Worker     return NU_PLAYER;
66*ec779b8eSAndroid Build Coastguard Worker }
67*ec779b8eSAndroid Build Coastguard Worker 
registerFactory(IFactory * factory,player_type type)68*ec779b8eSAndroid Build Coastguard Worker status_t MediaPlayerFactory::registerFactory(IFactory* factory,
69*ec779b8eSAndroid Build Coastguard Worker                                              player_type type) {
70*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock_(&sLock);
71*ec779b8eSAndroid Build Coastguard Worker     return registerFactory_l(factory, type);
72*ec779b8eSAndroid Build Coastguard Worker }
73*ec779b8eSAndroid Build Coastguard Worker 
unregisterFactory(player_type type)74*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerFactory::unregisterFactory(player_type type) {
75*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock_(&sLock);
76*ec779b8eSAndroid Build Coastguard Worker     sFactoryMap.removeItem(type);
77*ec779b8eSAndroid Build Coastguard Worker }
78*ec779b8eSAndroid Build Coastguard Worker 
79*ec779b8eSAndroid Build Coastguard Worker #define GET_PLAYER_TYPE_IMPL(a...)                      \
80*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock_(&sLock);                      \
81*ec779b8eSAndroid Build Coastguard Worker                                                         \
82*ec779b8eSAndroid Build Coastguard Worker     player_type ret = STAGEFRIGHT_PLAYER;               \
83*ec779b8eSAndroid Build Coastguard Worker     float bestScore = 0.0;                              \
84*ec779b8eSAndroid Build Coastguard Worker                                                         \
85*ec779b8eSAndroid Build Coastguard Worker     for (size_t i = 0; i < sFactoryMap.size(); ++i) {   \
86*ec779b8eSAndroid Build Coastguard Worker                                                         \
87*ec779b8eSAndroid Build Coastguard Worker         IFactory* v = sFactoryMap.valueAt(i);           \
88*ec779b8eSAndroid Build Coastguard Worker         float thisScore;                                \
89*ec779b8eSAndroid Build Coastguard Worker         CHECK(v != NULL);                               \
90*ec779b8eSAndroid Build Coastguard Worker         thisScore = v->scoreFactory(a, bestScore);      \
91*ec779b8eSAndroid Build Coastguard Worker         if (thisScore > bestScore) {                    \
92*ec779b8eSAndroid Build Coastguard Worker             ret = sFactoryMap.keyAt(i);                 \
93*ec779b8eSAndroid Build Coastguard Worker             bestScore = thisScore;                      \
94*ec779b8eSAndroid Build Coastguard Worker         }                                               \
95*ec779b8eSAndroid Build Coastguard Worker     }                                                   \
96*ec779b8eSAndroid Build Coastguard Worker                                                         \
97*ec779b8eSAndroid Build Coastguard Worker     if (0.0 == bestScore) {                             \
98*ec779b8eSAndroid Build Coastguard Worker         ret = getDefaultPlayerType();                   \
99*ec779b8eSAndroid Build Coastguard Worker     }                                                   \
100*ec779b8eSAndroid Build Coastguard Worker                                                         \
101*ec779b8eSAndroid Build Coastguard Worker     return ret;
102*ec779b8eSAndroid Build Coastguard Worker 
getPlayerType(const sp<IMediaPlayer> & client,const char * url)103*ec779b8eSAndroid Build Coastguard Worker player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
104*ec779b8eSAndroid Build Coastguard Worker                                               const char* url) {
105*ec779b8eSAndroid Build Coastguard Worker     GET_PLAYER_TYPE_IMPL(client, url);
106*ec779b8eSAndroid Build Coastguard Worker }
107*ec779b8eSAndroid Build Coastguard Worker 
getPlayerType(const sp<IMediaPlayer> & client,int fd,int64_t offset,int64_t length)108*ec779b8eSAndroid Build Coastguard Worker player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
109*ec779b8eSAndroid Build Coastguard Worker                                               int fd,
110*ec779b8eSAndroid Build Coastguard Worker                                               int64_t offset,
111*ec779b8eSAndroid Build Coastguard Worker                                               int64_t length) {
112*ec779b8eSAndroid Build Coastguard Worker     GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
113*ec779b8eSAndroid Build Coastguard Worker }
114*ec779b8eSAndroid Build Coastguard Worker 
getPlayerType(const sp<IMediaPlayer> & client,const sp<IStreamSource> & source)115*ec779b8eSAndroid Build Coastguard Worker player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
116*ec779b8eSAndroid Build Coastguard Worker                                               const sp<IStreamSource> &source) {
117*ec779b8eSAndroid Build Coastguard Worker     GET_PLAYER_TYPE_IMPL(client, source);
118*ec779b8eSAndroid Build Coastguard Worker }
119*ec779b8eSAndroid Build Coastguard Worker 
getPlayerType(const sp<IMediaPlayer> & client,const sp<DataSource> & source)120*ec779b8eSAndroid Build Coastguard Worker player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
121*ec779b8eSAndroid Build Coastguard Worker                                               const sp<DataSource> &source) {
122*ec779b8eSAndroid Build Coastguard Worker     GET_PLAYER_TYPE_IMPL(client, source);
123*ec779b8eSAndroid Build Coastguard Worker }
124*ec779b8eSAndroid Build Coastguard Worker 
125*ec779b8eSAndroid Build Coastguard Worker #undef GET_PLAYER_TYPE_IMPL
126*ec779b8eSAndroid Build Coastguard Worker 
createPlayer(player_type playerType,const sp<MediaPlayerBase::Listener> & listener,pid_t pid)127*ec779b8eSAndroid Build Coastguard Worker sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
128*ec779b8eSAndroid Build Coastguard Worker         player_type playerType,
129*ec779b8eSAndroid Build Coastguard Worker         const sp<MediaPlayerBase::Listener> &listener,
130*ec779b8eSAndroid Build Coastguard Worker         pid_t pid) {
131*ec779b8eSAndroid Build Coastguard Worker     sp<MediaPlayerBase> p;
132*ec779b8eSAndroid Build Coastguard Worker     IFactory* factory;
133*ec779b8eSAndroid Build Coastguard Worker     status_t init_result;
134*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock_(&sLock);
135*ec779b8eSAndroid Build Coastguard Worker 
136*ec779b8eSAndroid Build Coastguard Worker     if (sFactoryMap.indexOfKey(playerType) < 0) {
137*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Failed to create player object of type %d, no registered"
138*ec779b8eSAndroid Build Coastguard Worker               " factory", playerType);
139*ec779b8eSAndroid Build Coastguard Worker         return p;
140*ec779b8eSAndroid Build Coastguard Worker     }
141*ec779b8eSAndroid Build Coastguard Worker 
142*ec779b8eSAndroid Build Coastguard Worker     factory = sFactoryMap.valueFor(playerType);
143*ec779b8eSAndroid Build Coastguard Worker     CHECK(NULL != factory);
144*ec779b8eSAndroid Build Coastguard Worker     p = factory->createPlayer(pid);
145*ec779b8eSAndroid Build Coastguard Worker 
146*ec779b8eSAndroid Build Coastguard Worker     if (p == NULL) {
147*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Failed to create player object of type %d, create failed",
148*ec779b8eSAndroid Build Coastguard Worker                playerType);
149*ec779b8eSAndroid Build Coastguard Worker         return p;
150*ec779b8eSAndroid Build Coastguard Worker     }
151*ec779b8eSAndroid Build Coastguard Worker 
152*ec779b8eSAndroid Build Coastguard Worker     init_result = p->initCheck();
153*ec779b8eSAndroid Build Coastguard Worker     if (init_result == NO_ERROR) {
154*ec779b8eSAndroid Build Coastguard Worker         p->setNotifyCallback(listener);
155*ec779b8eSAndroid Build Coastguard Worker     } else {
156*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Failed to create player object of type %d, initCheck failed"
157*ec779b8eSAndroid Build Coastguard Worker               " (res = %d)", playerType, init_result);
158*ec779b8eSAndroid Build Coastguard Worker         p.clear();
159*ec779b8eSAndroid Build Coastguard Worker     }
160*ec779b8eSAndroid Build Coastguard Worker 
161*ec779b8eSAndroid Build Coastguard Worker     return p;
162*ec779b8eSAndroid Build Coastguard Worker }
163*ec779b8eSAndroid Build Coastguard Worker 
164*ec779b8eSAndroid Build Coastguard Worker /*****************************************************************************
165*ec779b8eSAndroid Build Coastguard Worker  *                                                                           *
166*ec779b8eSAndroid Build Coastguard Worker  *                     Built-In Factory Implementations                      *
167*ec779b8eSAndroid Build Coastguard Worker  *                                                                           *
168*ec779b8eSAndroid Build Coastguard Worker  *****************************************************************************/
169*ec779b8eSAndroid Build Coastguard Worker 
170*ec779b8eSAndroid Build Coastguard Worker class NuPlayerFactory : public MediaPlayerFactory::IFactory {
171*ec779b8eSAndroid Build Coastguard Worker   public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float curScore)172*ec779b8eSAndroid Build Coastguard Worker     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
173*ec779b8eSAndroid Build Coastguard Worker                                const char* url,
174*ec779b8eSAndroid Build Coastguard Worker                                float curScore) {
175*ec779b8eSAndroid Build Coastguard Worker         static const float kOurScore = 0.8;
176*ec779b8eSAndroid Build Coastguard Worker 
177*ec779b8eSAndroid Build Coastguard Worker         if (kOurScore <= curScore)
178*ec779b8eSAndroid Build Coastguard Worker             return 0.0;
179*ec779b8eSAndroid Build Coastguard Worker 
180*ec779b8eSAndroid Build Coastguard Worker         if (!strncasecmp("http://", url, 7)
181*ec779b8eSAndroid Build Coastguard Worker                 || !strncasecmp("https://", url, 8)
182*ec779b8eSAndroid Build Coastguard Worker                 || !strncasecmp("file://", url, 7)) {
183*ec779b8eSAndroid Build Coastguard Worker             size_t len = strlen(url);
184*ec779b8eSAndroid Build Coastguard Worker             if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
185*ec779b8eSAndroid Build Coastguard Worker                 return kOurScore;
186*ec779b8eSAndroid Build Coastguard Worker             }
187*ec779b8eSAndroid Build Coastguard Worker 
188*ec779b8eSAndroid Build Coastguard Worker             if (strstr(url,"m3u8")) {
189*ec779b8eSAndroid Build Coastguard Worker                 return kOurScore;
190*ec779b8eSAndroid Build Coastguard Worker             }
191*ec779b8eSAndroid Build Coastguard Worker 
192*ec779b8eSAndroid Build Coastguard Worker             if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
193*ec779b8eSAndroid Build Coastguard Worker                 return kOurScore;
194*ec779b8eSAndroid Build Coastguard Worker             }
195*ec779b8eSAndroid Build Coastguard Worker         }
196*ec779b8eSAndroid Build Coastguard Worker 
197*ec779b8eSAndroid Build Coastguard Worker         if (!strncasecmp("rtsp://", url, 7)) {
198*ec779b8eSAndroid Build Coastguard Worker             return kOurScore;
199*ec779b8eSAndroid Build Coastguard Worker         }
200*ec779b8eSAndroid Build Coastguard Worker 
201*ec779b8eSAndroid Build Coastguard Worker         return 0.0;
202*ec779b8eSAndroid Build Coastguard Worker     }
203*ec779b8eSAndroid Build Coastguard Worker 
scoreFactory(const sp<IMediaPlayer> &,const sp<IStreamSource> &,float)204*ec779b8eSAndroid Build Coastguard Worker     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
205*ec779b8eSAndroid Build Coastguard Worker                                const sp<IStreamSource>& /*source*/,
206*ec779b8eSAndroid Build Coastguard Worker                                float /*curScore*/) {
207*ec779b8eSAndroid Build Coastguard Worker         return 1.0;
208*ec779b8eSAndroid Build Coastguard Worker     }
209*ec779b8eSAndroid Build Coastguard Worker 
scoreFactory(const sp<IMediaPlayer> &,const sp<DataSource> &,float)210*ec779b8eSAndroid Build Coastguard Worker     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
211*ec779b8eSAndroid Build Coastguard Worker                                const sp<DataSource>& /*source*/,
212*ec779b8eSAndroid Build Coastguard Worker                                float /*curScore*/) {
213*ec779b8eSAndroid Build Coastguard Worker         // Only NuPlayer supports setting a DataSource source directly.
214*ec779b8eSAndroid Build Coastguard Worker         return 1.0;
215*ec779b8eSAndroid Build Coastguard Worker     }
216*ec779b8eSAndroid Build Coastguard Worker 
createPlayer(pid_t pid)217*ec779b8eSAndroid Build Coastguard Worker     virtual sp<MediaPlayerBase> createPlayer(pid_t pid) {
218*ec779b8eSAndroid Build Coastguard Worker         ALOGV(" create NuPlayer");
219*ec779b8eSAndroid Build Coastguard Worker         return new NuPlayerDriver(pid);
220*ec779b8eSAndroid Build Coastguard Worker     }
221*ec779b8eSAndroid Build Coastguard Worker };
222*ec779b8eSAndroid Build Coastguard Worker 
223*ec779b8eSAndroid Build Coastguard Worker class TestPlayerFactory : public MediaPlayerFactory::IFactory {
224*ec779b8eSAndroid Build Coastguard Worker   public:
scoreFactory(const sp<IMediaPlayer> &,const char * url,float)225*ec779b8eSAndroid Build Coastguard Worker     virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
226*ec779b8eSAndroid Build Coastguard Worker                                const char* url,
227*ec779b8eSAndroid Build Coastguard Worker                                float /*curScore*/) {
228*ec779b8eSAndroid Build Coastguard Worker         if (TestPlayerStub::canBeUsed(url)) {
229*ec779b8eSAndroid Build Coastguard Worker             return 1.0;
230*ec779b8eSAndroid Build Coastguard Worker         }
231*ec779b8eSAndroid Build Coastguard Worker 
232*ec779b8eSAndroid Build Coastguard Worker         return 0.0;
233*ec779b8eSAndroid Build Coastguard Worker     }
234*ec779b8eSAndroid Build Coastguard Worker 
createPlayer(pid_t)235*ec779b8eSAndroid Build Coastguard Worker     virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) {
236*ec779b8eSAndroid Build Coastguard Worker         ALOGV("Create Test Player stub");
237*ec779b8eSAndroid Build Coastguard Worker         return new TestPlayerStub();
238*ec779b8eSAndroid Build Coastguard Worker     }
239*ec779b8eSAndroid Build Coastguard Worker };
240*ec779b8eSAndroid Build Coastguard Worker 
registerBuiltinFactories()241*ec779b8eSAndroid Build Coastguard Worker void MediaPlayerFactory::registerBuiltinFactories() {
242*ec779b8eSAndroid Build Coastguard Worker     Mutex::Autolock lock_(&sLock);
243*ec779b8eSAndroid Build Coastguard Worker 
244*ec779b8eSAndroid Build Coastguard Worker     if (sInitComplete)
245*ec779b8eSAndroid Build Coastguard Worker         return;
246*ec779b8eSAndroid Build Coastguard Worker 
247*ec779b8eSAndroid Build Coastguard Worker     IFactory* factory = new NuPlayerFactory();
248*ec779b8eSAndroid Build Coastguard Worker     if (registerFactory_l(factory, NU_PLAYER) != OK)
249*ec779b8eSAndroid Build Coastguard Worker         delete factory;
250*ec779b8eSAndroid Build Coastguard Worker     factory = new TestPlayerFactory();
251*ec779b8eSAndroid Build Coastguard Worker     if (registerFactory_l(factory, TEST_PLAYER) != OK)
252*ec779b8eSAndroid Build Coastguard Worker         delete factory;
253*ec779b8eSAndroid Build Coastguard Worker 
254*ec779b8eSAndroid Build Coastguard Worker     sInitComplete = true;
255*ec779b8eSAndroid Build Coastguard Worker }
256*ec779b8eSAndroid Build Coastguard Worker 
257*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
258