一、问题引言:
初读mediacodec的代码,分析了stagefright框架中大量使用的AHandler、ALooper和AMessage组成的消息机制,我们知道每个AHandler都会通过ALooper去发送消息,然后,最终通过ALooper的loop函数将AMessage分发到各自的AHandler进行处理,但在Acodec中,明明仅ACodec是一个AHandler,为什么处理消息的时候确是由各个状态的onMessageReceived来响应的呢?针对这个问题,分析了一下源码,找到了答案。
先直接给出答案:
ACodec通过调用AHierarchicalStateMachine类维护的成员变量mstate来进行消息处理的。
二、代码分析:
- mediacodec创建的逻辑时序图如下(create->start):
mediacodec实例化的时候会去实例化Acode,在Acode的构造函数中,我们可以看到创建了很多的state:
ACodec::ACodec()
...
{
...
mUninitializedState = new UninitializedState(this);
mLoadedState = new LoadedState(this);
mLoadedToIdleState = new LoadedToIdleState(this);
mIdleToExecutingState = new IdleToExecutingState(this);
mExecutingState = new ExecutingState(this);
mOutputPortSettingsChangedState =
new OutputPortSettingsChangedState(this);
mExecutingToIdleState = new ExecutingToIdleState(this);
mIdleToLoadedState = new IdleToLoadedState(this);
mFlushingState = new FlushingState(this);
mPortEOS[kPortIndexInput] = mPortEOS[kPortIndexOutput] = false;
mInputEOSResult = OK;
/* 首先将Acodec的状态改变为mUninitializedState */
changeState(mUninitializedState);
}
这里注意一下每个state都是继承自ACodec中的类成员BaseState的,举例UninitializedState:
struct ACodec::UninitializedState : public ACodec::BaseState {
UninitializedState(ACodec *codec);
我们先拓展看一下BaseState的继承关系:
struct ACodec::BaseState : public AState {
BaseState(ACodec *codec, const sp<AState> &parentState = NULL);
struct AState : public RefBase {
AState(const sp<AState> &parentState = NULL);
最终都是继承自Android的基类RefBase ,这里我们可以确定,Acodec中的各个状态都不是AHandler,是不具备拥有自主消息机制收发的权利的,那么是谁赋予的每个状态拥有onMessageReceived的消息处理权利呢?另外,以UninitializedState 为例看下每个状态构造是怎么玩的:
ACodec::UninitializedState::UninitializedState(ACodec *codec)
: BaseState(codec) {
}
ACodec::BaseState::BaseState(ACodec *codec, const sp<AState> &parentState)
: AState(parentState),
mCodec(codec) {
}
这里初始化参数列表是通过基类构造实现的,所以mCodec就是我们的Acodec对象。
- 假定Acodec发送了一个AMessage,经过ALooper之后,会最终调用对应AHandler的onMessageReceived来处理,因为Acodec就是一个AHandler,那么我们直接去找Acodec的onMessageReceived:
ACodec.h
// AHierarchicalStateMachine implements the message handling
virtual void onMessageReceived(const sp<AMessage> &msg) {
handleMessage(msg);
}
因为ACodec继承自AHierarchicalStateMachine类,所以这里直接调用父类的handleMessage,来看一下这个函数做了什么:
AHierarchicalStateMachine.cpp
void AHierarchicalStateMachine::handleMessage(const sp<AMessage> &msg) {
/* 先保存当前状态 */
sp<AState> save = mState;
/* 调用当前状态的onMessageReceived去处理消息 */
sp<AState> cur = mState;
while (cur != NULL && !cur->onMessageReceived(msg)) {
/* 确认状态是否有改变 */
CHECK(save == mState);
/* 将当前状态置为“上一个”状态 */
cur = cur->parentState();
}
if (cur != NULL) {
return;
}
ALOGW("Warning message %s unhandled in root state.",
msg->debugString().c_str());
}
AHierarchicalStateMachine内部维护了一个成员变量叫mState,用来记录当前Acodec处于何种状态,当Acodec有消息要处理时,AHierarchicalStateMachine就会指派对应的状态去处理这个消息,注意,mediacodec中也维护了一个成员变量来mState来记录其所处的运行状态,只不过其类型为enum,不要弄混了,所以,在mediacodec和Acodec中,状态是非常重要的。