上一节我们了解到
android_media_MediaPlayer.cpp
中封装的是MediaPlayer native实现,这一节我们就来了解它的内部实现。
1、MediaPlayer
MediaPlayer native代码位于frameworks/av/media/libmedia/mediaplayer.cpp
先来看MediaPlayer
的声明,它继承于BnMediaPlayerClient
,包含一个IMediaPlayer
成员以及一个notify
方法。
class MediaPlayer : public BnMediaPlayerClient,public virtual IMediaDeathNotifier
{sp<IMediaPlayer> mPlayer;void notify(int msg, int ext1, int ext2, const Parcel *obj = NULL);
}
- mPlayer是通过
mediaserver
获取到的; - notify用于底层向上callback;
- 继承于
BnMediaPlayerClient
是因为MediaPlayer对象会通过binder传递给IMediaPlayer
,从而实现callback功能,从IMediaPlayerClient.h
中可以看到binder接口只有一个notify;
callback用的比较多方法的是声明一个ICallback对象,里面存储有上层对象,将这个ICallback通过binder传递到底层,而不是将上层对象直接传递下去,这里的用法比较少见,可以学习一下~
接下来看如何获取IMediaPlayer对象的:
status_t MediaPlayer::setDataSource(const sp<IMediaHTTPService> &httpService,const char *url, const KeyedVector<String8, String8> *headers)
{status_t err = BAD_VALUE;if (url != NULL) {// 获取MediaPlayerServiceconst sp<IMediaPlayerService> service(getMediaPlayerService());if (service != 0) {// create playersp<IMediaPlayer> player(service->create(this, mAudioSessionId, mAttributionSource));// call setDataSourceplayer->setDataSource(httpService, url, headers);// save playererr = attachNewPlayer(player);}}return err;
}
- 先获取
media.player
服务; - 调用服务的
create
方法创建本地IMediaPlayer
对象,并将自身作为参数传递,返回IMediaPlayer
的远程代理; - 调用
IMediaPlayer
的setDataSource
方法; - 将
IMediaPlayer
对象存储到mPlayer
。
IMediaPlayer的销毁流程如下:
void MediaPlayer::disconnect()
{sp<IMediaPlayer> p;{Mutex::Autolock _l(mLock);p = mPlayer;mPlayer.clear();}if (p != 0) {p->disconnect();}
}
- 调用
IMediaPlayer
的disconnect方法 - 离开disconnect函数作用域,
IMediaPlayer
自动销毁
MediaPlayer::disconnect
中会先加锁,接着将mPlayer赋给一个新的局部变量p,然后释放掉mPlayer的内容。为什么要这么做?我猜想是为了缩短锁占用的时间。
最后来看callback方法notify
,这个方法可以透过binder来跨进程调用,所以最后一个自定义的数据类型是Parcel。底层调用notify后,mediaplayer native会根据事件类型判断是否再将事件上抛。
void MediaPlayer::notify(int msg, int ext1, int ext2, const Parcel *obj)
{ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);bool send = true;....sp<MediaPlayerListener> listener = mListener;...if ((listener != 0) && send) {Mutex::Autolock _l(mNotifyLock);listener->notify(msg, ext1, ext2, obj);}
}
2、MediaServer
上一节我们了解了MediaPlayer native封装的是一个IMediaPlayer
对象,这个对象是由mediaserver
这个binder service创建的,这一节我们就来了解mediaserver
。
mediaserver
服务的启动代码位于frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc __unused, char **argv __unused)
{......MediaPlayerService::instantiate();ResourceManagerService::instantiate();......
}
mediaserver其实提供有两个服务,一个是MediaPlayerService(media.player),另一个是资源管理服务ResourceManagerService(media.resource_manager),这里我们仅了解MediaPlayerService。