android MediaPlayer深入分析

转载请注明出处: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中的表述如下:

[plain]  view plain copy
  1. service media /system/bin/mediaserver  
  2.     class main  
  3.     user media  
  4.     group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc  
  5.     ioprio rt 4  

init.rc是使用android的初始化语言来编写的。它包括了4种类型的语法:

动作 Action 

指令 Commands

服务 Service

选项 Options


MediaPlayer后台服务的名称叫做"mediaserver",代码位于main_mediaserver.cpp@frameworks/base/media/mediaserver中。


[cpp]  view plain copy
  1. int main(int argc, char** argv)  
  2. {  
  3.     /*用prctl函数给线程命名*/  
  4.     prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);  
  5.     /*设置组id和用户id为AID_MEDIA(android id 1013)*/  
  6.         setgid(AID_MEDIA);  
  7.         setuid(AID_MEDIA);  
  8.   
  9.     /*下面这堆先不研究,以后在补充*/  
  10.         struct __user_cap_header_struct header;  
  11.         struct __user_cap_data_struct cap;  
  12.   
  13.         header.pid = getpid();  
  14.         header.version = _LINUX_CAPABILITY_VERSION;  
  15.         if (capget(&header, &cap) < 0) {  
  16.             LOGE("capget error! errno = %d.", errno);  
  17.         }  
  18.         else {  
  19.             LOGD("Cap data 0x%x, 0x%x, 0x%x\n", cap.effective,  
  20.                 cap.permitted, cap.inheritable);  
  21.         }  
  22.   
  23.         header.version = _LINUX_CAPABILITY_VERSION;  
  24.         header.pid = 0;  
  25.         cap.effective = cap.permitted = (1 << CAP_SYS_RAWIO) | (1 << CAP_DAC_OVERRIDE);  
  26.         cap.inheritable = 0;  
  27.         if ( capset(&header, &cap)) {  
  28.             LOGE("capset error! errno = %d, pid = %d.", errno, getpid());  
  29.         }  
  30.     /*创建进程状态,准备binder的通信*/  
  31.         sp<ProcessState> proc(ProcessState::self());  
  32.     /*得到默认的服务管理器,就是大管家哦,用来添加和查询服务的。*/  
  33.         sp<IServiceManager> sm = defaultServiceManager();  
  34.         LOGI("ServiceManager: %p", sm.get());   
  35.     /*注册AudioFlinger服务*/  
  36.         AudioFlinger::instantiate();  
  37.     /*这个就是本文的主要,注册MediaPlayer服务。。。^_^*/  
  38.         MediaPlayerService::instantiate();  
  39.     /*注册相机服务,相机也是使用服务器客户端模式哦。*/  
  40.         CameraService::instantiate();  
  41.     /*注册音频策略的服务,和音频和输入输出有关,以后会分析。。*/  
  42.         AudioPolicyService::instantiate();  
  43.         /*创建一个线程来处理binder通信*/  
  44.         ProcessState::self()->startThreadPool();  
  45.     /*加入线程池,启动binder通信。。。binder通信的问题以后在研究。。(*^__^*) 嘻嘻……*/  
  46.         IPCThreadState::self()->joinThreadPool();  
  47. }  

我们从程序中可以看出这个后台程序主要启动了一些和meida有关的服务,包括了AudioFlinger,MediaPlayerService,CameraService,AudioPolicyService.。

我们先来分析一下MediaPlayerService服务这个大骨头,难啃啊。。。


看一下MeidaPlayerService::instantiate()函数干了什么事情。

它的代码在MediaPlayerService.cpp@frameworks/base/media/libmediadisplayerservice中。

[cpp]  view plain copy
  1. void MediaPlayerService::instantiate()   
  2. {  
  3.     /*新建一个MediaPlayerService的对象,把它添加到服务列表中。 
  4.       服务的名称为“meida.player”*/  
  5.     defaultServiceManager()->addService(  
  6.         String16("media.player"), new MediaPlayerService());  
  7. }  

defaultServiceManager()得到默认的服务管理器。android服务大总管,负责android中服务的添加和查询。关于它的分析我们会在其他问中介绍,本文只要只要通过它的addService函数就可以添加一个服务就行了。

程序中新建了一个MediaPlayerService的对象,作为新添加的服务,“media.player”是这个服务的名称,以后查询这个服务就靠它了。


再来看看MediaPlayerService这个类,它定义有两个部分。

包括头文件MediaPlayerService.h和实现文件MediaPlayerService.cpp

它们都定义在frameworks/base/media/libmediaplayerservice目录中。

先看一下这个类的声明。


