Bootstrap

chromium中mojom中增加接口

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

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;