一、引入:
MediaCodec这条通路的调用逻辑是MediaCode->ACodec->OMX
,因为OMX有自己的状态机,所以MediaCodec和ACodec也分别基于OMX组件的调用维护了其状态机,这篇博客就先分析MediaCodec的状态机是如何运转的。
二、MediaCodec与ACodec的联动:
1.MediaCodec的继承关系:
struct MediaCodec : public AHandler {
...
}
MediaCodec实际上是一个AHandler ,用于维护native层的消息机制。
2.ACodec的继承关系:
struct ACodec : public AHierarchicalStateMachine, public CodecBase {
...
}
ACodec继承自CodecBase ,而CodecBase 中含有一个内联函数:
inline void setCallback(std::unique_ptr<CodecCallback> &&callback) {
mCallback = std::move(callback);
}
这表明,在实例化ACodec的时候,是可以设置一个回调函数下来的。
3.MediaCodec与ACodec的关联:
看一下MediaCodec创建ACodec的场景:
status_t MediaCodec::init(const AString &name) {
...
/* 1.实例化Acodec */
mCodec = GetCodecBase(name);
if (mCodec == NULL) {
return NAME_NOT_FOUND;
}
...
/* 2.设置ACodec的回调 */
mCodec->setCallback(
std::unique_ptr<CodecBase::CodecCallback>(
new CodecCallback(new AMessage(kWhatCodecNotify, this))));
/* 3.创建buffer channel,为fillbuffer和emptybuffer做准备 */
mBufferChannel = mCodec->getBufferChannel();
mBufferChannel->setCallback(
std::unique_ptr<CodecBase::BufferCallback>(
new BufferCallback(new AMessage(kWhatCodecNotify, this))));
...
}
在MediaCodec的init函数中,首先会去创建ACodec,然后创建CodecCallback对象,这个对象专门用于处理ACodec中回调回来的各种消息,然后根据不同的消息去设置MediaCodec的状态机。
三、MediaCodec的各状态机:
MediaCodec有如下状态机:
enum State {
UNINITIALIZED,
INITIALIZING,
INITIALIZED,
CONFIGURING,
CONFIGURED,
STARTING,
STARTED,
FLUSHING,
FLUSHED,
STOPPING,
RELEASING,
};
1.UNINITIALIZED:
在构造MediaCodec对象的时候,会设置当前状态为UNINITIALIZED:
MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid)
: mState(UNINITIALIZED),
mReleasedByResourceManager(false),
mLooper(looper),
mCodec(NULL),
...
{
...
}
当然,如果在其他的状态机中(INITIALIZING
/STOPPING
/FLUSHING
),ACodec回调了kWhatError
消息时,也会将MediaCodec设置为UNINITIALIZED
。
2.INITIALIZING:
MediaCodec的init函数中,会发送kWhatInit消息,而消息的处理阶段,将会设置此状态机:
case kWhatInit:
{
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
if (mState != UNINITIALIZED) {
PostReplyWithError(replyID, INVALID_OPERATION);
break;
}
mReplyID = replyID