原创文章,转载请注明出处: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 proc(ProcessState::self());/*得到默认的服务管理器,就是大管家哦,用来添加和查询服务的。*/        sp 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  createMediaRecorder(pid_t pid);    void    removeMediaRecorderClient(wp client);    virtual sp createMetadataRetriever(pid_t pid);    virtual sp    create(pid_t pid, const sp& client, int audioSessionId);    virtual sp   createMediaConfig(pid_t pid);    virtual sp         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);    virtual sp         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);    virtual sp            getOMX();    virtual status_t            dump(int fd, const Vector& args);            void                removeClient(wp 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 createMediaRecorder(pid_t pid) = 0;    virtual sp createMetadataRetriever(pid_t pid) = 0;    virtual sp create(pid_t pid, const sp& client, int audioSessionId = 0) = 0;    virtual sp    createMediaConfig(pid_t pid ) = 0;    virtual sp         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;    virtual sp         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;    virtual sp            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;};
看,首先一个接口必须继承至IIterface,IInterface提供一些与binder通信有关的操作。

如果定义的服务名是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 asInterface(                       \            const android::sp& obj);                  \    virtual const android::String16& getInterfaceDescriptor() const;    \    I##INTERFACE();                                                     \    virtual ~I##INTERFACE();                                            \
主要提供几个有关binder通信的属性和方法声明。

与它对于是的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::asInterface(                \            const android::sp& obj)                   \    {                                                                   \        android::sp intr;                                 \        if (obj != NULL) {                                              \            intr = static_cast(                          \                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接口的对象,其他就是包


未完待续。。。。。。。

   
   
   
   
   
   
   


更多相关文章

  1. android Android签名证书的sha1值报错 :不是内部或外部命令,也不是
  2. android 一键锁屏 开发
  3. Android(安卓)Messenger 进程间通信
  4. Android(安卓)make脚本简记
  5. android 程序发布
  6. 自定义Android组件之带图像的TextView
  7. 自定义一个自己的Log
  8. [Android(安卓)Training视频系列]1.2 Running Your App
  9. Android(安卓)中级教程之------Android(安卓)MediaPlayer播放mp3

随机推荐

  1. JSP访问类实例
  2. eclipse写javaweb工程时文件目录为WebCon
  3. 启动非java虚拟机方式下运行matlab
  4. 转贴:JavaScript实现Ajax请求简单示例
  5. java之finally的用法
  6. 域对象/服务和业务逻辑层
  7. java常量的定义
  8. JAVA-全局变量与局部变量-继承-封装-(是三
  9. python 日志简单使用
  10. 关于反序列化时抛出java.io.EOFException