转载请注明出处:http://blog.csdn.net/superfang119/article/details/8250166
最近在做一个基于android的dvb的机顶盒,需要在android上增加实现对数字电视的支持。因此先对MediaPlayer进行一个深度的了解,以便能够合理的添加所需的功能。
我的平台是海思的3716c,基于android4.0定制的代码,所有可以文中分析的代码有可能与标准的代码不同。
好了,不废话了,现在就来分析下MediaPlayer吧。
android中的 MediaPlayer主要包括应用层,框架中的java层,框架中的c++层,HAL层,和硬件驱动部分组成。
采取了服务器,客户端的方式来进行对MediaPlayer的处理。服务器与客服端之间使用binder的通信机制,这种机制在以后的分析中将逐步的接触到。
先主要分析一下框架中的c++层中MediaPlayer的后台服务的前世今生。
android中的后台原生服务都是由init程序负责启动的。init程序是android的第一个运行的程序,它通过分析init.rc文件来启动相应的后台服务程序,我们的MediaPlayer的后台服务程序的启动部分在init.rc中的表述如下:
- service media /system/bin/mediaserver
- class main
- user media
- group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc
- ioprio rt 4
init.rc是使用android的初始化语言来编写的。它包括了4种类型的语法:
动作 Action
指令 Commands
服务 Service
选项 Options
MediaPlayer后台服务的名称叫做"mediaserver",代码位于main_mediaserver.cpp@frameworks/base/media/mediaserver中。
- int main(int argc, char** argv)
- {
- /*用prctl函数给线程命名*/
- prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
- /*设置组id和用户id为AID_MEDIA(android id 1013)*/
- setgid(AID_MEDIA);
- setuid(AID_MEDIA);
- /*下面这堆先不研究,以后在补充*/
- struct __user_cap_header_struct header;
- struct __user_cap_data_struct cap;
- header.pid = getpid();
- header.version = _LINUX_CAPABILITY_VERSION;
- if (capget(&header, &cap) < 0) {
- LOGE("capget error! errno = %d.", errno);
- }
- else {
- LOGD("Cap data 0x%x, 0x%x, 0x%x\n", cap.effective,
- cap.permitted, cap.inheritable);
- }
- header.version = _LINUX_CAPABILITY_VERSION;
- header.pid = 0;
- cap.effective = cap.permitted = (1 << CAP_SYS_RAWIO) | (1 << CAP_DAC_OVERRIDE);
- cap.inheritable = 0;
- if ( capset(&header, &cap)) {
- LOGE("capset error! errno = %d, pid = %d.", errno, getpid());
- }
- /*创建进程状态,准备binder的通信*/
- sp<ProcessState> proc(ProcessState::self());
- /*得到默认的服务管理器,就是大管家哦,用来添加和查询服务的。*/
- sp<IServiceManager> sm = defaultServiceManager();
- LOGI("ServiceManager: %p", sm.get());
- /*注册AudioFlinger服务*/
- AudioFlinger::instantiate();
- /*这个就是本文的主要,注册MediaPlayer服务。。。^_^*/
- MediaPlayerService::instantiate();
- /*注册相机服务,相机也是使用服务器客户端模式哦。*/
- CameraService::instantiate();
- /*注册音频策略的服务,和音频和输入输出有关,以后会分析。。*/
- AudioPolicyService::instantiate();
- /*创建一个线程来处理binder通信*/
- ProcessState::self()->startThreadPool();
- /*加入线程池,启动binder通信。。。binder通信的问题以后在研究。。(*^__^*) 嘻嘻……*/
- IPCThreadState::self()->joinThreadPool();
- }
我们从程序中可以看出这个后台程序主要启动了一些和meida有关的服务,包括了AudioFlinger,MediaPlayerService,CameraService,AudioPolicyService.。
我们先来分析一下MediaPlayerService服务这个大骨头,难啃啊。。。
看一下MeidaPlayerService::instantiate()函数干了什么事情。
它的代码在MediaPlayerService.cpp@frameworks/base/media/libmediadisplayerservice中。
- void MediaPlayerService::instantiate()
- {
- /*新建一个MediaPlayerService的对象,把它添加到服务列表中。
- 服务的名称为“meida.player”*/
- defaultServiceManager()->addService(
- String16("media.player"), new MediaPlayerService());
- }
defaultServiceManager()得到默认的服务管理器。android服务大总管,负责android中服务的添加和查询。关于它的分析我们会在其他问中介绍,本文只要只要通过它的addService函数就可以添加一个服务就行了。
程序中新建了一个MediaPlayerService的对象,作为新添加的服务,“media.player”是这个服务的名称,以后查询这个服务就靠它了。
再来看看MediaPlayerService这个类,它定义有两个部分。
包括头文件MediaPlayerService.h和实现文件MediaPlayerService.cpp
它们都定义在frameworks/base/media/libmediaplayerservice目录中。
先看一下这个类的声明。
- class MediaPlayerService : public BnMediaPlayerService
- {
- class Client;
- class MediaConfigClient;
- class AudioOutput : public MediaPlayerBase::AudioSink
- {
- ...
- };
- class AudioCache : public MediaPlayerBase::AudioSink
- {
- ...
- };
- public:
- static void instantiate();
- // IMediaPlayerService interface
- virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid);
- void removeMediaRecorderClient(wp<MediaRecorderClient> client);
- virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client,
- int audioSessionId);
- virtual sp<IMediaConfig> createMediaConfig(pid_t pid);
- virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate,
- int* pNumChannels, int* pFormat);
- virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length,
- uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
- virtual sp<IOMX> getOMX();
- virtual status_t dump(int fd, const Vector<String16>& args);
- void removeClient(wp<Client> client);
- ...
- private:
- class Client : public BnMediaPlayer
- {
- ...
- };
- class MediaConfigClient: public BnMediaConfig
- {
- ...
- };
- // ----------------------------------------------------------------------------
- MediaPlayerService();
- virtual ~MediaPlayerService();
- ...
- };
我们看到了MediaPlayerService的类继承至BnMediaPlayerService的类。这个Bn类就是服务端的类了。它是由android的binder通信机制来实现的。
讲这个Bn类之前,我们先来简要的介绍一下android中关于binder通信。
本来想将一下的,太多了,打字太累,以后在说,大家可以想看看大神写的文章http://blog.csdn.net/innost/article/details/6124685。。哈哈偷懒一下。
从大神文章可知,一个binder的服务,要编写它的Ixxx接口,Bnxxx服务端,Bpxxx客户端。
上面是MediaPlayerService的Bn服务端,我们先来看看它的接口IMediaPlayerService。它在IMediaPlayerService.h中定义。位置在framworks/base/include/media中。
- class IMediaPlayerService: public IInterface
- {
- public:
- DECLARE_META_INTERFACE(MediaPlayerService);
- virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid) = 0;
- virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0;
- virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId = 0) = 0;
- virtual sp<IMediaConfig> createMediaConfig(pid_t pid ) = 0;
- virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
- virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
- virtual sp<IOMX> getOMX() = 0;
- // codecs and audio devices usage tracking for the battery app
- enum BatteryDataBits {
- // tracking audio codec
- kBatteryDataTrackAudio = 0x1,
- // tracking video codec
- kBatteryDataTrackVideo = 0x2,
- // codec is started, otherwise codec is paused
- kBatteryDataCodecStarted = 0x4,
- // tracking decoder (for media player),
- // otherwise tracking encoder (for media recorder)
- kBatteryDataTrackDecoder = 0x8,
- // start to play an audio on an audio device
- kBatteryDataAudioFlingerStart = 0x10,
- // stop/pause the audio playback
- kBatteryDataAudioFlingerStop = 0x20,
- // audio is rounted to speaker
- kBatteryDataSpeakerOn = 0x40,
- // audio is rounted to devices other than speaker
- kBatteryDataOtherAudioDeviceOn = 0x80,
- };
- virtual void setHiplayerVol(int stream,float vol)=0;
- virtual void addBatteryData(uint32_t params) = 0;
- virtual status_t pullBatteryData(Parcel* reply) = 0;
- };
如果定义的服务名是xxx,那么它的接口一定要命名为Ixxx,Bn服务端一定要定义为Bnxxx,Bp客户端一定要定义为Bpxxx
在这个接口类的前部有一句话DECLARE_META_INTERFACE(MediaPlayerService);这个是一个宏定义,MediaPlayerService就是服务名xxx。
DECLARE_META_INTERFACE的定义如下:
- #define DECLARE_META_INTERFACE(INTERFACE) \
- static const android::String16 descriptor; \
- static android::sp<I##INTERFACE> asInterface( \
- const android::sp<android::IBinder>& obj); \
- virtual const android::String16& getInterfaceDescriptor() const; \
- I##INTERFACE(); \
- virtual ~I##INTERFACE(); \
与它对于是的IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");
IMPLEMENT_META_INTERFACE这个宏的定义为:
- #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
- const android::String16 I##INTERFACE::descriptor(NAME); \
- const android::String16& \
- I##INTERFACE::getInterfaceDescriptor() const { \
- return I##INTERFACE::descriptor; \
- } \
- android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
- const android::sp<android::IBinder>& obj) \
- { \
- android::sp<I##INTERFACE> intr; \
- if (obj != NULL) { \
- intr = static_cast<I##INTERFACE*>( \
- obj->queryLocalInterface( \
- I##INTERFACE::descriptor).get()); \
- if (intr == NULL) { \
- intr = new Bp##INTERFACE(obj); \
- } \
- } \
- return intr; \
- } \
- I##INTERFACE::I##INTERFACE() { } \
- I##INTERFACE::~I##INTERFACE() { } \
可以看出主要提供了descriptor属性,以及asInterface方法,getInterfaceDescriptor方法。
asInterface方法主要是用来获得服务的客户端Bpxxx的。它的输入参数是一个实现IBinder接口的对象,其他就是包
未完待续。。。。。。。