android AV 之 SimpleC2Component

一、总体架构

以 aac 解码 process 为例
App (MediaCodec) -> Framework (CCodec) -> Binder (HIDL/AIDL) -> mediaswcodec 进程 -> SimpleC2Component (基类循环) -> C2SoftAacDec::process

Android 调用到 libcodec2_soft_aacdec.so 里的 process 的关键步骤是:

  1. 加载库 :系统启动 mediaswcodec 服务进程,根据配置加载 libcodec2_soft_aacdec.so 并创建 C2SoftAacDec 对象。
  2. 基类驱动 :该对象启动时会创建一个后台线程(由基类 SimpleC2Component 管理)。
  3. 循环处理 :后台线程运行 processQueue() 循环,等待输入数据。
  4. 虚函数调用 :一旦收到数据,基类直接调用 process() 虚函数。
  5. 具体执行 :执行流进入 C2SoftAacDec::process,完成 AAC 解码。

二、函数分析

1. SimpleC2Component::processQueue

1.1 函数功能
  1. 队列管理:从工作队列中取出任务,处理flush和排空操作
  2. 资源初始化:首次使用时初始化输出块池
  3. 配置更新:处理工作项中的配置参数更新
  4. 任务处理:调用具体的process函数处理音视频数据
  5. 结果返回:根据处理状态立即返回结果或将工作放入挂起队列
  6. 错误处理:处理各种异常情况并通知监听器
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,
                    &params);
            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> &param: 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;
}
相关推荐
消失的旧时光-194330 分钟前
Android 接入 Flutter(Add-to-App)最小闭环:10 分钟跑起第一个混合页面
android·flutter
城东米粉儿44 分钟前
android StrictMode 笔记
android
Zender Han1 小时前
Flutter Android 启动页 & App 图标替换(不使用任何插件的完整实践)
android·flutter·ios
童无极1 小时前
Android 弹幕君APP开发实战01
android
赛恩斯1 小时前
kotlin 为什么可以在没有kotlin 环境的安卓系统上运行的
android·开发语言·kotlin
于山巅相见1 小时前
【3588】Android动态隐藏导航栏
android·导航栏·状态栏·android11
乡野码圣1 小时前
【RK3588 Android12】开发效率提升技巧
android·嵌入式硬件
eybk2 小时前
Beeware生成安卓apk取得系统tts语音朗读例子
android
zhangphil3 小时前
Android图像显示,CPU的Skia与GPU的Vulkan高性能渲染系统
android