上一篇我们讲了多媒体的总体框架,本章我们先来讨论媒体文件的本地播放,也是手机的基本功能。现在市面上的手机配置越来越高,支持高清视频(1920x1080P)已不在话下。那现在android主流播放器都支持哪些媒体格式呢?一般来说mp3,mp4,m4a,m4v,amr等大众格式都是支持的,具体支持成什么样这得看手机厂商和芯片厂商了。具体格式大全可以看framework/base/media/java/android/media/MediaFile.java。
我们下面进入正题研究多媒体文件的本地播放(video playback),具体用到的工具有source insight,astah(免费的画流程图工具),android 4.1代码。代码如何获取可以到google source下下载:http://source.android.com/source/downloading.html。
一般上层应用要本地播放播放一个媒体文件,需要经过如下过程:
MediaPlayer mMediaPlayer = new MediaPlayer( );
mMediaPlayer.setDataSource(mContext, mUri);-
mMediaPlayer.setDisplay(mSurfaceHolder);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.prepareAsync();
mMediaPlayer.start();
首先我们先来分析setDataSource方法,这个方法有两个功能:一个是根据文件类型获得相应的player,一个是创建相应文件类型的mediaExtractor,解析媒体文件,记录metadata的主要信息。
代码如下:
framework/av/media/libmedia/ MediaPlayer.cpp
status_t MediaPlayer::setDataSource(
const char *url, const KeyedVector<String8, String8> *headers)
{
ALOGV("setDataSource(%s)", url);
status_t err = BAD_VALUE;
if (url != NULL) {
const sp<IMediaPlayerService>& service(getMediaPlayerService());
if (service != 0) {
sp<IMediaPlayer> player(service->create(getpid(), this, mAudioSessionId));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(url, headers))) {
player.clear();
}
err = attachNewPlayer(player);
}
}
return err;
}
我们先来看下setDataSource方法中如何获取player。大体的流程图如下图:
我们知道MediaplayerService是负责外部请求,针对每个APP player ,mediaplayerservice都会开辟一个client端来专门处理。
client 定义如下:
framework/av/media/libmediaplayerservice/ MediaPlayerService.h
class Client : public BnMediaPlayer {...
private:
friend class MediaPlayerService;
Client( const sp<MediaPlayerService>& service,
pid_t pid,
int32_t connId,
const sp<IMediaPlayerClient>& client,
int audioSessionId,
uid_t uid);
}
}
从代码看就是一个BnMediaplayer的子类(即local binder)。既然有了BnMediaplayer,客户端也应该有相应的BpMediaplayer。获取这个BpMediaplayer要分两步骤走:第一,获取BpMediaplayerService;第二就是在setDataSource方法中的:
<