一、总体架构
以 aac 解码 process 为例
App (MediaCodec) -> Framework (CCodec) -> Binder (HIDL/AIDL) -> mediaswcodec 进程 -> SimpleC2Component (基类循环) -> C2SoftAacDec::process
Android 调用到 libcodec2_soft_aacdec.so 里的 process 的关键步骤是:
- 加载库 :系统启动
mediaswcodec服务进程,根据配置加载libcodec2_soft_aacdec.so并创建C2SoftAacDec对象。 - 基类驱动 :该对象启动时会创建一个后台线程(由基类
SimpleC2Component管理)。 - 循环处理 :后台线程运行
processQueue()循环,等待输入数据。 - 虚函数调用 :一旦收到数据,基类直接调用
process()虚函数。 - 具体执行 :执行流进入
C2SoftAacDec::process,完成 AAC 解码。
二、函数分析
1. SimpleC2Component::processQueue
1.1 函数功能
- 队列管理:从工作队列中取出任务,处理flush和排空操作
- 资源初始化:首次使用时初始化输出块池
- 配置更新:处理工作项中的配置参数更新
- 任务处理:调用具体的process函数处理音视频数据
- 结果返回:根据处理状态立即返回结果或将工作放入挂起队列
- 错误处理:处理各种异常情况并通知监听器
1.2 函数注释
cpp
bool SimpleC2Component::processQueue() {
// 声明变量:工作项、代际、排空模式等
std::unique_ptr<C2Work> work;
uint64_t generation;
int32_t drainMode;
bool isFlushPending = false;
bool hasQueuedWork = false;
{
// 获取工作队列的锁
Mutexed<WorkQueue>::Locked queue(mWorkQueue);
// 检查队列是否为空
if (queue->empty()) {
return false; // 队列为空,返回false表示没有工作需要处理
}
// 获取当前队列的代际信息(用于检测flush操作)
generation = queue->generation();
// 获取排空模式
drainMode = queue->drainMode();
// 检查是否有待处理的flush操作
isFlushPending = queue->popPendingFlush();
// 从队列前端取出一个工作项
work = queue->pop_front();
// 检查队列是否还有剩余工作
hasQueuedWork = !queue->empty();
}
// 如果有待处理的flush操作,执行flush
if (isFlushPending) {
ALOGV("processing pending flush");
// 调用flush处理函数
c2_status_t err = onFlush_sm();
if (err != C2_OK) {
ALOGD("flush err: %d", err);
// TODO: 错误处理
}
}
// 如果输出块池尚未初始化,进行初始化
if (!mOutputBlockPool) {
c2_status_t err = [this] {
// 查询输出格式配置
C2StreamBufferTypeSetting::output outputFormat(0u);
std::vector<std::unique_ptr<C2Param>> params;
// 查询块池调优参数
c2_status_t err = intf()->query_vb(
{ &outputFormat },
{ C2PortBlockPoolsTuning::output::PARAM_TYPE },
C2_DONT_BLOCK,
¶ms);
if (err != C2_OK && err != C2_BAD_INDEX) {
ALOGD("query err = %d", err);
return err;
}
// 根据输出格式确定块池ID
C2BlockPool::local_id_t poolId =
outputFormat.value == C2BufferData::GRAPHIC
? C2BlockPool::BASIC_GRAPHIC
: C2BlockPool::BASIC_LINEAR;
// 如果有参数返回,使用配置的块池
if (params.size()) {
C2PortBlockPoolsTuning::output *outputPools =
C2PortBlockPoolsTuning::output::From(params[0].get());
if (outputPools && outputPools->flexCount() >= 1) {
poolId = outputPools->m.values[0];
}
}
// 获取块池实例
std::shared_ptr<C2BlockPool> blockPool;
err = GetCodec2BlockPool(poolId, shared_from_this(), &blockPool);
ALOGD("Using output block pool with poolID %llu => got %llu - %d",
(unsigned long long)poolId,
(unsigned long long)(
blockPool ? blockPool->getLocalId() : 111000111),
err);
if (err == C2_OK) {
// 创建阻塞式块池包装器
mOutputBlockPool = std::make_shared<BlockingBlockPool>(blockPool);
}
return err;
}();
// 如果块池初始化失败,发送错误通知
if (err != C2_OK) {
Mutexed<ExecState>::Locked state(mExecState);
std::shared_ptr<C2Component::Listener> listener = state->mListener;
state.unlock();
listener->onError_nb(shared_from_this(), err);
return hasQueuedWork;
}
}
// 如果work为空,表示是排空操作
if (!work) {
// 执行排空处理
c2_status_t err = drain(drainMode, mOutputBlockPool);
if (err != C2_OK) {
// 排空失败,发送错误通知
Mutexed<ExecState>::Locked state(mExecState);
std::shared_ptr<C2Component::Listener> listener = state->mListener;
state.unlock();
listener->onError_nb(shared_from_this(), err);
}
return hasQueuedWork;
}
{
// 处理配置更新
std::vector<C2Param *> updates;
// 收集所有配置更新参数
for (const std::unique_ptr<C2Param> ¶m: work->input.configUpdate) {
if (param) {
updates.emplace_back(param.get());
}
}
// 应用配置更新
if (!updates.empty()) {
std::vector<std::unique_ptr<C2SettingResult>> failures;
c2_status_t err = intf()->config_vb(updates, C2_MAY_BLOCK, &failures);
ALOGD("applied %zu configUpdates => %s (%d)", updates.size(), asString(err), err);
}
}
// 记录处理开始
ALOGV("start processing frame #%" PRIu64, work->input.ordinal.frameIndex.peeku());
// 处理空输入缓冲区的情况
if (!work->input.buffers.empty() && !work->input.buffers[0]) {
ALOGD("Encountered null input buffer. Clearing the input buffer");
work->input.buffers.clear();
}
// 核心处理:调用具体的处理函数
process(work, mOutputBlockPool);
ALOGV("processed frame #%" PRIu64, work->input.ordinal.frameIndex.peeku());
{
// 再次获取队列锁,检查代际是否变化
Mutexed<WorkQueue>::Locked queue(mWorkQueue);
if (queue->generation() != generation) {
ALOGD("work form old generation: was %" PRIu64 " now %" PRIu64,
queue->generation(), generation);
// 代际已变化,标记工作为未找到
work->result = C2_NOT_FOUND;
queue.unlock();
// 通知监听器工作完成
Mutexed<ExecState>::Locked state(mExecState);
std::shared_ptr<C2Component::Listener> listener = state->mListener;
state.unlock();
listener->onWorkDone_nb(shared_from_this(), vec(work));
return hasQueuedWork;
}
// 检查工作是否已处理完成
if (work->workletsProcessed != 0u) {
queue.unlock();
// 工作已处理完成,立即返回结果
Mutexed<ExecState>::Locked state(mExecState);
ALOGV("returning this work");
std::shared_ptr<C2Component::Listener> listener = state->mListener;
state.unlock();
listener->onWorkDone_nb(shared_from_this(), vec(work));
} else {
// 工作尚未处理完成,放入挂起队列
ALOGV("queue pending work");
work->input.buffers.clear();
std::unique_ptr<C2Work> unexpected;
// 获取帧索引
uint64_t frameIndex = work->input.ordinal.frameIndex.peeku();
// 检查是否已有相同帧索引的挂起工作
if (queue->pending().count(frameIndex) != 0) {
unexpected = std::move(queue->pending().at(frameIndex));
queue->pending().erase(frameIndex);
}
// 将当前工作放入挂起队列
(void)queue->pending().insert({ frameIndex, std::move(work) });
queue.unlock();
// 如果有意外的工作项,发送错误通知
if (unexpected) {
ALOGD("unexpected pending work");
unexpected->result = C2_CORRUPTED;
Mutexed<ExecState>::Locked state(mExecState);
std::shared_ptr<C2Component::Listener> listener = state->mListener;
state.unlock();
listener->onWorkDone_nb(shared_from_this(), vec(unexpected));
}
}
}
// 返回是否还有待处理的工作
return hasQueuedWork;
}