0
点赞
收藏
分享

微信扫一扫

虚幻引擎像素流源码解读


前言

假期在家把虚幻引擎像素流的源码有研究了一下,进行了一下总结,本文适合有一定使用虚幻引擎像素流经验的人阅读。

源码地址

这里研究的是UE5.1的版本,源码位置如下

C:\Program Files\Epic Games\UE_5.1\Engine\Plugins\Media\PixelStreaming



虚幻引擎像素流源码解读_封装

websocket处理

像素流和signal服务之间通过websocket进行通信,处理业务的逻辑在FPixelStreamingSignallingConnection这个类中,处理消息的函数如下

void FPixelStreamingSignallingConnection::OnMessage(const FString& Msg)
{
 FJsonObjectPtr JsonMsg;
 const auto JsonReader = TJsonReaderFactory<TCHAR>::Create(Msg);

 if (!FJsonSerializer::Deserialize(JsonReader, JsonMsg))
 {
  UE_LOG(LogPixelStreamingSS, Error, TEXT("Failed to parse SS message:\n%s"), *Msg);
  return;
 }

 FString MsgType;
 if (!JsonMsg->TryGetStringField(TEXT("type"), MsgType))
 {
  UE_LOG(LogPixelStreamingSS, Error, TEXT("Cannot find `type` field in SS message:\n%s"), *Msg);
  return;
 }

 TFunction<void(FJsonObjectPtr)>* Handler = MessageHandlers.Find(MsgType);
 if (Handler != nullptr)
 {
  (*Handler)(JsonMsg);
 }
 else
 {
  UE_LOG(LogPixelStreamingSS, Error, TEXT("Unsupported message `%s` received from SS"), *MsgType);
 }
}

一共定义了12种类型的消息处理,如下图



虚幻引擎像素流源码解读_虚幻引擎_02

意外发现,居然还有一个PixelStreamServers工程,可以创建signal服务,这样的话,就可以一个虚幻程序,搞定所有,不再需要再启动一个nodejs的signal服务了。websocket服务监听,代码如下:,调用的是WebSocketNetworking这个模块创建的服务端。



虚幻引擎像素流源码解读_游戏引擎_03

相关业务处理逻辑见FSignallingServer这个类,可以管理连接上来的websocket连接。



虚幻引擎像素流源码解读_游戏引擎_04

web与UE通信事件

web和UE的通信事件,在FPixelStreamingModule::PopulateProtocol函数中进行定义,每个事件有一个id。



虚幻引擎像素流源码解读_游戏引擎_05

我们的peerstream里面定义的事件id也是和这里一一对应的。



虚幻引擎像素流源码解读_虚幻引擎_06

大家可以看到两边的值是一样的,整个通信,实际上就是通过这个id来进行区分。

UE接受web的消息处理函数为FPixelStreamingDataChannel::OnMessage,



虚幻引擎像素流源码解读_虚幻_07

这里所有接受到的数据,都会丢进游戏线程进行处理。这里第一个字节,表示消息类型,所以最大可以定义255种消息。

接下来,业务逻辑处理的函数在FStreamer::OnDataChannelMessage中进行处理。

虚幻引擎像素流源码解读_消息处理_08

通过InputHandler对象进行统一处理,其定义如下

InputHandler = MakeShared<FPixelStreamingInputHandler>(PixelStreamerApplicationWrapper, BaseHandler);

整个业务处理封装在FPixelStreamingInputHandler类中,在其定义中,我们发现了根据不同类型的处理函数。



虚幻引擎像素流源码解读_虚幻_09

其定义了一个void FPixelStreamingInputHandler::OnMessage(const webrtc::DataBuffer& Buffer)函数,作为统一的消息处理入口。



虚幻引擎像素流源码解读_游戏引擎_10

所有的消息处理,都统一丢到了一个消息处理队列中。最后在tick中进行处理,所以UE接受的数据,都是在游戏线程进行业务逻辑的。



虚幻引擎像素流源码解读_虚幻_11

视频处理

视频处理是单独开启了一个线程来抓取图像,在FVideoSourceGroup类中,



虚幻引擎像素流源码解读_虚幻_12

根据帧率,定期的调用tick处理函数



虚幻引擎像素流源码解读_虚幻_13

图像的抓取,在FVideoSource这个类中进行,并通过OnFrame推送给webrtc库



虚幻引擎像素流源码解读_消息处理_14

整个图像的获取封装在FPixelStreamingVideoInput对象中,但是真正的抓取在FPixelCaptureCapturerMultiFormat类中,这个处理都封装在另外一个插件PixelCapture中,位置如下



虚幻引擎像素流源码解读_游戏引擎_15

视频的读取这一块,还没看明白,还需要再研究研究,如何从虚幻引擎读取画面,并推送到webrtc。

蓝图交互

蓝图的交互封装在UPixelStreamingInput这个对象里面,其继承至UActorComponent。其主要是想了两个函数,一个是回调数据给蓝图,一个是发送数据给web。



虚幻引擎像素流源码解读_封装_16

然后顺便还实现了json的一些简单操作,这里不做介绍。

相关的事件消息封装在UPixelStreamingDelegates对象中,其继承UObject。用户的连接事件、断线事件都是在这里进行处理。

虚幻引擎像素流源码解读_封装_17

总结

本文大概得研究了一下信令的交互流程,由于内容比较多,还有比较多的细节,需要深入研究。

举报

相关推荐

0 条评论