Android Media Framework(十三)ACodec - Ⅰ

从这一篇文章开始,我们就进入ACodec的学习了。ACodec作为IL Client的一部分,封装了OMX组件与OMXNodeInstance的调用细节,想要轻松学习ACodec需要熟悉OMX组件与OMXNodeInstance的工作原理。接下来的几篇文章,我们会在应用层面上(ACodec)对组件的配置、状态转换过程、Buffer分配过程以及销毁过程做深入剖析。在这一篇文章中,我们将深入学习ACodec的消息处理机制,虽然本章的篇幅比较短小,但是理解这一部分是后续学习的基础。

1、CodecBase

struct ACodec : public AHierarchicalStateMachine, public CodecBase {
}

struct CodecBase : public AHandler, ColorUtils {
}

ACodec继承于CodecBase,实现了CodecBase定义的编解码插件标准接口。CodecBase继承于AHandler,onMessageReceived方法由ACodec实现。ACodec内部采用ALooper-AHandler-AMessage异步消息处理机制来处理函数调用,将被处理的消息划分为三类:组件控制消息、buffer处理消息、组件Callback消息。

  • 组件控制消息:操作/控制组件状态的消息,这类消息由MediaCodec调用CodecBase定义的接口发出,这些方法都异步执行的:
virtual void initiateAllocateComponent(const sp<AMessage> &msg) = 0;
virtual void initiateConfigureComponent(const sp<AMessage> &msg) = 0;
virtual void initiateCreateInputSurface() = 0;
virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface) = 0;
virtual void initiateStart() = 0;
virtual void initiateShutdown(bool keepComponentAllocated = false) = 0;
virtual void signalFlush() = 0;
virtual void signalResume() = 0;
virtual void signalRequestIDRFrame() = 0;
virtual void signalSetParameters(const sp<AMessage> &msg) = 0;
virtual void signalEndOfInputStream() = 0;
  • buffer处理消息:上层处理input/output buffer发出的消息,这些消息是由MediaCodec调用ACodecBufferChannel的方法发出的:
virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) = 0;
virtual status_t queueSecureInputBuffer(...) = 0;
virtual status_t renderOutputBuffer(...) = 0;
virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) = 0;
  • 组件Callback消息:我们在之前的文章中学过了,包含Event Callback和Buffer Callback两类事件。ACodec会对接收到的组件Callback消息先做处理,然后再将部分消息再回传给上层。

Android Media框架设计中广泛采用了异步编程的思想,异步意味着我们不再需要轮询检查是否有buffer或event的到来,而是采用Callback机制来通知消息的到来。

使用异步消息机制可以将所有对ACodec的调用转换为AMessage消息,并将这些消息加入到ALooper队列中等待处理。由于整个系统仅依赖一个ALooper线程来处理队列中的消息,因此即便有多个线程并发地调用ACodec,也无需使用锁来同步访问,从而有效避免了锁竞争和死锁的风险。

当然,这套异步消息机制也是有缺点的,由于所有的消息都在一个线程中处理,如果有哪条消息处理过程耗时过长,就会导致整个流程出现异常,比如有播放卡顿的情况,这时候debug起来会比较麻烦。不过瑕不掩瑜,使用异步消息机制大大提升了代码的可读性。

2、AHierarchicalStateMachine

OMX组件有OMX_StateLoaded、OMX_StateIdle、OMX_StateExecuting三种状态,分别表示组件创建、组件准备完成、组件正在运行。算上状态切换的中间状态OMX_LoadedToIdle、OMX_IdleToExecuting、OMX_ExecutingToIdle、OMX_IdleToLoade,一共有七种状态。

ACodec的分层状态机一共有九种状态:

struct UninitializedState;
struct LoadedState;
struct LoadedToIdleState;
struct IdleToExecutingState;
struct ExecutingState;
struct OutputPortSettingsChangedState;
struct ExecutingToIdleState;
struct IdleToLoadedState;
struct FlushingState;

可能有一些读者会觉得疑惑,怎么ACodec和组件的状态还不一样了呢,它们应该如何对应起来呢?接下来对两者状态的对应关系进行梳理:

  • UninitializedState:ACodec增加的状态,用于标记组件还未分配或者已被销毁;

  • LoadedState:对应于OMX_StateLoaded,组件创建完成后ACodec直接进入该状态;

  • LoadedToIdleState:对应组件中间状态OMX_LoadedToIdle状态,上层调用initiateStart方法后,ACodec向组件下发命令,驱使组件进入OMX_StateIdle,之前的学习中我们知道,这个过程涉及到input/ouput buffer的分配于注册,这个中间状态使用LoadedToIdleState来记录;

关注公众号《青山渺渺》阅读全文
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青山渺渺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值