代码目录: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中一些函数介绍:
- 251 MediaPlayerService::MediaPlayerService()
- 252 {
- 253 LOGV(“MediaPlayerService created”);
- 254 mNextConnId = 1;
- 255 }
MediaPlayerService的构造函数
mNextConnId记录着client可用的connect id, 每创建一个client,mNextConnId都递增1,已经用过的connect id不能复用
- sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pid)
- {
- sp<MetadataRetrieverClient> retriever = new MetadataRetrieverClient(pid);
- LOGV(“Create new media retriever from pid %d”, pid);
- return retriever;
- }
创建一个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等等
- 286 sp<IMediaPlayer> MediaPlayerService::create(
- 287 pid_t pid, const sp<IMediaPlayerClient>& client, const char* url,
- 288 const KeyedVector<String8, String8> *headers, int audioSessionId)
- 289 {
- 290 int32_t connId = android_atomic_inc(&mNextConnId);
- 291 sp<Client> c = new Client(this, pid, connId, client, audioSessionId);
- 292 LOGV(“Create new client(%d) from pid %d, url=%s, connId=%d, audioSessionId=%d”,
- 293 connId, pid, url, connId, audioSessionId);
- 294 if (NO_ERROR != c->setDataSource(url, headers))
- 295 {
- 296 c.clear();
- 297 return c;
- 298 }
- 299 wp<Client> w = c;
- 300 Mutex::Autolock lock(mLock);
- 301 mClients.add(w);
- 302 return c;
- 303 }
为MediaPlayer Client创建一个对应的实体
@pid: client所在进程的id
@client: MediaPlayer client
@url: media 文件url
@headers: 未知
@audioSessionId:
301 mClients,是一个client对象数组,每一个新建的client都增加到这里面
……等等函数