codec2play是android上codec2的一个demo程序,在frameworks/av/media/codec2/components/cmds
目录下可以找到原始代码,这里把hardware component
创建和software component
创建做一个对比,加深对codec2
的理解。
首先,Codec2Client::CreateFromService中通过hidl ServiceManager获取ServiceManager对象,然后通过listManifestByInterface接口,查询平台的component name,然后返回name合集,根据name创建创建Codec2Client对象client,SetPreferredCodec2ComponentStore将client设置到gPreferredComponentStore,后面创建component就从这个store里面创建。
// create decoder component
std::shared_ptr<Codec2Client> client = Codec2Client::CreateFromService("default");
SetPreferredCodec2ComponentStore(std::make_shared<Codec2ClientInterfaceWrapper>(client));
mComponent = Codec2Client::CreateComponentByName("c2.qti.avc.decoder", mClientListener, &client);
serviceManager中获取service的代码:
transResult = serviceManager->listManifestByInterface(
IComponentStore::descriptor,
[&defaultNames, &vendorNames, &otherNames](
hidl_vec<hidl_string> const& instanceNames) {
for (hidl_string const& instanceName : instanceNames) {
char const* name = instanceName.c_str();
if (strncmp(name, "default", 7) == 0) {
defaultNames.emplace_back(name);
} else if (strncmp(name, "vendor", 6) == 0) {
vendorNames.emplace_back(name);
} else {
otherNames.emplace_back(name);
}
}
});
Base1_0和Base1_1的定义实际上是V1_0和V1_1的IComponent别名:
typedef ::android::hardware::media::c2::V1_0::IComponent Base1_0;
typedef ::android::hardware::media::c2::V1_1::IComponent Base1_1;
typedef Base1_0 Base;
hidl中的接口类的声明:
namespace android::hardware::media::c2::V1_0 {
struct IConfigurable;
struct IComponent;
struct IComponentInterface;
struct IComponentStore;
struct IInputSink;
struct IInputSurface;
struct IInputSurfaceConnection;
} // namespace android::hardware::media::c2::V1_0
namespace android::hardware::media::c2::V1_1 {
struct IComponent;
struct IComponentStore;
} // namespace android::hardware::media::c2::V1_1
通过Base1_0或者Base1_1的createComponent接口,创建component:
c2_status_t status;
sp<Component::HidlListener> hidlListener = new Component::HidlListener{
};
mBase1_0->createComponent(
name,
hidlListener,
ClientManager::getInstance(),
[&status, component, hidlListener](
Status s,
const sp<hardware::media::c2::V1_0::IComponent>& c) {
status = static_cast<c2_status_t>(s);
if (status != C2_OK) {
return;
}
*component = std::make_shared<Codec2Client::Component>(c);
hidlListener->component = *component;
}
);
其中lambda表达式可以理解为一个函数指针对应的函数体,要知道这个在哪调用,进入createComponent_1_1函数就可以看到,最后component创建后以后会作为参数c传递给lambda表达式,status的值作为参数s,在createComponent_1_1中通过
_hidl_cb
调用,lambda表达式实际上就是_hidl_cb
。[&status, component, hidlListener]( Status s, const sp<hardware::media::c2::V1_0::IComponent>& c) { status = static_cast<c2_status_t>(s); if (status != C2_OK) { return; } *component = std::make_shared<Codec2Client::Component>(c); hidlListener->component = *component; }
ComponentStore::createComponent_1_1函数,也就是hidl中的::android::hardware::media::c2::V1_1::utils::ComponentStore::createComponent_1_1
,真正创建component就是在这里创建的。
// from ::android::hardware::media::c2::V1_1::utils::ComponentStore
Return<void> ComponentStore::createComponent_1_1(
const hidl_string& name,
const sp<IComponentListener>& listener,
const sp<IClientManager>& pool,
createComponent_1_1_cb _hidl_cb) {
sp<Component> component;
std::shared_ptr<C2Component> c2component;
Status status = static_cast<Status>(
mStore->createComponent(name, &c2component));
if (status == Status::OK) {
onInterfaceLoaded(c2component->intf());
component = new Component(c2component, listener, this, pool);
if (!component) {
status = Status::CORRUPTED;
} else {
reportComponentBirth(component.get());
if (component->status() != C2_OK) {
status = static_cast<Status>(component->status());
} else {
component->initListener(component);
if (component->status() != C2_OK) {
status = static_cast<Status>(component->status());
}
}
}
}
// 这个调用就走到lambda表达式里面
_hidl_cb(status, component);
return Void();
}
codec2play中原始代码是直接获取platform component store,通过store直接创建component的,这个store里面只是注册了软解的codec component。
std::shared_ptr<C2ComponentStore> store = GetCodec2PlatformComponentStore();
std::shared_ptr<C2Component> component;
(void)store->createComponent("c2.android.avc.decoder", &component);
可以看到C2PlatformComponentStore加载的库都在这个列表里面:
C2PlatformComponentStore::C2PlatformComponentStore()
: mVisited(false),
mReflector(std::make_shared<C2ReflectorHelper>()),
mInterface(mReflector) {
auto emplace = [this](const char *libPath) {
mComponents.emplace(libPath, libPath);
};
emplace("libcodec2_soft_aacdec.so");
emplace("libcodec2_soft_aacenc.so");
emplace("libcodec2_soft_amrnbdec.so");
emplace("libcodec2_soft_amrnbenc.so");
emplace("libcodec2_soft_amrwbdec.so");
emplace("libcodec2_soft_amrwbenc.so");
emplace("libcodec2_soft_avcdec.so");
emplace("libcodec2_soft_avcenc.so");
emplace("libcodec2_soft_flacdec.so");
emplace("libcodec2_soft_flacenc.so");
emplace("libcodec2_soft_g711alawdec.so");
emplace("libcodec2_soft_g711mlawdec.so");
emplace("libcodec2_soft_gsmdec.so");
emplace("libcodec2_soft_h263dec.so");
emplace("libcodec2_soft_h263enc.so");
emplace("libcodec2_soft_hevcdec.so");
emplace("libcodec2_soft_hevcenc.so");
emplace("libcodec2_soft_mp3dec.so");
emplace("libcodec2_soft_mpeg2dec.so");
emplace("libcodec2_soft_mpeg4dec.so");
emplace("libcodec2_soft_mpeg4enc.so");
emplace("libcodec2_soft_opusdec.so");
emplace("libcodec2_soft_opusenc.so");
emplace("libcodec2_soft_rawdec.so");
emplace("libcodec2_soft_vorbisdec.so");
emplace("libcodec2_soft_vp8dec.so");
emplace("libcodec2_soft_vp8enc.so");
emplace("libcodec2_soft_vp9dec.so");
emplace("libcodec2_soft_vp9enc.so");
}
hardware/interfaces/media/c2/
├── 1.0
│ ├── Android.bp
│ ├── IComponent.hal
│ ├── IComponentInterface.hal
│ ├── IComponentListener.hal
│ ├── IComponentStore.hal
│ ├── IConfigurable.hal
│ ├── IInputSink.hal
│ ├── IInputSurfaceConnection.hal
│ ├── IInputSurface.hal
│ └── types.hal
└── 1.1
├── Android.bp
├── IComponent.hal
└── IComponentStore.hal
namespace android::hardware::media::c2::V1_0 {
struct IConfigurable;
struct IComponent;
struct IComponentInterface;
struct IComponentStore;
struct IInputSink;
struct IInputSurface;
struct IInputSurfaceConnection;
} // namespace android::hardware::media::c2::V1_0
namespace android::hardware::media::c2::V1_1 {
struct IComponent;
struct IComponentStore;
} // namespace android::hardware::media::c2::V1_1
类似的可以在drm里面看到:
- drm/libmediadrm/interface/mediadrm/ICrypto.h
namespace android { namespace hardware { class HidlMemory; namespace drm { namespace V1_0 { struct SharedBuffer; struct DestinationBuffe } // namespace V1_0 } // namespace drm } // namespace hardwar } // namespace android
namespace android
namespace hardware
namespace media
namespace c2
namespace V1_0
struct IConfigurable
struct IComponent
struct IComponentInterface
struct IComponentStore
struct IInputSink
struct IInputSurface
struct IInputSurfaceConnection
namespace android
namespace hardware
namespace media
namespace c2
namespace V1_1
struct IComponent
struct IComponentStore
namespace android
namespace hardware
namespace media
namespace bufferpool
namespace V2_0
struct IClientManager
namespace android
namespace hardware
namespace graphics
namespace bufferqueue
namespace V1_0
struct IGraphicBufferProducer
namespace android
namespace hardware
namespace graphics
namespace bufferqueue
namespace V2_0
struct IGraphicBufferProducer
namespace android
namespace hardware
namespace media
namespace omx
namespace V1_0
struct IGraphicBufferSource
Codec2Client是包含以下内部类的主类:
- Listener
- Configurable
- Interface
- Component
Codec2Client中的类、codec2.0接口,和HIDL之间的关系:
- Codec2Client <==> C2ComponentStore <==> IComponentStore
- Codec2Client::Listener <==> C2Component::Listener <==> IComponentListener
- Codec2Client::Configurable <==> [No equivalent] <==> IConfigurable
- Codec2Client::Interface <==> C2ComponentInterface <==> IComponentInterface
- Codec2Client::Component <==> C2Component <==> IComponent
入口点是Codec2Client::CreateFromService(),它创建一个Codec2Client对象,在Codec2Client中,可以通过调用createComponent()和createInterface()来创建接口和组件对象。createComponent()接受一个Listener对象,该对象必须由用户实现。
目前,createBlockPool()是唯一一个生成可配置对象。但是请注意,接口、组件和Codec2Client是可配置的所有子类。
Codec2Client::CreateFromService
getServiceIndex
Codec2Client::GetServiceNames
serviceManager = IServiceManager::getService
serviceManager->listManifestByInterface
Codec2Client::CreateFromService会通过Hidl ServiceManager::listManifestByInterface获取service名字,创建Codec2Client,然后SetPreferredCodec2ComponentStore之后,就可以访问vendor的store。
// set up preferred component store to access vendor store parameters
client = Codec2Client::CreateFromService("default");
if (client) {
ALOGI("setting up '%s' as default (vendor) store", client->getServiceName().c_str());
SetPreferredCodec2ComponentStore(
std::make_shared<Codec2ClientInterfaceWrapper>(client));
}
这部分是从CCodecBufferChannel::renderOutputBuffer代码中找出来的,用于理解hardwarecodec的渲染流程,首先从output中获得c2Buffer,然后创建android::IGraphicBufferProducer::QueueBufferInput
对象qbi,最后是mComponent->queueToOutputSurface把buffer
送给surface显示。
这部分的调用栈:
NuPlayer::Decoder::onRenderBuffer
MediaCodec::renderOutputBufferAndRelease
MediaCodec::onReleaseOutputBuffer
CCodecBufferChannel::renderOutputBuffer
CCodecBufferChannel::renderOutputBuffer中的主要代码:
// c2Buffer
std::shared_ptr<C2Buffer> c2Buffer;
bool released = false;
{
Mutexed<Output>::Locked output(mOutput);
if (output->buffers) {
released = output->buffers->releaseBuffer(buffer, &c2Buffer);
}
}
// get C2ConstGraphicBlock
std::vector<C2ConstGraphicBlock> blocks = c2Buffer->data().graphicBlocks();
if (blocks.size() != 1u) {
ALOGD("[%s] expected 1 graphic block, but got %zu", mName, blocks.size());
return UNKNOWN_ERROR;
}
const C2ConstGraphicBlock &block = blocks.front();
// TODO: revisit this after C2Fence implementation.
android::IGraphicBufferProducer::QueueBufferInput qbi(
timestampNs,
false, // droppable
dataSpace,
Rect(blocks.front().crop().left,
blocks.front().crop().top,
blocks.front().crop().right(),
blocks.front().crop().bottom()),
videoScalingMode,
transform,
Fence::NO_FENCE, 0);
// we don't have dirty regions
qbi.setSurfaceDamage(Region::INVALID_REGION);
android::IGraphicBufferProducer::QueueBufferOutput qbo;
status_t result = mComponent->queueToOutputSurface(block, qbi, &qbo);
if (result != OK) {
ALOGI("[%s] queueBuffer failed: %d", mName, result);
return result;
}
int slot;
sp<Fence> fence;
std::shared_ptr<C2Buffer> output;
const sp<IGraphicBufferProducer> &igbp = mSurface->getIGraphicBufferProducer();
size_t size = work->worklets.front()->output.buffers.size();
if (size == 1u) {
output = work->worklets.front()->output.buffers[0];
} else {
fprintf(stderr, "got output buffers size: %zu.\n", size);
}
// 从work中拿到C2Buffer类型的output后进行渲染
if (output != nullptr) {
const C2ConstGraphicBlock block = output->data().graphicBlocks().front();
native_handle_t *grallocHandle = UnwrapNativeCodec2GrallocHandle(block.handle());
sp<GraphicBuffer> buffer(new GraphicBuffer(
grallocHandle,
GraphicBuffer::CLONE_HANDLE,
block.width(),
block.height(),
HAL_PIXEL_FORMAT_YV12,
1,
(uint64_t)GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,
block.width()));
native_handle_delete(grallocHandle);
// 创建QueueBufferInput
status_t err = igbp->attachBuffer(&slot, buffer);
IGraphicBufferProducer::QueueBufferInput qbi(
(work->worklets.front()->output.ordinal.timestamp * 1000ll).peekll(),
false,
HAL_DATASPACE_UNKNOWN,
Rect(block.width(), block.height()),
NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW,
0,
Fence::NO_FENCE,
0);
// 调用IGraphicBufferProducer::queueBuffer把inputbuffer给送给surface
IGraphicBufferProducer::QueueBufferOutput qbo;
err = igbp->queueBuffer(slot, qbi, &qbo);
fprintf(stderr, "%d igbp queue buffer.\n", gettid());
}
文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib
文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang
文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些
文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器
文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距
文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器
文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn
文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios
文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql
文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...
文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120
文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数