安利一个音视频博主,他的博文写的很详细。本博文只是简单介绍大致的播放流程。
音视频播放流程:
大致流程就这,建议先熟悉这个流程图再结合代码看,代码是实现的那一部分的功能。
service list | grep media
重点关注下
media.extractor 分离音视频
media.player media播放
media.audio_flinger 音频执行
media.audio_policy 音频策略
ps -ef | grep media
只需要先了解有如下四个进程就ok:
media.extractor(分离)
mediaserver(media服务,总管media)
mediacodec(分软件解码和硬件解码)
软件解码 media.swcodec oid.media.swcodec/bin/mediaswcodec
硬件解码 media.codec hw/[email protected]
在main_mediaserver.cpp中会创建"media_player"服务。
主要就是创建MediaPlayerService,然后添加到ServiceManager中。
再往下追一点点,追到NuPlayer就行。
//Main_mediaserver.cpp (frameworks\av\media\mediaserver)
int main(int argc __unused, char **argv __unused)
{
//创建service管理器
sp<IServiceManager> sm(defaultServiceManager());
//初始化mediaplayer服务
MediaPlayerService::instantiate();
}
//MediaPlayerService.cpp (frameworks\av\media\libmediaplayerservice)
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
MediaPlayerService::MediaPlayerService()
{
ALOGV("MediaPlayerService created");
mNextConnId = 1;
//创建
MediaPlayerFactory::registerBuiltinFactories();
}
void MediaPlayerFactory::registerBuiltinFactories() {
Mutex::Autolock lock_(&sLock);
if (sInitComplete)
return;
//创建NuPlayerFactory实例
IFactory* factory = new NuPlayerFactory();
if (registerFactory_l(factory, NU_PLAYER) != OK)
delete factory;
//创建TestPlayer实例
factory = new TestPlayerFactory();
if (registerFactory_l(factory, TEST_PLAYER) != OK)
delete factory;
sInitComplete = true;
}
enum player_type {
STAGEFRIGHT_PLAYER = 3,
NU_PLAYER = 4,
// Test players are available only in the 'test' and 'eng' builds.
// The shared library with the test player is passed passed as an
// argument to the 'test:' url in the setDataSource call.
TEST_PLAYER = 5,
};
需要注意的是,mediaplayer的实例创建了两个,分别是NuPlayer和TestPlayer,实际使用中使用的是NuPlayer,TestPlayer有兴趣的可以看看,代码比较少。
至此,我们简单了解了mediaplay服务的创建以及mediaplayer的实例是nuplayer。
顺便了解一下音频的server创建。
AudioPolicyService是策略的制定者,比如什么时候打开音频接口设备、某种Stream类型的音频对应什么设备等等。而AudioFlinger则是策略的执行者,例如具体如何与音频设备通信,如何维护现有系统中的音频设备,以及多个音频流的混音如何处理等等都得由它来完成。AudioPolicyService根据用户配置来指导AudioFlinger加载设备接口,起到路由功能。
来源文章:深入剖析Android音频之AudioPolicyService
//Main_audioserver.cpp (frameworks\av\media\audioserver)
int main(int argc __unused, char **argv)
{
sp<IServiceManager> sm = defaultServiceManager();
//创建执行
AudioFlinger::instantiate();
//创建策略制定
AudioPolicyService::instantiate();
//创建语音识别服务
SoundTriggerHwService::instantiate();
}
}
视频的显示依赖surface
视频数据渲染之后就是通过这个类进行送显的,先了解一下。
//Main_surfaceflinger.cpp (frameworks\native\services\surfaceflinger)
int main(int, char**) {
//绘图Graphics服务启动
startGraphicsAllocatorService();
//创建SurfaceFlinger
sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
//添加SurfaceFlinger到ServiceManager
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);
//启动显示服务
startDisplayService(); // dependency on SF getting registered above
}
图片来源:Android MultiMedia框架完全解析 - 概览
上图的框架图特别好,service的关系也理清了。
在nuplayer的实现中会访问到音频和视频的server去实现播放。
在安卓官网上查看下mediaplayer的介绍。
MediaPlayer 类是媒体框架最重要的组成部分之一。此类的对象能够获取、解码以及播放音频和视频,而且只需极少量设置。它支持多种不同的媒体源,例如:
看下java层的播放流程。
Uri myUri = ....; // initialize Uri here
// 1. 创建mediaplayer
MediaPlayer mediaPlayer = new MediaPlayer();
// 2. 获取音频播放流的类型stream_type(默认是music)
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
// 3. 获取播放文件资源source
mediaPlayer.setDataSource(getApplicationContext(), myUri);
// 4. 播放准备
mediaPlayer.prepare();
// 5. 播放开始
mediaPlayer.start();
主要的播放流程就是这样,结合文章最开始的图片查看,其中准备阶段内包含了分离音视频数据,播放开始阶段才进行解码、渲染、输出。
图片来源:Android MultiMedia框架完全解析 - 概览
建议看下这个博主的文章,写的都特别赞。
首先java层向下调用,中间有个jni,是用于java和cpp交互的,也就是android_media_MediaPlayer.cpp
文件路径:android\frameworks\base\media\jni
java层
//android\frameworks\base\media\java\android\media\MediaPlayer.java
//java层会调用startImpl函数用于播放
private void startImpl() {
baseStart();
stayAwake(true);
_start();
}
//定义了_start函数是调用到native层
private native void _start() throws IllegalStateException;
jni层
//android_media_MediaPlayer.cpp (frameworks\base\media\jni)
//定义了_start的native层对应的是android_media_MediaPlayer_start
static const JNINativeMethod gMethods[] = {
{"_start", "()V", (void *)android_media_MediaPlayer_start},
}
//jni层函数定义
android_media_MediaPlayer_start(JNIEnv *env, jobject thiz)
{
ALOGV("start");
//获取mediaplayer
sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
//调用mediaplayer的start函数
process_media_player_call( env, thiz, mp->start(), NULL, NULL );
}
native层(cpp文件)
//Mediaplayer.cpp (frameworks\av\media\libmedia)
status_t MediaPlayer::start()
{
ALOGV("start");
//省略许多代码
//调用mediaplayer的实例的start函数
ret = mPlayer->start();
}
//Mediaplayer.h (frameworks\av\media\libmedia)
//mPlayer类型为IMediaPlayer,有代理
sp<IMediaPlayer> mPlayer;
//MediaPlayerService.cpp (frameworks\av\media\libmediaplayerservice)
//这里只是获取基础类MediaPlayerBase,然后调用定义的start函数
status_t MediaPlayerService::Client::start()
{
ALOGV("[%d] start", mConnId);
sp<MediaPlayerBase> p = getPlayer();
return p->start();
}
//MediaPlayerInterface.h (frameworks\av\include\media)
定义一个虚函数
virtual status_t start() = 0;
实际上start函数在mediaplayer实例化的时候会被重载,也就是我们的nuplayer。
当然nuplayer只是一种实例,还有旧版的awesomeplayer等等,有兴趣可以了解一下。