You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Refactor player sessions Fix PixelStreamingAudioComponent had delayed audio. Fix audio bitrate from Unreal Engine to browser was set to a low default causing compressed audio quality in stream. The new default is now Opus maximum value of 510kb/s. Fix the Selective Forwarding Unit (SFU) not being added to the Pixel Streaming samples folder for a packaged project Fix default max bitrate not being high enough to support 4k. Fix reconnections not autoplaying in the browser. Add datachannel support to SFU. Add WebRTC c++ client behaviour to pixel streaming system. This is used for developing unit tests. Add a unit test that will start streaming, connect a client and check that a data channel message can be sent. Add the ability for a user to start/stop streaming as needed through the use of PixelStreaming.StartStreaming and PixelStreaming.StopStreaming Add the ability for the stream resolution to be changed at runtime Notes: AVEncoder no longer stores a width and height; These properties have been moved to the FVideoEncoderInput. This input is now the source of truth and both AMF and NVENC will adapt their resolution to the input resolution. #rb luke.bermingham #fyi mattias.jansson, nick.pace, matthew.cotton, aidan.possemiers, sandor.hadas #preflight 6204c7aba65a8a28464df03c #jira none [CL 18948482 by William Belcher in ue5-main branch]
112 lines
3.7 KiB
C++
112 lines
3.7 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "VideoEncoderInput.h"
|
|
#include "Misc/FrameRate.h"
|
|
#include "Misc/ScopeLock.h"
|
|
|
|
namespace AVEncoder
|
|
{
|
|
class AVENCODER_API FVideoEncoder
|
|
{
|
|
public:
|
|
enum class RateControlMode { UNKNOWN, CONSTQP, VBR, CBR };
|
|
enum class MultipassMode { UNKNOWN, DISABLED, QUARTER, FULL };
|
|
enum class H264Profile { AUTO, CONSTRAINED_BASELINE, BASELINE, MAIN, CONSTRAINED_HIGH, HIGH, HIGH444, STEREO, SVC_TEMPORAL_SCALABILITY, PROGRESSIVE_HIGH };
|
|
|
|
struct FLayerConfig
|
|
{
|
|
uint32 Width = 0;
|
|
uint32 Height = 0;
|
|
uint32 MaxFramerate = 0;
|
|
int32 MaxBitrate = 0;
|
|
int32 TargetBitrate = 0;
|
|
int32 QPMax = -1;
|
|
int32 QPMin = -1;
|
|
RateControlMode RateControlMode = RateControlMode::CBR;
|
|
MultipassMode MultipassMode = MultipassMode::FULL;
|
|
bool FillData = false;
|
|
H264Profile H264Profile = H264Profile::BASELINE;
|
|
|
|
bool operator==(FLayerConfig const& other) const
|
|
{
|
|
return Width == other.Width
|
|
&& Height == other.Height
|
|
&& MaxFramerate == other.MaxFramerate
|
|
&& MaxBitrate == other.MaxBitrate
|
|
&& TargetBitrate == other.TargetBitrate
|
|
&& QPMax == other.QPMax
|
|
&& QPMin == other.QPMin
|
|
&& RateControlMode == other.RateControlMode
|
|
&& MultipassMode == other.MultipassMode
|
|
&& FillData == other.FillData
|
|
&& H264Profile == other.H264Profile;
|
|
}
|
|
|
|
bool operator!=(FLayerConfig const& other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
};
|
|
|
|
virtual ~FVideoEncoder();
|
|
|
|
virtual bool Setup(TSharedRef<FVideoEncoderInput> input, FLayerConfig const& config) { return false; }
|
|
virtual void Shutdown() {}
|
|
|
|
virtual bool AddLayer(FLayerConfig const& config);
|
|
uint32 GetNumLayers() const { return static_cast<uint32>(Layers.Num()); }
|
|
virtual uint32 GetMaxLayers() const { return 1; }
|
|
|
|
FLayerConfig GetLayerConfig(uint32 layerIdx) const;
|
|
void UpdateLayerConfig(uint32 layerIdx, FLayerConfig const& config);
|
|
|
|
using OnFrameEncodedCallback = TFunction<void(const TSharedPtr<FVideoEncoderInputFrame> /* InCompletedFrame */)>;
|
|
using OnEncodedPacketCallback = TFunction<void(uint32 /* LayerIndex */, const TSharedPtr<FVideoEncoderInputFrame> /* Frame */, const FCodecPacket& /* Packet */)>;
|
|
|
|
struct FEncodeOptions
|
|
{
|
|
bool bForceKeyFrame = false;
|
|
OnFrameEncodedCallback OnFrameEncoded;
|
|
};
|
|
|
|
void SetOnEncodedPacket(OnEncodedPacketCallback callback) { OnEncodedPacket = MoveTemp(callback); }
|
|
void ClearOnEncodedPacket() { OnEncodedPacket = nullptr; }
|
|
|
|
virtual void Encode(const TSharedPtr<FVideoEncoderInputFrame> frame, FEncodeOptions const& options) {}
|
|
|
|
protected:
|
|
FVideoEncoder() = default;
|
|
|
|
class FLayer
|
|
{
|
|
public:
|
|
explicit FLayer(FLayerConfig const& layerConfig)
|
|
: CurrentConfig(layerConfig)
|
|
, NeedsReconfigure(false)
|
|
{}
|
|
virtual ~FLayer() = default;
|
|
|
|
FLayerConfig const& GetConfig() const { return CurrentConfig; }
|
|
void UpdateConfig(FLayerConfig const& config)
|
|
{
|
|
FScopeLock lock(&ConfigMutex);
|
|
CurrentConfig = config;
|
|
NeedsReconfigure = true;
|
|
}
|
|
|
|
protected:
|
|
FCriticalSection ConfigMutex;
|
|
FLayerConfig CurrentConfig;
|
|
bool NeedsReconfigure;
|
|
};
|
|
|
|
virtual FLayer* CreateLayer(uint32 layerIdx, FLayerConfig const& config) { return nullptr; }
|
|
virtual void DestroyLayer(FLayer* layer) {};
|
|
|
|
TArray<FLayer*> Layers;
|
|
OnEncodedPacketCallback OnEncodedPacket;
|
|
};
|
|
} |