[cpp]  view plain copy
  1. class MediaPlayerService : public BnMediaPlayerService  
  2. {  
  3.     class Client;  
  4.     class MediaConfigClient;  
  5.   
  6.     class AudioOutput : public MediaPlayerBase::AudioSink  
  7.     {  
  8.    
  9.     ...  
  10.   
  11.     };  
  12.   
  13.     class AudioCache : public MediaPlayerBase::AudioSink  
  14.     {  
  15.     ...  
  16.     };  
  17.   
  18. public:  
  19.     static  void                instantiate();  
  20.   
  21.     // IMediaPlayerService interface  
  22.     virtual sp<IMediaRecorder>  createMediaRecorder(pid_t pid);  
  23.     void    removeMediaRecorderClient(wp<MediaRecorderClient> client);  
  24.     virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid);  
  25.   
  26.     virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client,   
  27.                     int audioSessionId);  
  28.   
  29.     virtual sp<IMediaConfig>   createMediaConfig(pid_t pid);  
  30.     virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate,   
  31.                     int* pNumChannels, int* pFormat);  
  32.     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length,   
  33.                     uint32_t *pSampleRate, int* pNumChannels, int* pFormat);  
  34.     virtual sp<IOMX>            getOMX();  
  35.   
  36.     virtual status_t            dump(int fd, const Vector<String16>& args);  
  37.   
  38.             void                removeClient(wp<Client> client);  
  39.   
  40.   
  41.   
  42.     ...  
  43. private:  
  44.   
  45.     class Client : public BnMediaPlayer   
  46.     {  
  47.     ...  
  48.    
  49.     };  
  50.   
  51.   
  52.     class MediaConfigClient: public BnMediaConfig  
  53.     {  
  54.     ...  
  55.     };  
  56.   
  57. // ----------------------------------------------------------------------------  
  58.   
  59.                             MediaPlayerService();  
  60.     virtual                 ~MediaPlayerService();  
  61.   
  62.     ...  
  63. };  

我们看到了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中。

[cpp]  view plain copy
  1. class IMediaPlayerService: public IInterface  
  2. {  
  3. public:  
  4.     DECLARE_META_INTERFACE(MediaPlayerService);  
  5.   
  6.     virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid) = 0;  
  7.     virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0;  
  8.     virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int audioSessionId = 0) = 0;  
  9.     virtual sp<IMediaConfig>    createMediaConfig(pid_t pid ) = 0;  
  10.     virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;  
  11.     virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;  
  12.     virtual sp<IOMX>            getOMX() = 0;  
  13.   
  14.     // codecs and audio devices usage tracking for the battery app  
  15.     enum BatteryDataBits {  
  16.         // tracking audio codec  
  17.         kBatteryDataTrackAudio          = 0x1,  
  18.         // tracking video codec  
  19.         kBatteryDataTrackVideo          = 0x2,  
  20.         // codec is started, otherwise codec is paused  
  21.         kBatteryDataCodecStarted        = 0x4,  
  22.         // tracking decoder (for media player),  
  23.         // otherwise tracking encoder (for media recorder)  
  24.         kBatteryDataTrackDecoder        = 0x8,  
  25.         // start to play an audio on an audio device  
  26.         kBatteryDataAudioFlingerStart   = 0x10,  
  27.         // stop/pause the audio playback  
  28.         kBatteryDataAudioFlingerStop    = 0x20,  
  29.         // audio is rounted to speaker  
  30.         kBatteryDataSpeakerOn           = 0x40,  
  31.         // audio is rounted to devices other than speaker  
  32.         kBatteryDataOtherAudioDeviceOn  = 0x80,  
  33.     };  
  34.     virtual void setHiplayerVol(int stream,float vol)=0;  
  35.     virtual void addBatteryData(uint32_t params) = 0;  
  36.     virtual status_t pullBatteryData(Parcel* reply) = 0;  
  37. };  
看,首先一个接口必须继承至IIterface,IInterface提供一些与binder通信有关的操作。

如果定义的服务名是xxx,那么它的接口一定要命名为Ixxx,Bn服务端一定要定义为Bnxxx,Bp客户端一定要定义为Bpxxx

在这个接口类的前部有一句话DECLARE_META_INTERFACE(MediaPlayerService);这个是一个宏定义,MediaPlayerService就是服务名xxx。

DECLARE_META_INTERFACE的定义如下:

[cpp]  view plain copy
  1. #define DECLARE_META_INTERFACE(INTERFACE)                               \  
  2.     static const android::String16 descriptor;                          \  
  3.     static android::sp<I##INTERFACE> asInterface(                       \  
  4.             const android::sp<android::IBinder>& obj);                  \  
  5.     virtual const android::String16& getInterfaceDescriptor() const;    \  
  6.     I##INTERFACE();                                                     \  
  7.     virtual ~I##INTERFACE();                                            \  
主要提供几个有关binder通信的属性和方法声明。

与它对于是的IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");

IMPLEMENT_META_INTERFACE这个宏的定义为:

[cpp]  view plain copy
  1. #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \  
  2.     const android::String16 I##INTERFACE::descriptor(NAME);             \  
  3.     const android::String16&                                            \  
  4.             I##INTERFACE::getInterfaceDescriptor() const {              \  
  5.         return I##INTERFACE::descriptor;                                \  
  6.     }                                                                   \  
  7.     android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \  
  8.             const android::sp<android::IBinder>& obj)                   \  
  9.     {                                                                   \  
  10.         android::sp<I##INTERFACE> intr;                                 \  
  11.         if (obj != NULL) {                                              \  
  12.             intr = static_cast<I##INTERFACE*>(                          \  
  13.                 obj->queryLocalInterface(                               \  
  14.                         I##INTERFACE::descriptor).get());               \  
  15.             if (intr == NULL) {                                         \  
  16.                 intr = new Bp##INTERFACE(obj);                          \  
  17.             }                                                           \  
  18.         }                                                               \  
  19.         return intr;                                                    \  
  20.     }                                                                   \  
  21.     I##INTERFACE::I##INTERFACE() { }                                    \  
  22.     I##INTERFACE::~I##INTERFACE() { }                                   \  

可以看出主要提供了descriptor属性,以及asInterface方法,getInterfaceDescriptor方法。

asInterface方法主要是用来获得服务的客户端Bpxxx的。它的输入参数是一个实现IBinder接口的对象,其他就是包


未完待续。。。。。。。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值