版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_19923217/article/details/82979613
1. 引入 ALooper、AHandler、AMessage
在 android multimedia stagefright 的框架代码中,通篇都是这几个类的身影,所以熟悉 android 多媒体框架的第一步必须理解这几个类的含义。
这几个类是为了实现异步消息机制而设计的,这里有两个概念 “异步” & “消息机制”,下面详细说明一下。
同步和异步概念区别比较简单,可以举个例子说明:
- 同步:肚子饿了去饭店,点好菜后坐着等服务员上菜,什么时候菜做好了,你才能结束等菜。
- 异步:掏出手机,打开外卖软件,下单,这个时候你就可以去做别的事情,而不是干等着,等到时候饭店做好菜了,小哥自然送上门。
可以看出,异步处理更加灵活自由,对于需要兼顾编码、解码、显示、音频输出等功能的多媒体框架,无疑需要异步处理,来降低 cpu 的使用率。
我们知道,想要我们的程序执行一些事情要么同步要么异步,而消息机制是异步的一种实现方式。消息机制完美的解决了多线程间的同步问题,使程序设计更加便捷明了。下面的章节简单说明一下原理。
2. 消息机制原理概述
首先三个类的职责可以从字面理解:
- AMessage:消息载体
- ALooper:消息循环分发
- AHandler:消息处理
消息机制原理流程如下图:
首先由 创建一个消息队列,这个消息队列在一个单独的线程中轮询,由其他线程产生的消息 会被投递到消息队列中, 持续不断的轮询消息队列,从消息队列中取出 ,并分发给对应的 进行消息处理。
这里有几点需要注意:
- 一个 ALooper 消息队列中可以有多个 AHandler 注册其中,但是一个 AHandler 不能注册在多个 ALooper 下
- ALooper 启动后(线程启动),会不断轮询,有AMessage 就抛给指定的 AHandler 处理。并且在发现自己的消息队列中没有任何消息时,会等待,不会一直跑,从而降低 CPU 的占用率
这样,三个类各司其职、紧密合作,维持消息框架处理机制的正常运转。
附源码中消息机制相关代码:
1. NuPlayerDriver.cpp
NuPlayerDriver::NuPlayerDriver(pid_t pid)
...
{
mLooper = new ALooper();
mLooper->setName("NuPlayerDriver Looper");
// 开启线程,进行消息队列循环
mLooper->start(
false, /* runOnCallingThread */
true, /* canCallJava */
PRIORITY_AUDIO);
// NuPlayer 继承自 AHandler,用于进行消息处理
mPlayer = new NuPlayer(pid);
// 注册 AHandler
mLooper->registerHandler(mPlayer);
}
2. Nuplayer.cpp
// Nuplayer 是 AHandler 的实现类,用于消息处理
void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) {
// 创建一个消息,第二个参数指定处理的 AHandler
sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
// 投递到消息队列中去,后续由 ALooper 分发到对应的 AHandler 中处理
msg->post();
}
// AHandler 的 virtual 方法,消息在这个函数中进行处理
void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatSetDataSource:
{
// 消息处理
}
}
3. 源码详解
后续补上