Files
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

193 lines
6.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "EpicRtcTrack.h"
#include "IPixelStreaming2DataProtocol.h"
#include "Templates/SharedPointer.h"
#define UE_API PIXELSTREAMING2RTC_API
namespace UE::PixelStreaming2
{
template <typename T>
inline size_t GetByteSizeOf(const T&& Value)
{
// Requires being r-value reference because the string and array specialization
// is not always detected and forwarding allows the right specialization to be used.
static_assert(std::is_rvalue_reference<decltype(Value)>::value);
return sizeof(Value);
}
template <typename T>
inline const void* GetDataPointer(const T&& Value)
{
// Requires being r-value reference because the string and array specialization
// is not always detected and forwarding allows the right specialization to be used.
static_assert(std::is_rvalue_reference<decltype(Value)>::value);
return &Value;
}
inline size_t GetByteSizeOf(const FString&& Value)
{
// Requires being r-value reference because the string and array specialization
// is not always detected and forwarding allows the right specialization to be used.
static_assert(std::is_rvalue_reference<decltype(Value)>::value);
return Value.Len() * sizeof(TCHAR);
}
inline const void* GetDataPointer(const FString&& Value)
{
// Requires being r-value reference because the string and array specialization
// is not always detected and forwarding allows the right specialization to be used.
static_assert(std::is_rvalue_reference<decltype(Value)>::value);
return *Value;
}
template <typename T>
inline size_t GetByteSizeOf(const TArray<T>&& Value)
{
// Requires being r-value reference because the string and array specialization
// is not always detected and forwarding allows the right specialization to be used.
static_assert(std::is_rvalue_reference<decltype(Value)>::value);
return Value.Num() * sizeof(T);
}
template <typename T>
inline const void* GetDataPointer(const TArray<T>&& Value)
{
// Requires being r-value reference because the string and array specialization
// is not always detected and forwarding allows the right specialization to be used.
static_assert(std::is_rvalue_reference<decltype(Value)>::value);
return Value.GetData();
}
struct FBufferBuilder
{
TArray<uint8> Buffer;
size_t Pos;
FBufferBuilder(size_t size)
: Pos(0)
{
Buffer.SetNum(size);
}
size_t Serialize(const void* Data, size_t DataSize)
{
check(Pos + DataSize <= Buffer.Num());
FMemory::Memcpy(Buffer.GetData() + Pos, Data, DataSize);
return Pos + DataSize;
}
template <typename T>
void Insert(const T&& Value)
{
// Requires being r-value reference because the string and array specialization
// is not always detected and forwarding allows the right specialization to be used.
static_assert(std::is_rvalue_reference<decltype(Value)>::value);
const size_t VSize = GetByteSizeOf(Forward<const T>(Value));
const void* VLoc = GetDataPointer(Forward<const T>(Value));
check(Pos + VSize <= Buffer.Num());
FMemory::Memcpy(Buffer.GetData() + Pos, VLoc, VSize);
Pos += VSize;
}
};
class FEpicRtcDataTrack : public TEpicRtcTrack<EpicRtcDataTrackInterface>, public TSharedFromThis<FEpicRtcDataTrack>
{
public:
static UE_API TSharedPtr<FEpicRtcDataTrack> Create(TRefCountPtr<EpicRtcDataTrackInterface> InTrack, TWeakPtr<IPixelStreaming2DataProtocol> InDataProtocol);
virtual ~FEpicRtcDataTrack() = default;
/**
* Sends a series of arguments to the data channel with the given type.
* @param MessageType The name of the message you want to send. This message name must be registered IPixelStreaming2InputHandler::GetFromStreamerProtocol().
* @returns True of the message was successfully sent.
*/
template <typename... Args>
bool SendMessage(FString MessageType, Args... VarArgs) const
{
if (!IsActive())
{
return false;
}
uint8 MessageId;
if (!GetMessageId(MessageType, MessageId))
{
return false;
}
FBufferBuilder Builder = EncodeMessage(MessageId, Forward<Args>(VarArgs)...);
return Send(Builder.Buffer);
}
/**
* Sends a large buffer of data to the data track, will chunk into multiple data frames if frames greater than 16KB.
* @param MessageType The name of the message, it must be registered in IPixelStreaming2InputHandler::GetTo/FromStreamerProtocol()
* @param DataBytes The raw byte buffer to send.
* @returns True of the message was successfully sent.
*/
UE_API bool SendArbitraryData(const FString& MessageType, const TArray64<uint8>& DataBytes) const;
/**
* @return The state of the underlying EpicRtc data track.
*/
EpicRtcTrackState GetState() const { return Track->GetState(); }
void SetSendTrack(TRefCountPtr<EpicRtcDataTrackInterface> InSendTrack) { SendTrack = InSendTrack; }
protected:
UE_API FEpicRtcDataTrack(TRefCountPtr<EpicRtcDataTrackInterface> InTrack, TWeakPtr<IPixelStreaming2DataProtocol> InDataProtocol);
UE_API FEpicRtcDataTrack(TSharedPtr<FEpicRtcDataTrack> InTrack, TWeakPtr<IPixelStreaming2DataProtocol> InDataProtocol);
virtual void PrependData(FBufferBuilder& Builder) const {};
UE_API bool IsActive() const;
UE_API bool GetMessageId(const FString& MessageType, uint8& OutMessageId) const;
private:
/**
* Track that is used for sending data with Consumer/Producer architecture.
*/
TRefCountPtr<EpicRtcDataTrackInterface> SendTrack;
TWeakPtr<IPixelStreaming2DataProtocol> WeakDataProtocol;
UE_API bool Send(TArray<uint8>& Buffer) const;
template <typename... Args>
FBufferBuilder EncodeMessage(uint8 Type, Args... VarArgs) const
{
FBufferBuilder Builder(sizeof(Type) + (0 + ... + GetByteSizeOf(Forward<Args>(VarArgs))));
PrependData(Builder);
Builder.Insert(Forward<uint8>(Type));
(Builder.Insert(Forward<Args>(VarArgs)), ...);
return MoveTemp(Builder);
}
};
class FEpicRtcMutliplexDataTrack : public FEpicRtcDataTrack
{
public:
static UE_API TSharedPtr<FEpicRtcMutliplexDataTrack> Create(TSharedPtr<FEpicRtcDataTrack> InTrack, TWeakPtr<IPixelStreaming2DataProtocol> InDataProtocol, const FString& InPlayerId);
protected:
UE_API FEpicRtcMutliplexDataTrack(TSharedPtr<FEpicRtcDataTrack> InTrack, TWeakPtr<IPixelStreaming2DataProtocol> InDataProtocol, const FString& InPlayerId);
UE_API virtual void PrependData(FBufferBuilder& Builder) const override;
private:
const FString PlayerId;
};
} // namespace UE::PixelStreaming2
#undef UE_API