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_));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~