Android MultiMedia框架——ALooper AHandler AMessage
Posted VNanyesheshou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android MultiMedia框架——ALooper AHandler AMessage相关的知识,希望对你有一定的参考价值。
Android MultiMedia框架——OMX服务启动
Android MultiMedia框架——OMXPlugin
Android MultiMedia框架——MediaCodec编码(上)
Android MultiMedia框架——MediaCodec编码(下)
Android MultiMedia框架——ACodec加载OMX
Android MultiMedia框架——ALooper AHandler AMessage
基于Android 9.0源码分析
在分析meidacodec framework层代码有看到ALooper、AHandler、AMessage这几个类,这主要分析下其内部原理
代码路径:frameworks/av/media/libstagefright/foundation/
ALooper
首先看下ALooper使用示例
mLooper = new ALooper;
mLooper->setName("MediaCodec_looper");
mLooper->start(
false, // runOnCallingThread
true, // canCallJava
android_PRIORITY_VIDEO);
1 初始化
ALooper::ALooper()
: mRunningLocally(false)
// clean up stale AHandlers. Doing it here instead of in the destructor avoids
// the side effect of objects being deleted from the unregister function recursively.
gLooperRoster.unregisterStaleHandlers();
- mRunningLocally用来区分ALooper执行线程是否在调用线程,start函数会进行复制;
- 清理过时的AHandler;
2 start
status_t ALooper::start(
bool runOnCallingThread, bool canCallJava, int32_t priority)
if (runOnCallingThread)
Mutex::Autolock autoLock(mLock);
if (mThread != NULL || mRunningLocally)
return INVALID_OPERATION;
mRunningLocally = true;
do
while (loop());
return OK;
Mutex::Autolock autoLock(mLock);
if (mThread != NULL || mRunningLocally)
return INVALID_OPERATION;
mThread = new LooperThread(this, canCallJava);
status_t err = mThread->run(
mName.empty() ? "ALooper" : mName.c_str(), priority);
if (err != OK)
mThread.clear();
return err;
-
runOnCallingThread参数用来区分ALooper执行时在调用者线程还是新创建线程;
runOnCallingThread为ture,则在调用者线程进行loop循环;
-
runOnCallingThread为false,创建LooperThread,并调用其run方法;
接着看下LooperThread
struct ALooper::LooperThread : public Thread
LooperThread(ALooper *looper, bool canCallJava)
: Thread(canCallJava),
mLooper(looper),
mThreadId(NULL)
virtual bool threadLoop()
return mLooper->loop();
//.........
- LooperThread继承于Thread类,其run函数会调用到threadLoop函数中;
- threadLoop会调用ALooper的loop函数,进行消息的分发;
3 loop
先看下ALooper类的一些变量
private:
friend struct AMessage; // post()
//封装消息 结构体
struct Event
int64_t mWhenUs;
sp<AMessage> mMessage;
;
Mutex mLock; //锁
Condition mQueueChangedCondition;
AString mName;
//event队列
List<Event> mEventQueue;
struct LooperThread;
sp<LooperThread> mThread; //新建的运行线程
bool mRunningLocally; //是否在调用者线程运行
Event结构体封装了AMessage及对应的时间,mEventQueue则对应接收到的消息队列。
bool ALooper::loop()
Event event;
Mutex::Autolock autoLock(mLock);
if (mThread == NULL && !mRunningLocally)
return false;
if (mEventQueue.empty())
mQueueChangedCondition.wait(mLock);
return true;
int64_t whenUs = (*mEventQueue.begin()).mWhenUs;
int64_t nowUs = GetNowUs();
if (whenUs > nowUs)
int64_t delayUs = whenUs - nowUs;
mQueueChangedCondition.waitRelative(mLock, delayUs * 1000ll);
return true;
event = *mEventQueue.begin();
mEventQueue.erase(mEventQueue.begin());
event.mMessage->deliver();
// NOTE: It's important to note that at this point our "ALooper" object
// may no longer exist (its final reference may have gone away while
// delivering the message). We have made sure, however, that loop()
// won't be called again.
return true;
- mEventQueue如果内部空,没有元素则进行阻塞等待;
- mEventQueue不为空,则获取第一个元素的时间,如果时间大于当前时间则表示没有到时间,则阻塞指定时间并返回;
- 如果whenUs不大于当前时间,则表示应该执行第一个任务了;
- 取出第一个event,并从mEventQueue中擦除,执行message deliver函数,稍后分析deliver;
ALooper loop函数负责从mEventQueue获取事件,并进行分发;
AMessage
先看使用示例
sp<AMessage> msg = new AMessage(kWhatInit, this);
msg->setMessage("on-frame-rendered", notify);
msg->post()
接着看下AMessage内部实现
AMessage::AMessage(uint32_t what, const sp<const AHandler> &handler)
: mWhat(what),
mNumItems(0)
setTarget(handler);
void AMessage::setTarget(const sp<const AHandler> &handler)
if (handler == NULL)
mTarget = 0;
mHandler.clear();
mLooper.clear();
else
mTarget = handler->id();
mHandler = handler->getHandler();
mLooper = handler->getLooper();
初始化AMessage,设置其what值,并且和handler、Looper绑定关系。
status_t AMessage::post(int64_t delayUs)
sp<ALooper> looper = mLooper.promote();
if (looper == NULL)
ALOGW("failed to post message as target looper for handler %d is gone.", mTarget);
return -ENOENT;
looper->post(this, delayUs);
return OK;
post获取ALooper指针,调用其post函数,将AMessage封装成Event,添加到mEventQueue队列中。
看下Amessage deliver函数,
void AMessage::deliver()
sp<AHandler> handler = mHandler.promote();
if (handler == NULL)
ALOGW("failed to deliver message as target handler %d is gone.", mTarget);
return;
handler->deliverMessage(this);
deliver中获取AHandler指针,并将消息分发给AHandler处理;
AHandler
void AHandler::deliverMessage(const sp<AMessage> &msg)
onMessageReceived(msg);
mMessageCounter++;
if (mVerboseStats)
uint32_t what = msg->what();
ssize_t idx = mMessages.indexOfKey(what);
if (idx < 0)
mMessages.add(what, 1);
else
mMessages.editValueAt(idx)++;
AHandler接收到消息,调用onMessageReceived函数进行处理,类似java 中handleMessage。
C++层和java层区别(AHandler 和Handler区别)
- 都实现了线程间通信机制
- ALooper在start时,确定其执行线程是在调用者线程,还是新建线程,而Looper则在初始化(prepare)时确定其执行线程为本线程;
- C++层发送消息可以等待获取回应,java层不能阻塞获取回应。
以上是关于Android MultiMedia框架——ALooper AHandler AMessage的主要内容,如果未能解决你的问题,请参考以下文章
Android MultiMedia框架——OMXPlugin
Android MultiMedia框架——ACodec加载OMX
Android MultiMedia框架——ALooper AHandler AMessage
Android MultiMedia框架——MediaCodec编码(下)