258 lines
8.3 KiB
C++
258 lines
8.3 KiB
C++
/*
|
|
**
|
|
** Copyright 2012, The Android Open Source Project
|
|
**
|
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
|
** you may not use this file except in compliance with the License.
|
|
** You may obtain a copy of the License at
|
|
**
|
|
** http://www.apache.org/licenses/LICENSE-2.0
|
|
**
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
** See the License for the specific language governing permissions and
|
|
** limitations under the License.
|
|
*/
|
|
|
|
//#define LOG_NDEBUG 0
|
|
#define LOG_TAG "MediaPlayerFactory"
|
|
#include <utils/Log.h>
|
|
|
|
#include <cutils/properties.h>
|
|
#include <datasource/FileSource.h>
|
|
#include <media/DataSource.h>
|
|
#include <media/IMediaPlayer.h>
|
|
#include <media/stagefright/foundation/ADebug.h>
|
|
#include <utils/Errors.h>
|
|
#include <utils/misc.h>
|
|
|
|
#include "MediaPlayerFactory.h"
|
|
|
|
#include "TestPlayerStub.h"
|
|
#include "nuplayer/NuPlayerDriver.h"
|
|
|
|
namespace android {
|
|
|
|
Mutex MediaPlayerFactory::sLock;
|
|
MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
|
|
bool MediaPlayerFactory::sInitComplete = false;
|
|
|
|
status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
|
|
player_type type) {
|
|
if (NULL == factory) {
|
|
ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
|
|
" NULL.", type);
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
if (sFactoryMap.indexOfKey(type) >= 0) {
|
|
ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
|
|
" already registered.", type);
|
|
return ALREADY_EXISTS;
|
|
}
|
|
|
|
if (sFactoryMap.add(type, factory) < 0) {
|
|
ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
|
|
" to map.", type);
|
|
return UNKNOWN_ERROR;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
static player_type getDefaultPlayerType() {
|
|
return NU_PLAYER;
|
|
}
|
|
|
|
status_t MediaPlayerFactory::registerFactory(IFactory* factory,
|
|
player_type type) {
|
|
Mutex::Autolock lock_(&sLock);
|
|
return registerFactory_l(factory, type);
|
|
}
|
|
|
|
void MediaPlayerFactory::unregisterFactory(player_type type) {
|
|
Mutex::Autolock lock_(&sLock);
|
|
sFactoryMap.removeItem(type);
|
|
}
|
|
|
|
#define GET_PLAYER_TYPE_IMPL(a...) \
|
|
Mutex::Autolock lock_(&sLock); \
|
|
\
|
|
player_type ret = STAGEFRIGHT_PLAYER; \
|
|
float bestScore = 0.0; \
|
|
\
|
|
for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
|
|
\
|
|
IFactory* v = sFactoryMap.valueAt(i); \
|
|
float thisScore; \
|
|
CHECK(v != NULL); \
|
|
thisScore = v->scoreFactory(a, bestScore); \
|
|
if (thisScore > bestScore) { \
|
|
ret = sFactoryMap.keyAt(i); \
|
|
bestScore = thisScore; \
|
|
} \
|
|
} \
|
|
\
|
|
if (0.0 == bestScore) { \
|
|
ret = getDefaultPlayerType(); \
|
|
} \
|
|
\
|
|
return ret;
|
|
|
|
player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
|
|
const char* url) {
|
|
GET_PLAYER_TYPE_IMPL(client, url);
|
|
}
|
|
|
|
player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
|
|
int fd,
|
|
int64_t offset,
|
|
int64_t length) {
|
|
GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
|
|
}
|
|
|
|
player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
|
|
const sp<IStreamSource> &source) {
|
|
GET_PLAYER_TYPE_IMPL(client, source);
|
|
}
|
|
|
|
player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
|
|
const sp<DataSource> &source) {
|
|
GET_PLAYER_TYPE_IMPL(client, source);
|
|
}
|
|
|
|
#undef GET_PLAYER_TYPE_IMPL
|
|
|
|
sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
|
|
player_type playerType,
|
|
const sp<MediaPlayerBase::Listener> &listener,
|
|
pid_t pid) {
|
|
sp<MediaPlayerBase> p;
|
|
IFactory* factory;
|
|
status_t init_result;
|
|
Mutex::Autolock lock_(&sLock);
|
|
|
|
if (sFactoryMap.indexOfKey(playerType) < 0) {
|
|
ALOGE("Failed to create player object of type %d, no registered"
|
|
" factory", playerType);
|
|
return p;
|
|
}
|
|
|
|
factory = sFactoryMap.valueFor(playerType);
|
|
CHECK(NULL != factory);
|
|
p = factory->createPlayer(pid);
|
|
|
|
if (p == NULL) {
|
|
ALOGE("Failed to create player object of type %d, create failed",
|
|
playerType);
|
|
return p;
|
|
}
|
|
|
|
init_result = p->initCheck();
|
|
if (init_result == NO_ERROR) {
|
|
p->setNotifyCallback(listener);
|
|
} else {
|
|
ALOGE("Failed to create player object of type %d, initCheck failed"
|
|
" (res = %d)", playerType, init_result);
|
|
p.clear();
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* *
|
|
* Built-In Factory Implementations *
|
|
* *
|
|
*****************************************************************************/
|
|
|
|
class NuPlayerFactory : public MediaPlayerFactory::IFactory {
|
|
public:
|
|
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
|
|
const char* url,
|
|
float curScore) {
|
|
static const float kOurScore = 0.8;
|
|
|
|
if (kOurScore <= curScore)
|
|
return 0.0;
|
|
|
|
if (!strncasecmp("http://", url, 7)
|
|
|| !strncasecmp("https://", url, 8)
|
|
|| !strncasecmp("file://", url, 7)) {
|
|
size_t len = strlen(url);
|
|
if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
|
|
return kOurScore;
|
|
}
|
|
|
|
if (strstr(url,"m3u8")) {
|
|
return kOurScore;
|
|
}
|
|
|
|
if ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?")) {
|
|
return kOurScore;
|
|
}
|
|
}
|
|
|
|
if (!strncasecmp("rtsp://", url, 7)) {
|
|
return kOurScore;
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
|
|
const sp<IStreamSource>& /*source*/,
|
|
float /*curScore*/) {
|
|
return 1.0;
|
|
}
|
|
|
|
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
|
|
const sp<DataSource>& /*source*/,
|
|
float /*curScore*/) {
|
|
// Only NuPlayer supports setting a DataSource source directly.
|
|
return 1.0;
|
|
}
|
|
|
|
virtual sp<MediaPlayerBase> createPlayer(pid_t pid) {
|
|
ALOGV(" create NuPlayer");
|
|
return new NuPlayerDriver(pid);
|
|
}
|
|
};
|
|
|
|
class TestPlayerFactory : public MediaPlayerFactory::IFactory {
|
|
public:
|
|
virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/,
|
|
const char* url,
|
|
float /*curScore*/) {
|
|
if (TestPlayerStub::canBeUsed(url)) {
|
|
return 1.0;
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
virtual sp<MediaPlayerBase> createPlayer(pid_t /* pid */) {
|
|
ALOGV("Create Test Player stub");
|
|
return new TestPlayerStub();
|
|
}
|
|
};
|
|
|
|
void MediaPlayerFactory::registerBuiltinFactories() {
|
|
Mutex::Autolock lock_(&sLock);
|
|
|
|
if (sInitComplete)
|
|
return;
|
|
|
|
IFactory* factory = new NuPlayerFactory();
|
|
if (registerFactory_l(factory, NU_PLAYER) != OK)
|
|
delete factory;
|
|
factory = new TestPlayerFactory();
|
|
if (registerFactory_l(factory, TEST_PLAYER) != OK)
|
|
delete factory;
|
|
|
|
sInitComplete = true;
|
|
}
|
|
|
|
} // namespace android
|