系列文章的目的是什么?
粗略:
细化:

首先从MediaCodec 到具体的解码Component 梳理出一条路径,然后在具体理解里面的细节。 本文就从MediaCodec出发 理解Android 解码框架的各个层次, 总的来说可以分为三个部分

如图所示 上游主要包含了以下这些部分。
MediaCodec 首先会创建出ccodec,后续的操作都是通过ccodec 这个codecbase进行调用(这里是为了兼容ACodec 和 Codec2的情况)。同时也通过这个ccodec获取codec创建的CCodecBufferChannel。
codec2client:
和下游HIDL进行交互 的客户端, 主要是调用IComponetStore 和IComponet的接口。
std::shared_ptr client = _CreateFromIndex(index);
std::shared_ptr Codec2Client::_CreateFromIndex(size_t index) {
std::string const& name = GetServiceNames()[index];
LOG(WARNING) << "Creating a Codec2 client to service \"" << name << "\"";
sp baseStore = Base::getService(name);
CHECK(baseStore) << "Codec2 service \"" << name << "\""
" inaccessible for unknown reasons.";
LOG(WARNING) << "Client to Codec2 service \"" << name << "\" created";
return std::make_shared(baseStore, index);
}
Manifest定义了HAL的名字”android.hardware.media.c2”, hidl传输方式”hwbinder”,interface的名字”IComponentStore”,instance的名字”default”。而GetServiceNames也是通过这些信息去定位到具体的HAL。
Base::getService(name): 其中Base是IComponentStore类型,也就是service 端。通过名字获取到service端的服务。 然后赋值到baseStore。
接着用这个baseStore初始化创建codec2client(也就是mBase 是baseStore)。
std::make_shared
所以说codecclinet 调用的接口会调用到service 端的ComponentStore。
CCodecBufferChannel:管理输入和输出buffer的地方,当时有输入和输出buffer的时候通过回调上报到MediaCodec ,随后MediaCodec上报到应用
下游包括两个方面 一个是componentStore 另一个是Componet
componetStore
调用关系以createComponent 为例。调用流程如下
codec2client----->(HIDL)compometStore(获取真正的store)------>C2PlatformComponentStore(或者vendor自己实现的componetstore) -----> C2SoftAvcDecFactory .
在HIDL 上层 codec2clinet 获取componetStore服务的时候 会调用下面的函数返回C2PlatformComponentStore。而后调用createCompoent就调用到这个类当中。
在这个类的创建componet中会根据具体的名字找到componet调用其的createComponent,比如avc的C2SoftAvcDecFactory 的 createComponent
c2store.cpp
std::shared_ptr GetCodec2PlatformComponentStore() {
static std::mutex mutex;
static std::weak_ptr platformStore;
std::lock_guard lock(mutex);
std::shared_ptr store = platformStore.lock();
if (store == nullptr) {
store = std::make_shared();
platformStore = store;
}
return store;
}
c2_status_t C2PlatformComponentStore::createComponent(
C2String name, std::shared_ptr *const component) {
// This method SHALL return within 100ms.
component->reset();
std::shared_ptr module;
c2_status_t res = findComponent(name, &module);
if (res == C2_OK) {
// TODO: get a unique node ID
res = module->createComponent(0, component);
}
return res;
}
component
compont的调用 也是通过HIDL的接口调用到 SimpleC2Component ,然后 SimpleC2Component 调用具体的avc、hevc等等的componet。 SimpleC2Component 是每个compont的基类。
以queue接口为例 HIDL上层的codec2bufferChannel 会调用具体解码组件的queue接口 将待解码的数据包放入的具体的component中 首先调用到Codec2Client 这个调用componet的queue,然后调用到SimpleC2Component的queue_nb, queue_nb发送消息, 在消息处理线程中调用子类的process函数。
c2_status_t Codec2Client::Component::queue(
std::list>* const items) {
Return transStatus = mBase1_0->queue(workBundle);
}
// Methods from ::android::hardware::media::c2::V1_1::IComponent
Return Component::queue(const WorkBundle& workBundle) {
return static_cast(mComponent->queue_nb(&c2works));
}
c2_status_t SimpleC2Component::queue_nb(std::list> * const items) {
{
if (queueWasEmpty) {
(new AMessage(WorkHandler::kWhatProcess, mHandler))->post();
}
}
bool SimpleC2Component::processQueue() {
}
process(work, mOutputBlockPool);
}
IComponentStore
C2ComponentStore(这定义了各种接口, codec2client/C2PlatformComponentStore都继承他并实现里面的接口。)
有哪些接口 主要是
createComponent: 创建各种编解码器组件
createInterface:创建定义各种组件的配置
listComponents:列出所有的组件。
IComponent
主要定义了对组件的各种操作 实际可以分为数据流和控制流, 数据流包括配置编码输入surface,解码输出surface,输入解码包,清空编解码数据。控制流:启动组件、退出组件、释放组件等等操作
connectToInputSurface:使用surface启动组件
queue: 将work 放到组件中。
drain: 清空组件,不是堵塞运行的。
setOutputSurface: 设置输出的surface。
start: 启动组件。
stop: stop组件。
frameworks\av\media\codec2\hidl\services\vendor.cpp
在这里面的rc 中会启动一个android.hardware.media.c2@1.2-default-service
这个main函数中实现的是一个componentStore。
store = new utils::ComponentStore(
std::make_shared());
constexpr char const* serviceName = "default";
if (store->registerAsService(serviceName) != OK) {
LOG(ERROR) << "Cannot register Codec2's IComponentStore service"
" with instance name << \""
<< serviceName << "\".";
} else {
LOG(DEBUG) << "Codec2's IComponentStore service registered. "
"Instance name: \"" << serviceName << "\".";
}