您的位置:首页 > 其它

Audio笔记之MediaPlayerService:setDataSource

2015-06-15 18:05 399 查看
//下面是一个典型的播放序列:
MediaPlayer player=new MediaPlayer()
player->setDataSource(url,header);
player->prepare();
player->start();
...
//使用MediaPlayerServcie的Client对象设置数据源
status_t MediaPlayer::setDataSource(
const char *url, const KeyedVector<String8, String8> *headers)
{
ALOGV("setDataSource(%s)", url);
status_t err = BAD_VALUE;
if (url != NULL) {
//1、获得MediaPlayerService
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != 0) {
//2、返回MediaPlayerService的Client对象player,并保存在Service的数组对象中,
//后续使用该Client将向MediaPlayer提供服务,因此每个MediaPlayer都对应一个Client
sp<IMediaPlayer> player(service->create(this, mAudioSessionId));
//3、选择正确的播放器,并设置播放器的数据源
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(url, headers))) {
player.clear();
}
//4、保存最新的Client对象,断开之前Client对象
err = attachNewPlayer(player);
}
}
return err;
}
1、获取MeidaPlayerSercie
/*static*/const sp<IMediaPlayerService>&
IMediaDeathNotifier::getMediaPlayerService()
{
ALOGV("getMediaPlayerService");
Mutex::Autolock _l(sServiceLock);
if (sMediaPlayerService == 0) {
//获得BpServiceManager对象
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
do {
binder = sm->getService(String16("media.player"));
if (binder != 0) {
break;
}
ALOGW("Media player service not published, waiting...");
usleep(500000); // 0.5 s
} while (true);

if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier();
}
//通过Bind获取BpMediaPlayerService对象
binder->linkToDeath(sDeathNotifier);
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
}
ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
return sMediaPlayerService;
}
2、构造MediaPlayerService的Client对象
sp<IMediaPlayer> MediaPlayerService::create(const sp<IMediaPlayerClient>& client,
int audioSessionId)
{
pid_t pid = IPCThreadState::self()->getCallingPid();
int32_t connId = android_atomic_inc(&mNextConnId);

sp<Client> c = new Client(
this, pid, connId, client, audioSessionId,
IPCThreadState::self()->getCallingUid());

ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid,
IPCThreadState::self()->getCallingUid());

wp<Client> w = c;
{
Mutex::Autolock lock(mLock);
mClients.add(w);
}
return c;
}
//保存Client端的AudioSessionId等信息
MediaPlayerService::Client::Client(
const sp<MediaPlayerService>& service, pid_t pid,
int32_t connId, const sp<IMediaPlayerClient>& client,
int audioSessionId, uid_t uid)
{
ALOGV("Client(%d) constructor", connId);
mPid = pid;
mConnId = connId;
mService = service;
mClient = client;
mLoop = false;
mStatus = NO_INIT;
mAudioSessionId = audioSessionId;
mUID = uid;
mRetransmitEndpointValid = false;

#if CALLBACK_ANTAGONIZER
ALOGD("create Antagonizer");
mAntagonizer = new Antagonizer(notify, this);
#endif
}
//通过url获取对应的播放器,然后保存该播放器,并设置播放器的数据源
status_t MediaPlayerService::Client::setDataSource(
const char *url, const KeyedVector<String8, String8> *headers)
{
ALOGV("setDataSource(%s)", url);
if (url == NULL)
return UNKNOWN_ERROR;

if ((strncmp(url, "http://", 7) == 0) ||
(strncmp(url, "https://", 8) == 0) ||
(strncmp(url, "rtsp://", 7) == 0)) {
if (!checkPermission("android.permission.INTERNET")) {
return PERMISSION_DENIED;
}
}

if (strncmp(url, "content://", 10) == 0) {
// get a filedescriptor for the content Uri and
// pass it to the setDataSource(fd) method

String16 url16(url);
int fd = android::openContentProviderFile(url16);
if (fd < 0)
{
ALOGE("Couldn't open fd for %s", url);
return UNKNOWN_ERROR;
}
setDataSource(fd, 0, 0x7fffffffffLL); // this sets mStatus
close(fd);
return mStatus;
} else {
//通过url获取对应的播放器
player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
sp<MediaPlayerBase> p = setDataSource_pre(playerType);
if (p == NULL) {
return NO_INIT;
}

setDataSource_post(p, p->setDataSource(url, headers));
return mStatus;
}
}
//通过播放器工厂的scoreFactory函数判断该播放器是否合适,选择播放器类型
#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);
}
//这里如果所有播放器都不合适,则选择默认播放器这里流程是,
//从播放器仓库中选取最佳播放器,通过scoreFactory来确定
player_type MediaPlayerFactory::getDefaultPlayerType() {
char value[PROPERTY_VALUE_MAX];
if (property_get("media.stagefright.use-nuplayer", value, NULL)
&& (!strcmp("1", value) || !strcasecmp("true", value))) {
return NU_PLAYER;
}

return STAGEFRIGHT_PLAYER;
}


sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre(
player_type playerType)
{
ALOGV("player type = %d", playerType);

// create the right type of player
sp<MediaPlayerBase> p = createPlayer(playerType);
if (p == NULL) {
return p;
}
//根据AudioSessionId设置播放器的输出端
if (!p->hardwareOutput()) {
mAudioOutput = new AudioOutput(mAudioSessionId);
static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput);
}

return p;
}
sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
{
// determine if we have the right player type
sp<MediaPlayerBase> p = mPlayer;
if ((p != NULL) && (p->playerType() != playerType)) {
ALOGV("delete player");
p.clear();
}
if (p == NULL) {
p = MediaPlayerFactory::createPlayer(playerType, this, notify);
}

if (p != NULL) {
p->setUID(mUID);
}

return p;
}
//主要是创建播放器

//上面看具体StagefrightPlayerFactory 实现的时候,代码中实现了createPlayer,此处就是调用的此方法

//因此等价于return (new StagefrightPlayer()) ;
void MediaPlayerService::Client::setDataSource_post(
const sp<MediaPlayerBase>& p,
status_t status)
{
ALOGV(" setDataSource");
mStatus = status;
if (mStatus != OK) {
ALOGE("  error: %d", mStatus);
return;
}

// Set the re-transmission endpoint if one was chosen.
if (mRetransmitEndpointValid) {
mStatus = p->setRetransmitEndpoint(&mRetransmitEndpoint);
if (mStatus != NO_ERROR) {
ALOGE("setRetransmitEndpoint error: %d", mStatus);
}
}

if (mStatus == OK) {
mPlayer = p;
}
}
//setDataSource_post(p, p->setDataSource(source))
//设置播放器的数据源,因为实际的视屏播放是由该播放器完成
status_t StagefrightPlayer::setDataSource(
const char *url, const KeyedVector<String8, String8> *headers) {
return mPlayer->setDataSource(url, headers);
}
status_t AwesomePlayer::setDataSource(
const char *uri, const KeyedVector<String8, String8> *headers) {
Mutex::Autolock autoLock(mLock);
return setDataSource_l(uri, headers);
}
status_t AwesomePlayer::setDataSource_l(
const char *uri, const KeyedVector<String8, String8> *headers) {
reset_l();

mUri = uri;

if (headers) {
mUriHeaders = *headers;

ssize_t index = mUriHeaders.indexOfKey(String8("x-hide-urls-from-log"));
if (index >= 0) {
// Browser is in "incognito" mode, suppress logging URLs.

// This isn't something that should be passed to the server.
mUriHeaders.removeItemsAt(index);

modifyFlags(INCOGNITO, SET);
}
}

ALOGI("setDataSource_l(URL suppressed)");

// The actual work will be done during preparation in the call to
// ::finishSetDataSource_l to avoid blocking the calling thread in
// setDataSource for any significant time.

{
Mutex::Autolock autoLock(mStatsLock);
mStats.mFd = -1;
mStats.mURI = mUri;
}

return OK;
}
//4、保存新的MediaPlayerService的Client对象,并断开之前的Client和Service
status_t MediaPlayer::attachNewPlayer(const sp<IMediaPlayer>& player)
{
status_t err = UNKNOWN_ERROR;
sp<IMediaPlayer> p;
{ // scope for the lock
Mutex::Autolock _l(mLock);

if ( !( (mCurrentState & MEDIA_PLAYER_IDLE) ||
(mCurrentState == MEDIA_PLAYER_STATE_ERROR ) ) ) {
ALOGE("attachNewPlayer called in state %d", mCurrentState);
return INVALID_OPERATION;
}
//重置相关参数
clear_l();
p = mPlayer;
mPlayer = player;//更新Client属性
if (player != 0) {
mCurrentState = MEDIA_PLAYER_INITIALIZED;
err = NO_ERROR;
} else {
ALOGE("Unable to create media player");
}
}
//断开之前的Client
if (p != 0) {
p->disconnect();
}

return err;
}
// always call with lock held
void MediaPlayer::clear_l()
{
mCurrentPosition = -1;
mSeekPosition = -1;
mVideoWidth = mVideoHeight = 0;
mRetransmitEndpointValid = false;
}
void MediaPlayerService::Client::disconnect()
{
ALOGV("disconnect(%d) from pid %d", mConnId, mPid);
// grab local reference and clear main reference to prevent future
// access to object
sp<MediaPlayerBase> p;
{
Mutex::Autolock l(mLock);
p = mPlayer;//播放器对象,如StagefrightPlayer
mClient.clear();//MdediaPlayer对象
}

mPlayer.clear();

// clear the notification to prevent callbacks to dead client
// and reset the player. We assume the player will serialize
// access to itself if necessary.
if (p != 0) {
p->setNotifyCallback(0, 0);
#if CALLBACK_ANTAGONIZER
ALOGD("kill Antagonizer");
mAntagonizer->kill();
#endif
p->reset();//调用具体播放器的reset函数,如
}

disconnectNativeWindow();

IPCThreadState::self()->flushCommands();
}
void MediaPlayerService::Client::disconnectNativeWindow() {
if (mConnectedWindow != NULL) {
status_t err = native_window_api_disconnect(mConnectedWindow.get(),
NATIVE_WINDOW_API_MEDIA);

if (err != OK) {
ALOGW("native_window_api_disconnect returned an error: %s (%d)",
strerror(-err), err);
}
}
mConnectedWindow.clear();
}
status_t StagefrightPlayer::reset() {
ALOGV("reset");

mPlayer->reset();

return OK;
}
//具体的reset操作,不同的播放器有不同的实现
void AwesomePlayer::reset_l() {
mVideoRenderingStarted = false;
mActiveAudioTrackIndex = -1;
mDisplayWidth = 0;
mDisplayHeight = 0;

if (mDecryptHandle != NULL) {
mDrmManagerClient->setPlaybackStatus(mDecryptHandle,
Playback::STOP, 0);
mDecryptHandle = NULL;
mDrmManagerClient = NULL;
}

if (mFlags & PLAYING) {
uint32_t params = IMediaPlayerService::kBatteryDataTrackDecoder;
if ((mAudioSource != NULL) && (mAudioSource != mAudioTrack)) {
params |= IMediaPlayerService::kBatteryDataTrackAudio;
}
if (mVideoSource != NULL) {
params |= IMediaPlayerService::kBatteryDataTrackVideo;
}
addBatteryData(params);
}

if (mFlags & PREPARING) {
modifyFlags(PREPARE_CANCELLED, SET);
if (mConnectingDataSource != NULL) {
ALOGI("interrupting the connection process");
mConnectingDataSource->disconnect();
}

if (mFlags & PREPARING_CONNECTED) {
// We are basically done preparing, we're just buffering
// enough data to start playback, we can safely interrupt that.
finishAsyncPrepare_l();
}
}

while (mFlags & PREPARING) {
mPreparedCondition.wait(mLock);
}

cancelPlayerEvents();

mWVMExtractor.clear();
mCachedSource.clear();
mAudioTrack.clear();
mVideoTrack.clear();
mExtractor.clear();

// Shutdown audio first, so that the respone to the reset request
// appears to happen instantaneously as far as the user is concerned
// If we did this later, audio would continue playing while we
// shutdown the video-related resources and the player appear to
// not be as responsive to a reset request.
if ((mAudioPlayer == NULL || !(mFlags & AUDIOPLAYER_STARTED))
&& mAudioSource != NULL) {
// If we had an audio player, it would have effectively
// taken possession of the audio source and stopped it when
// _it_ is stopped. Otherwise this is still our responsibility.
mAudioSource->stop();
}
mAudioSource.clear();

mTimeSource = NULL;

delete mAudioPlayer;
mAudioPlayer = NULL;

if (mTextDriver != NULL) {
delete mTextDriver;
mTextDriver = NULL;
}

mVideoRenderer.clear();

if (mVideoSource != NULL) {
shutdownVideoDecoder_l();
}

mDurationUs = -1;
modifyFlags(0, ASSIGN);
mExtractorFlags = 0;
mTimeSourceDeltaUs = 0;
mVideoTimeUs = 0;

mSeeking = NO_SEEK;
mSeekNotificationSent = true;
mSeekTimeUs = 0;

mUri.setTo("");
mUriHeaders.clear();

mFileSource.clear();

mBitrate = -1;
mLastVideoTimeUs = -1;

{
Mutex::Autolock autoLock(mStatsLock);
mStats.mFd = -1;
mStats.mURI = String8();
mStats.mBitrate = -1;
mStats.mAudioTrackIndex = -1;
mStats.mVideoTrackIndex = -1;
mStats.mNumVideoFramesDecoded = 0;
mStats.mNumVideoFramesDropped = 0;
mStats.mVideoWidth = -1;
mStats.mVideoHeight = -1;
mStats.mFlags = 0;
mStats.mTracks.clear();
}

mWatchForAudioSeekComplete = false;
mWatchForAudioEOS = false;
}

以上调用流程:

MediaPlayer(JAVA层)->MediaPlayer(C层)->Client->MediaPlayService->StagefrightPlayer->AwesomePlayer

最终所有对应具体文件的操作都需要AwesomePlayer落实,如:

prepare

play

pause

总结下几种播放器的区别

StagefrightPlayer: 默认播放器,本地文件基本都使用其播放

NuPlayerDriver:主要用于播放网络视频,http https rtsp等

SonivoxPlayer:用于播放midi等类型的音乐
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: