chromium中mojom中增加接口

博客介绍了如何在Mojo的VideoDecoder接口中添加新的FramesRendered方法,用于获取解码后的帧渲染次数。详细阐述了从修改mojom文件,到编译生成C++接口,再到实现回调函数的整个过程,包括在MojoVideoDecoderService和MojoVideoDecoder中如何调用和处理这个方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FramesRendered接口

Mojo是一个跨平台IPC框架,它诞生于chromium,用来实现chromium进程内/进程间的通信。Mojo在Binding层中引入了mojom这种IDL语言,用它来定义接口。接口定义文件的后缀一般为.mojom

比如:

// mojom/test.mojom

// 定义接口所属的"module",在生成的C++代码中对应到命名空间
module demo.mojom;

// 定义一个接口,在C++中对应一个抽象类
interface Test {
  // 定义一个Hello方法,该方法没有返回值
  Hello(string who);
  // 定义一个Hi方法,返回值为string类型
  // 返回值会对应到C++中的回调方法
  Hi() => (string who);
};

我们因为使用mojo video decoder,所以增加一个获取底层平台的接口,从DecoderStream中获取,就需要在mojom::VideoDecoder中增加接口。

media/mojo/mojom/video_decoder.mojom

interface VideoDecoder {

  GetSupportedConfigs() =>
      (array<SupportedVideoDecoderConfig> supported_configs,
       VideoDecoderType decoder_type);

  Construct(
      pending_associated_remote<VideoDecoderClient> client,
      pending_remote<MediaLog> media_log,
      pending_receiver<VideoFrameHandleReleaser> video_frame_handle_releaser,
      handle<data_pipe_consumer> decoder_buffer_pipe,
      CommandBufferId? command_buffer_id,
      gfx.mojom.ColorSpace target_color_space);

  Initialize(VideoDecoderConfig config, bool low_delay,
             mojo_base.mojom.UnguessableToken? cdm_id)
      => (DecoderStatus status,
          bool needs_bitstream_conversion,
          int32 max_decode_requests,
          VideoDecoderType decoder_type);

  Decode(DecoderBuffer buffer) => (DecoderStatus status);
  
  Reset() => ();
  
  OnOverlayInfoChanged(OverlayInfo overlay_info);
};          

修改mojom文件:

打开mojo/mojom/video_decoder.mojom文件,在interface VideoDecoder 的最后添加定义FramesRendered()方法,返回值是int32类型(用int的时候报错,提示不支持,int32就没问题),返回值会对应到C++中的回调方法:

  GetFramesRendered() => (int32 frames_rendered);

编译后生成的头文件out/chrome/video_decoder.mojom.h中,会产生一个GetFramesRenderedCallback的定义,可以看到这个方法是纯虚函数,需要自己实现具体的功能,函数参数变成这个GetFramesRenderedCallback,这个名字是由函数名加上Callback组成:

  using GetFramesRenderedCallback = base::OnceCallback<void(int32_t)>;
  
  virtual void GetFramesRendered(GetFramesRenderedCallback callback) = 0;

mojo/services/mojo_video_decoder_service.h中继承,实现GetFramesRendered

// .h
void GetFramesRendered(GetFramesRenderedCallback callback) final;

// .cc
void MojoVideoDecoderService::GetFramesRendered(
  GetFramesRenderedCallback callback) {

  int32_t frames_rendered = decoder_->GetFramesRendered();
  std::move(callback).Run(frames_rendered);
}

在上面MojoVideoDecoderService::GetFramesRendered中,decoder_就是比较具体的decoder了,由GpuMojoMediaClient::CreateVideoDecoder创建具体的platform decoder,从decoder_中得到frames_rendered值之后,然后通过callback调用,把这个值给传出去。

MojoVideoDecoderService创建decoder_的代码:

  decoder_ = mojo_media_client_->CreateVideoDecoder(
      task_runner, media_log_.get(), std::move(command_buffer_id),
      base::BindRepeating(
          &MojoVideoDecoderService::OnDecoderRequestedOverlayInfo, weak_this_),
      target_color_space);

然后从MojoVideoDecoder中去调用这个函数,头文件中增加以下定义:

int GetFramesRendered() override;
void OnFramesRendered(int32_t rendered);

int32_t frames_rendered_ = 0;

cc文件中调用GetFramesRendered,并且绑定回调函数MojoVideoDecoder::OnFramesRendered:

int MojoVideoDecoder::GetFramesRendered() {
  // remote_decoder_就是MojoVideoDecoderService对象
  // 绑定MojoVideoDecoder::OnFramesRendered函数
  remote_decoder_->GetFramesRendered(
      base::BindOnce(&MojoVideoDecoder::OnFramesRendered, weak_this_));
  return frames_rendered_;
}

void MojoVideoDecoder::OnFramesRendered(int32_t rendered) {
  frames_rendered_ = rendered;
}

这里,callback的定义必须是符合void(int32_t)形式,返回值是void,参数是int32_t

void MojoVideoDecoder::OnFramesRendered(int32_t rendered) {
  frames_rendered_ = rendered;
    
}
base::BindOnce

base::OnceCallback<>base::BindOnce()创建,只能运行一次。

weak_this_

MojoVideoDecoder有一个base::WeakPtr weak_this_成员,则使用以下方法绑定类方法:

base::BindOnce(&MojoVideoDecoder::OnFramesRendered, weak_this_)

使用weak_this_的好处是如果对象已被销毁,则回调将不会运行。


碰到一个书写错误导致的编译问题,类型声明和定义不匹配就有这样的错误输出,实际上是很简单的一个错误,但是在chromium中,会输出好多条错误信息,看着有点懵,仔细检查下就行:

error: no viable conversion from 'OnceCallback<internal::MakeUnboundRunType<int (MojoVideoDecoder::*)(int), WeakPtr<MojoVideoDecoder> &>>' to 'OnceCallback<void (int32_t)>'
      base::BindOnce(&MojoVideoDecoder::OnFramesRendered, weak_this_));
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

参考

Chrome多线程任务处理

Chromium Mojo & IPC

### 关于 Chromium 的中文资料和教程 对于希望深入了解 Chromium开发者来说,获取高质量的学习资源至关重要。以下是关于 Chromium 的一些重要中文资料和教程: #### 1. **官方文档翻译** 虽然 Chromium 和 Chrome 官方文档主要以英文为主,但社区已经提供了部分中文翻译资源。可以通过以下方式查找相关内容: - 访问 Chromium 官方开发者文档的镜像站点[^1],并利用在线工具将其自动翻译成中文。 - 参考国内技术博客中的 Chromium 文档解读文章。 #### 2. **华为 OpenHarmony 上的 Chromium 学习资源** 华为维护了一个名为 `openharmony-tpc/chromium_chrome` 的开源仓库,该仓库不仅包含了 Chromium 的源码,还提供了一些学习指南和技术说明。可以重点关注以下几个方面: - 源码目录结构解析:通过阅读 `master` 分支下的代码组织形式,理解 Chromium 的模块化设计。 - 渲染引擎 Blink 的实现细节:Blink 是 Chromium 的核心渲染引擎之一,其相关书籍和教程可以帮助深入研究网页渲染机制。 #### 3. **Playwright 工具及其 Python 实现** 如果目标是自动化测试或者模拟浏览器行为,则可以考虑使用 Playwright 工具。它支持多种浏览器环境(如 Chromium),并且有一个专门针对 Python 用户编写的入门级教程项目——playwright-python-tutorial[^3]。该项目涵盖了如何设置开发环境以及编写基本脚本等内容。 #### 4. **CEFSharp 升级与定制化需求** 对于需要集成嵌入式 Web 浏览器的应用程序而言,CEF(Chromium Embedded Framework)是一个不错的选择。特别是 CEFSharp 这一 .NET 平台上的封装库,在不同版本之间可能存在兼容性差异[^4]。因此建议关注具体应用场景下所选版本的功能特性描述。 ```python from playwright.sync_api import sync_playwright with sync_playwright() as p: browser = p.chromium.launch(headless=False) page = browser.new_page() page.goto('http://example.com') print(page.title()) browser.close() ``` 上述代码展示了如何利用 Playwright 控制 Chromium 浏览器加载页面并打印标题。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值