Android(4.4)音频系统之MediaPlayerService服务

  • Post author:
  • Post category:其他

代码目录:frameworks/av/media/libmediaplayerservice

目录中代码是MediaPlayer 服务器端代码,实现了媒体播放,获取元数据,录像录音。

在mediaserver的main_mediaserver.cpp文件中添加了MediaPlayerService服务:

AudioPlayerService::instantiate();

MediaplayerService是一个系统服务,Android 视频播放,录音录像,元数据获取等客户端应用与MediaplayerService交互,由MediaPlayerService实现视频的播放,录像,元数据获取等操作。

MediaPlayerService服务主要实现在MediaPlayerService.cpp中,是服务器端媒体操作的主接口,MediaPlayerService根据客户端请求的操作类型不同,创建不同的client代理,跟Client应用交互。

StagefrightPlayer.cpp是Android内置播放器,真正的播放器AwesomePlayer在framework/av/media/libstagefright/下。

MidiFile.cpp 是Android内置的midi文件类型的播放器

Android把MediaPlayerService获取媒体文件元数据的代码移到MetadataRetrieverClient.cpp和MidiMetadataRetriever.cpp中(Midi文件的元数据获取和普通媒体文件方式有所区别,所以单独提出了MidiMetadataRetriever.cpp)

Android把Recorder相关的代码提取出来放入了MediaRecorderClient.cpp中,这个类实际只起到了中转作用,具体的recorder有Android内置的StagefrightRecorder。

MediaplayerService工作流程相当简单

设置阶段

  • client应用发起申请,MediaPlayerService创建对应的client代理
  • client调用setDataSource接口,MediaPlayerService根据文件内容后缀名或者url类型,选择相应的播放器

操作阶段


  • client发送play命令,MediaPlayerService端调用相应播放器的播放命令

  • client发送metadata操作命令,MediaPlayerService端的 MetadataRetrieverClient调用不同的metadata获取插件来获取metadata
  • client发送recorder命令,MediaPlayerService端的MediaRecorderClient调用不同的recorder插件录音录像。

Midi格式介绍

Midi是一类比较特殊的媒体文件,普通的声音文件(*.wav文件)是计算机直接把声音信号的模拟信号经过取样——量化处理,变成与声音波形对应的数字信号,存储在文件中,而mid文件只是记录了演奏乐器的各种信息和指令,如用哪一种乐器,什么时候按某个键,力度怎么样等等,至于播放时发出的声音,那是通过播放软件或者音源的转换而成的。

Metadata

我的理解是除去媒体内容外,描述媒体文件的数据,包括类型,大小,日期,Author,duration,width,height,甚至thumbnail等都可算做元数据

MediaPlayerService.cpp中一些函数介绍:

  1. 251 MediaPlayerService::MediaPlayerService()  
  2. 252 {  
  3. 253     LOGV(“MediaPlayerService created”);  
  4. 254     mNextConnId = 1;  
  5. 255 }  

MediaPlayerService的构造函数

mNextConnId记录着client可用的connect id, 每创建一个client,mNextConnId都递增1,已经用过的connect id不能复用

  1. sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pid)  
  2. {  
  3.     sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);  
  4.     LOGV(“Create new media retriever from pid %d”, pid);  
  5.     return retriever;  
  6. }  

创建一个Metadata retriever client,从类的名字我们可以猜测出这个函数是获取media文件的metadata。查看MetadataRetrieverClient的定义文件libmediaplayerservice/MetadataRetrieverClient.cpp,可以看到这个类提供了如下几种方法

  • getFrameAtTime 获取video文件参数指定时间的帧内容,可用来获取media文件的thumbnail
  • extractAlbumArt 获取media文件的AlbumArt, AlbumArt是media文件的预览封面,一般来说,如果不能抽取到这个,就用getFrameAtTime获取第一帧来代替
  • extractMetadata:获取media文件的元数据:Album, Artist, Author, Date, Genre, VIDEO_FORMAT, VIDEO_HEIGHT等等
  1. 286 sp<IMediaPlayer> MediaPlayerService::create(  
  2.  287         pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,  
  3.  288         const KeyedVector<String8, String8> *headers, int audioSessionId)  
  4.  289 {  
  5.  290     int32_t connId = android_atomic_inc(&mNextConnId);  
  6.  291     sp<Client> c = new Client(this, pid, connId, client, audioSessionId);  
  7.  292     LOGV(“Create new client(%d) from pid %d, url=%s, connId=%d, audioSessionId=%d”,  
  8.  293             connId, pid, url, connId, audioSessionId);  
  9.  294     if (NO_ERROR != c->setDataSource(url, headers))  
  10.  295     {  
  11.  296         c.clear();  
  12.  297         return c;  
  13.  298     }  
  14.  299     wp<Client> w = c;  
  15.  300     Mutex::Autolock lock(mLock);  
  16.  301     mClients.add(w);  
  17.  302     return c;  
  18.  303 }

为MediaPlayer Client创建一个对应的实体

@pid: client所在进程的id

@client: MediaPlayer client

@url: media 文件url

@headers: 未知

@audioSessionId:

301 mClients,是一个client对象数组,每一个新建的client都增加到这里面

……等等函数


版权声明:本文为chenjiaban原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。