forked from TheStudio/VPDevtemplate
Added ndi receiver and sdi outputs
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
|
||||
|
||||
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
|
||||
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <CoreMinimal.h>
|
||||
#include <Kismet/BlueprintFunctionLibrary.h>
|
||||
#include <Structures/NDIBroadcastConfiguration.h>
|
||||
|
||||
#include "NDIBroadcastConfigurationLibrary.generated.h"
|
||||
|
||||
UCLASS(NotBlueprintable, BlueprintType, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI Broadcast Configuration Library"))
|
||||
class NDIIO_API UNDIBroadcastConfigurationLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
private:
|
||||
/**
|
||||
Returns a value indicating whether the two structures are comparably equal
|
||||
|
||||
@param A The structure used as the source comparator
|
||||
@param B The structure used as the target comparator
|
||||
@return The resulting value of the comparator operator
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "NDI IO",
|
||||
META = (DisplayName = "Equals (NDI Broadcast Configuration)",
|
||||
CompactNodeTitle = "==", Keywords = "= == Equals", AllowPrivateAccess = true))
|
||||
static bool K2_Compare_NDIBroadcastConfiguration(FNDIBroadcastConfiguration A, FNDIBroadcastConfiguration B)
|
||||
{
|
||||
return A == B;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a value indicating whether the two structures are NOT comparably equal
|
||||
|
||||
@param A The structure used as the source comparator
|
||||
@param B The structure used as the target comparator
|
||||
@return The resulting value of the comparator operator
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "NDI IO",
|
||||
META = (DisplayName = "Not Equals (NDI Broadcast Configuration)",
|
||||
CompactNodeTitle = "!=", Keywords = "! != Not Equals", AllowPrivateAccess = true))
|
||||
static bool K2_Compare_Not_NDIBroadcastConfiguration(FNDIBroadcastConfiguration A, FNDIBroadcastConfiguration B)
|
||||
{
|
||||
return A != B;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
|
||||
|
||||
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
|
||||
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <CoreMinimal.h>
|
||||
#include <Kismet/BlueprintFunctionLibrary.h>
|
||||
#include <Structures/NDIConnectionInformation.h>
|
||||
|
||||
#include "NDIConnectionInformationLibrary.generated.h"
|
||||
|
||||
UCLASS(NotBlueprintable, BlueprintType, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI Connection Information Library"))
|
||||
class NDIIO_API UNDIConnectionInformationLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
private:
|
||||
/**
|
||||
Returns a value indicating whether the two structures are comparably equal
|
||||
|
||||
@param A The structure used as the source comparator
|
||||
@param B The structure used as the target comparator
|
||||
@return The resulting value of the comparator operator
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "NDI IO",
|
||||
META = (DisplayName = "Equals (NDI Connection Information)",
|
||||
CompactNodeTitle = "==", Keywords = "= == Equals", AllowPrivateAccess = true))
|
||||
static bool K2_Compare_NDIConnectionInformation(FNDIConnectionInformation A, FNDIConnectionInformation B)
|
||||
{
|
||||
return A == B;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a value indicating whether the two structures are NOT comparably equal
|
||||
|
||||
@param A The structure used as the source comparator
|
||||
@param B The structure used as the target comparator
|
||||
@return The resulting value of the comparator operator
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "NDI IO",
|
||||
META = (DisplayName = "Not Equals (NDI Connection Information)",
|
||||
CompactNodeTitle = "!=", Keywords = "! != Not Equals", AllowPrivateAccess = true))
|
||||
static bool K2_Compare_Not_NDIConnectionInformation(FNDIConnectionInformation A, FNDIConnectionInformation B)
|
||||
{
|
||||
return A != B;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a value indicating whether the property values of the supplied structure is valid
|
||||
|
||||
@param ConnectionInformation The structure to validate
|
||||
@return An indication of the supplied structures validity
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Is Valid?", AllowPrivateAccess = true))
|
||||
static bool K2_NDIConnectionInformation_IsValid(FNDIConnectionInformation& ConnectionInformation)
|
||||
{
|
||||
return ConnectionInformation.IsValid();
|
||||
}
|
||||
|
||||
/**
|
||||
Resets the structure's properties to their default values
|
||||
|
||||
@param ConnectionInformation The structure to reset to the default value
|
||||
@return The reference to the passed in structure after the 'reset' has been completed
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO",
|
||||
META = (DisplayName = "Reset Connection Information", AllowPrivateAccess = true))
|
||||
static UPARAM(ref) FNDIConnectionInformation& K2_NDIConnectionInformation_Reset(
|
||||
UPARAM(ref) FNDIConnectionInformation& ConnectionInformation)
|
||||
{
|
||||
// call the underlying function to reset the properties of the object
|
||||
ConnectionInformation.Reset();
|
||||
|
||||
// return the ConnectionInformation object reference
|
||||
return ConnectionInformation;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
|
||||
|
||||
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
|
||||
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <CoreMinimal.h>
|
||||
#include <Kismet/BlueprintFunctionLibrary.h>
|
||||
|
||||
#include <Structures/NDIConnectionInformation.h>
|
||||
#include <Objects/Media/NDIMediaReceiver.h>
|
||||
#include <Objects/Media/NDIMediaSender.h>
|
||||
|
||||
#include "NDIIOLibrary.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
An metadata element as returned by K2_ParseNDIMetaData()
|
||||
Blueprints do not support recursive datastructures, so parsing metadata
|
||||
with this will result in only the top-level elements being returned.
|
||||
*/
|
||||
USTRUCT(BlueprintType)
|
||||
struct FNDIMetaDataElement
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Metadata")
|
||||
FString ElementName;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Metadata")
|
||||
TMap<FString,FString> Attributes;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Metadata")
|
||||
FString Data;
|
||||
};
|
||||
|
||||
|
||||
UCLASS(META = (DisplayName = "NDI IO Library"))
|
||||
class NDIIO_API UNDIIOLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
private:
|
||||
/**
|
||||
Retrieves a collection of NDI sources appearing on the network
|
||||
|
||||
@return A collection of NDI Sources appearing on the network
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "NDI IO",
|
||||
META = (DisplayName = "Get NDI Source Collection", AllowPrivateAccess = true))
|
||||
static const TArray<FNDIConnectionInformation> K2_GetNDISourceCollection();
|
||||
|
||||
/**
|
||||
Attempts to search the NDI Source Collection for the source name, returning a result indicating
|
||||
success with the ConnectionInformation parameter filled with the found connection
|
||||
|
||||
@param ConnectionInformation The connection information for a successful find with the supplied InSourceName
|
||||
@param InSourceName The name of the source to find within the collection of NDI sources
|
||||
|
||||
@return The result of whether the search was successful
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO",
|
||||
META = (DisplayName = "Find Network Source by Name", DefaultToSelf = "WorldContextObject",
|
||||
HidePin = "WorldContextObject", AllowPrivateAccess = true))
|
||||
static const bool K2_FindNetworkSourceByName(UObject* WorldContextObject,
|
||||
FNDIConnectionInformation& ConnectionInformation,
|
||||
FString InSourceName = FString(""));
|
||||
|
||||
private:
|
||||
/**
|
||||
Attempts to start broadcasting the active viewport. The output of the active viewport is the current camera
|
||||
that is actively being viewed (through), and does not have to be an NDI Broadcast Viewport Component.
|
||||
|
||||
@return The result of whether broadcasting the active viewport was started
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO",
|
||||
META = (DisplayName = "Begin Broadcasting Active Viewport", DefaultToSelf = "WorldContextObject",
|
||||
HidePin = "WorldContextObject", AllowPrivateAccess = true))
|
||||
static bool K2_BeginBroadcastingActiveViewport(UObject* WorldContextObject);
|
||||
|
||||
/**
|
||||
Will stop broadcasting the active viewport, which was started by a previous call to 'Begin Broadcasting Active
|
||||
Viewport'
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO",
|
||||
META = (DisplayName = "Stop Broadcasting Active Viewport", DefaultToSelf = "WorldContextObject",
|
||||
HidePin = "WorldContextObject", AllowPrivateAccess = true))
|
||||
static void K2_StopBroadcastingActiveViewport(UObject* WorldContextObject);
|
||||
|
||||
private:
|
||||
/**
|
||||
Returns an NDI Media Receiver object
|
||||
|
||||
@param Receiver The Receiver object to return
|
||||
@return The selected Receiver object
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO",
|
||||
META = (DisplayName = "Get NDI Media Receiver", AllowPrivateAccess = true))
|
||||
static UPARAM(ref) UNDIMediaReceiver* K2_GetNDIMediaReceiver(UNDIMediaReceiver* Receiver = nullptr);
|
||||
|
||||
/**
|
||||
Returns an NDI Media Sender object
|
||||
|
||||
@param Sender The Sender object to return
|
||||
@return The selected Sender object
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO",
|
||||
META = (DisplayName = "Get NDI Media Sender", AllowPrivateAccess = true))
|
||||
static UPARAM(ref) UNDIMediaSender* K2_GetNDIMediaSender(UNDIMediaSender* Sender = nullptr);
|
||||
|
||||
private:
|
||||
/**
|
||||
Parses a string as metadata
|
||||
Blueprints do not support recursive datastructures, so parsing metadata
|
||||
with this will result in only the top-level elements being returned.
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO",
|
||||
META = (DisplayName = "Parse NDI MetaData", AllowPrivateAccess = true))
|
||||
static const TArray<FNDIMetaDataElement> K2_ParseNDIMetaData(FString Data);
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
|
||||
|
||||
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
|
||||
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <CoreMinimal.h>
|
||||
#include <Kismet/BlueprintFunctionLibrary.h>
|
||||
#include <Structures/NDIReceiverPerformanceData.h>
|
||||
|
||||
#include "NDIReceiverPerformanceDataLibrary.generated.h"
|
||||
|
||||
UCLASS(NotBlueprintable, BlueprintType, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI Receiver Performance Data Library"))
|
||||
class NDIIO_API UNDIReceiverPerformanceDataLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
private:
|
||||
/**
|
||||
Returns a value indicating whether the two structures are comparably equal
|
||||
|
||||
@param A The structure used as the source comparator
|
||||
@param B The structure used as the target comparator
|
||||
@return The resulting value of the comparator operator
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "NDI IO",
|
||||
META = (DisplayName = "Equals (NDI Receiver Performance Data)",
|
||||
CompactNodeTitle = "==", Keywords = "= == Equals", AllowPrivateAccess = true))
|
||||
static bool K2_Compare_NDIReceiverPerformanceData(FNDIReceiverPerformanceData A, FNDIReceiverPerformanceData B)
|
||||
{
|
||||
return A == B;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a value indicating whether the two structures are NOT comparably equal
|
||||
|
||||
@param A The structure used as the source comparator
|
||||
@param B The structure used as the target comparator
|
||||
@return The resulting value of the comparator operator
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "NDI IO",
|
||||
META = (DisplayName = "Not Equals (NDI Receiver Performance Data)",
|
||||
CompactNodeTitle = "!=", Keywords = "! != Not Equals", AllowPrivateAccess = true))
|
||||
static bool K2_Compare_Not_NDIReceiverPerformanceData(FNDIReceiverPerformanceData A, FNDIReceiverPerformanceData B)
|
||||
{
|
||||
return A != B;
|
||||
}
|
||||
|
||||
/**
|
||||
Resets the structure's properties to their default values
|
||||
|
||||
@param PerformanceData The structure to reset to the default value
|
||||
@return The reference to the passed in structure after the 'reset' has been completed
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO",
|
||||
META = (DisplayName = "Reset Receiver Performance Data", AllowPrivateAccess = true))
|
||||
static UPARAM(ref) FNDIReceiverPerformanceData& K2_NDIReceiverPerformanceData_Reset(
|
||||
UPARAM(ref) FNDIReceiverPerformanceData& PerformanceData)
|
||||
{
|
||||
// call the underlying function to reset the properties of the object
|
||||
PerformanceData.Reset();
|
||||
|
||||
// return the Performance Data object reference
|
||||
return PerformanceData;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
|
||||
|
||||
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
|
||||
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NDIIOPluginAPI.h>
|
||||
|
||||
#include <UObject/Object.h>
|
||||
#include <Misc/Timecode.h>
|
||||
#include <Misc/FrameRate.h>
|
||||
#include <TimeSynchronizableMediaSource.h>
|
||||
#include <RendererInterface.h>
|
||||
|
||||
#include <Objects/Media/NDIMediaSoundWave.h>
|
||||
#include <Objects/Media/NDIMediaTexture2D.h>
|
||||
#include <Structures/NDIConnectionInformation.h>
|
||||
#include <Structures/NDIReceiverPerformanceData.h>
|
||||
|
||||
#include "NDIMediaReceiver.generated.h"
|
||||
|
||||
|
||||
namespace NDIMediaOption
|
||||
{
|
||||
static const FName IsNDIMediaReceiver("IsNDIMediaReceiver");
|
||||
static const FName MaxVideoFrameBuffer("MaxVideoFrameBuffer");
|
||||
static const FName MaxAudioFrameBuffer("MaxAudioFrameBuffer");
|
||||
static const FName MaxAncillaryFrameBuffer("MaxAncillaryFrameBuffer");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Delegates to notify that the NDIMediaReceiver has received a video, audio, or metadata frame
|
||||
*/
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIMediaReceiverVideoReceived, UNDIMediaReceiver*, Receiver);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIMediaReceiverAudioReceived, UNDIMediaReceiver*, Receiver);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FNDIMediaReceiverMetaDataReceived, UNDIMediaReceiver*, Receiver, FString, Data, bool, bAttachedToVideoFrame);
|
||||
|
||||
|
||||
/**
|
||||
A Media object representing the NDI Receiver for being able to receive Audio, Video, and Metadata over NDI
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable, HideCategories = ("Platforms"), Category = "NDI IO",
|
||||
HideCategories = ("Information"), AutoCollapseCategories = ("Content"),
|
||||
META = (DisplayName = "NDI Media Receiver"))
|
||||
class NDIIO_API UNDIMediaReceiver : public UTimeSynchronizableMediaSource
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
/**
|
||||
Information describing detailed information about the sender this receiver is to connect to
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Settings",
|
||||
META = (DisplayName = "Connection", AllowPrivateAccess = true))
|
||||
FNDIConnectionInformation ConnectionSetting;
|
||||
|
||||
private:
|
||||
/**
|
||||
The current frame count, seconds, minutes, and hours in time-code notation
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Information",
|
||||
META = (DisplayName = "Timecode", AllowPrivateAccess = true))
|
||||
FTimecode Timecode;
|
||||
|
||||
/**
|
||||
The desired number of frames (per second) for video to be displayed
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Information",
|
||||
META = (DisplayName = "Frame Rate", AllowPrivateAccess = true))
|
||||
FFrameRate FrameRate;
|
||||
|
||||
/**
|
||||
The width and height of the last received video frame
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Information",
|
||||
META = (DisplayName = "Resolution", AllowPrivateAccess = true))
|
||||
FIntPoint Resolution;
|
||||
|
||||
/**
|
||||
Indicates whether the timecode should be synced to the Source Timecode value
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Settings",
|
||||
META = (DisplayName = "Sync Timecode to Source", AllowPrivateAccess = true))
|
||||
bool bSyncTimecodeToSource = true;
|
||||
|
||||
/**
|
||||
Should perform the sRGB to Linear color space conversion
|
||||
*/
|
||||
UPROPERTY(BlueprintReadonly, VisibleAnywhere, Category = "Information",
|
||||
META = (DisplayName = "Perform sRGB to Linear?", AllowPrivateAccess = true))
|
||||
bool bPerformsRGBtoLinear = true;
|
||||
|
||||
/**
|
||||
Information describing detailed information about the sender this receiver is currently connected to
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Information",
|
||||
META = (DisplayName = "Connection Information", AllowPrivateAccess = true))
|
||||
FNDIConnectionInformation ConnectionInformation;
|
||||
|
||||
/**
|
||||
Information describing detailed information about the receiver performance when connected to an NDI sender
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Information",
|
||||
META = (DisplayName = "Performance Data", AllowPrivateAccess = true))
|
||||
FNDIReceiverPerformanceData PerformanceData;
|
||||
|
||||
/**
|
||||
Provides an NDI Video Texture object to render videos frames from the source onto (optional)
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, BlueprintSetter = "ChangeVideoTexture", Category = "Content",
|
||||
AdvancedDisplay, META = (DisplayName = "Video Texture (optional)", AllowPrivateAccess = true))
|
||||
UNDIMediaTexture2D* VideoTexture = nullptr;
|
||||
|
||||
public:
|
||||
DECLARE_EVENT_OneParam(FNDIMediaReceiverConnectionEvent, FOnReceiverConnectionEvent,
|
||||
UNDIMediaReceiver*) FOnReceiverConnectionEvent OnNDIReceiverConnectedEvent;
|
||||
DECLARE_EVENT_OneParam(FNDIMediaReceiverDisconnectionEvent, FOnReceiverDisconnectionEvent,
|
||||
UNDIMediaReceiver*) FOnReceiverDisconnectionEvent OnNDIReceiverDisconnectedEvent;
|
||||
|
||||
DECLARE_EVENT_TwoParams(FNDIMediaReceiverVideoCaptureEvent, FOnReceiverVideoCaptureEvent,
|
||||
UNDIMediaReceiver*, const NDIlib_video_frame_v2_t&) FOnReceiverVideoCaptureEvent OnNDIReceiverVideoCaptureEvent;
|
||||
DECLARE_EVENT_TwoParams(FNDIMediaReceiverAudioCaptureEvent, FOnReceiverAudioCaptureEvent,
|
||||
UNDIMediaReceiver*, const NDIlib_audio_frame_v2_t&) FOnReceiverAudioCaptureEvent OnNDIReceiverAudioCaptureEvent;
|
||||
DECLARE_EVENT_TwoParams(FNDIMediaReceiverMetadataCaptureEvent, FOnReceiverMetadataCaptureEvent,
|
||||
UNDIMediaReceiver*, const NDIlib_metadata_frame_t&) FOnReceiverMetadataCaptureEvent OnNDIReceiverMetadataCaptureEvent;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On Video Received by Receiver", AllowPrivateAccess = true))
|
||||
FNDIMediaReceiverVideoReceived OnReceiverVideoReceived;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On Audio Received by Receiver", AllowPrivateAccess = true))
|
||||
FNDIMediaReceiverAudioReceived OnReceiverAudioReceived;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On MetaData Received by Receiver", AllowPrivateAccess = true))
|
||||
FNDIMediaReceiverMetaDataReceived OnReceiverMetaDataReceived;
|
||||
|
||||
public:
|
||||
|
||||
UNDIMediaReceiver();
|
||||
|
||||
/**
|
||||
Called before destroying the object. This is called immediately upon deciding to destroy the object,
|
||||
to allow the object to begin an asynchronous cleanup process.
|
||||
*/
|
||||
void BeginDestroy() override;
|
||||
|
||||
/**
|
||||
Attempts to perform initialization logic for creating a receiver through the NDI sdk api
|
||||
*/
|
||||
enum class EUsage
|
||||
{
|
||||
Standalone, // The receiver automatically captures its own video frame every engine render frame
|
||||
Controlled // The user of the receiver manually triggers capturing a frame through CaptureConnectedVideo/Audio()
|
||||
};
|
||||
bool Initialize(const FNDIConnectionInformation& InConnectionInformation, EUsage InUsage);
|
||||
bool Initialize(EUsage Inusage);
|
||||
|
||||
/**
|
||||
Attempt to (re-)start the connection
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Start Connection"))
|
||||
void StartConnection();
|
||||
|
||||
/**
|
||||
Stop the connection
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Stop Connection"))
|
||||
void StopConnection();
|
||||
|
||||
/**
|
||||
Attempts to change the connection to another NDI sender source
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Change Connection"))
|
||||
void ChangeConnection(const FNDIConnectionInformation& InConnectionInformation);
|
||||
|
||||
/**
|
||||
Attempts to change the Video Texture object used as the video frame capture object
|
||||
*/
|
||||
UFUNCTION(BlueprintSetter)
|
||||
void ChangeVideoTexture(UNDIMediaTexture2D* InVideoTexture = nullptr);
|
||||
|
||||
/**
|
||||
Attempts to generate the pcm data required by the 'AudioWave' object
|
||||
*/
|
||||
int32 GeneratePCMData(UNDIMediaSoundWave* AudioWave, uint8* PCMData, const int32 SamplesNeeded);
|
||||
int32 GetAudioChannels();
|
||||
|
||||
/**
|
||||
Attempts to register a sound wave object with this object
|
||||
*/
|
||||
void RegisterAudioWave(UNDIMediaSoundWave* InAudioWave = nullptr);
|
||||
|
||||
/**
|
||||
This will send a metadata frame to the sender
|
||||
The data is expected to be valid XML
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Send Metadata To Sender"))
|
||||
void SendMetadataFrame(const FString& Data);
|
||||
/**
|
||||
This will send a metadata frame to the sender
|
||||
The data will be formatted as: <Element>ElementData</Element>
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Send Metadata To Sender (Element + Data)"))
|
||||
void SendMetadataFrameAttr(const FString& Element, const FString& ElementData);
|
||||
/**
|
||||
This will send a metadata frame to the sender
|
||||
The data will be formatted as: <Element Key0="Value0" Key1="Value1" Keyn="Valuen"/>
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Send Metadata To Sender (Element + Attributes)"))
|
||||
void SendMetadataFrameAttrs(const FString& Element, const TMap<FString,FString>& Attributes);
|
||||
|
||||
/**
|
||||
This will set the up-stream tally notifications. If no streams are connected, it will automatically
|
||||
send the tally state upon connection
|
||||
*/
|
||||
void SendTallyInformation(const bool& IsOnPreview, const bool& IsOnProgram);
|
||||
|
||||
/**
|
||||
Attempts to immediately stop receiving frames from the connected NDI sender
|
||||
*/
|
||||
void Shutdown();
|
||||
|
||||
/**
|
||||
Remove the AudioWave object from this object (if it was previously registered)
|
||||
|
||||
@param InAudioWave An NDIMediaSoundWave object registered with this object
|
||||
*/
|
||||
void UnregisterAudioWave(UNDIMediaSoundWave* InAudioWave = nullptr);
|
||||
|
||||
/**
|
||||
Updates the DynamicMaterial with the VideoTexture of this object
|
||||
*/
|
||||
void UpdateMaterialTexture(class UMaterialInstanceDynamic* MaterialInstance, FString ParameterName);
|
||||
|
||||
/**
|
||||
Attempts to capture a frame from the connected source. If a new frame is captured, broadcast it to
|
||||
interested receivers through the capture event. Returns true if new data was captured.
|
||||
*/
|
||||
bool CaptureConnectedVideo();
|
||||
bool CaptureConnectedAudio();
|
||||
bool CaptureConnectedMetadata();
|
||||
|
||||
/**
|
||||
Attempts to immediately update the 'VideoTexture' object with the captured video frame
|
||||
*/
|
||||
FTextureRHIRef DisplayFrame(const NDIlib_video_frame_v2_t& video_frame);
|
||||
|
||||
private:
|
||||
void SetIsCurrentlyConnected(bool bConnected);
|
||||
|
||||
/**
|
||||
Attempts to gather the performance metrics of the connection to the remote source
|
||||
*/
|
||||
void GatherPerformanceMetrics();
|
||||
|
||||
public:
|
||||
/**
|
||||
Set whether or not a RGB to Linear conversion is made
|
||||
*/
|
||||
void PerformsRGBToLinearConversion(bool Value);
|
||||
|
||||
/**
|
||||
Returns the current framerate of the connected source
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Get Current Frame Rate"))
|
||||
const FFrameRate& GetCurrentFrameRate() const;
|
||||
|
||||
/**
|
||||
Returns the current resolution of the connected source
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Get Current Resolution"))
|
||||
const FIntPoint& GetCurrentResolution() const;
|
||||
|
||||
/**
|
||||
Returns the current timecode of the connected source
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Get Current Timecode"))
|
||||
const FTimecode& GetCurrentTimecode() const;
|
||||
|
||||
/**
|
||||
Returns the current connection information of the connected source
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Get Current Connection Information"))
|
||||
const FNDIConnectionInformation& GetCurrentConnectionInformation() const;
|
||||
|
||||
/**
|
||||
Returns the current performance data of the receiver while connected to the source
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Get Performance Data"))
|
||||
const FNDIReceiverPerformanceData& GetPerformanceData() const;
|
||||
|
||||
/** Returns a value indicating whether this object is currently connected to the sender source */
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Is Currently Connected"))
|
||||
const bool GetIsCurrentlyConnected() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
Perform the color conversion (if any) and bit copy from the gpu
|
||||
*/
|
||||
FTextureRHIRef DrawProgressiveVideoFrame(FRHICommandListImmediate& RHICmdList, const NDIlib_video_frame_v2_t& Result);
|
||||
FTextureRHIRef DrawProgressiveVideoFrameAlpha(FRHICommandListImmediate& RHICmdList, const NDIlib_video_frame_v2_t& Result);
|
||||
FTextureRHIRef DrawInterlacedVideoFrame(FRHICommandListImmediate& RHICmdList, const NDIlib_video_frame_v2_t& Result);
|
||||
FTextureRHIRef DrawInterlacedVideoFrameAlpha(FRHICommandListImmediate& RHICmdList, const NDIlib_video_frame_v2_t& Result);
|
||||
|
||||
virtual bool Validate() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual FString GetUrl() const override;
|
||||
|
||||
FTextureResource* GetVideoTextureResource() const;
|
||||
FTextureResource* GetInternalVideoTextureResource() const;
|
||||
|
||||
#if WITH_EDITORONLY_DATA
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
#endif
|
||||
|
||||
public:
|
||||
virtual bool GetMediaOption(const FName& Key, bool DefaultValue) const override;
|
||||
virtual int64 GetMediaOption(const FName& Key, int64 DefaultValue) const override;
|
||||
virtual FString GetMediaOption(const FName& Key, const FString& DefaultValue) const override;
|
||||
virtual bool HasMediaOption(const FName& Key) const override;
|
||||
|
||||
private:
|
||||
int64_t LastFrameTimestamp = 0;
|
||||
NDIlib_frame_format_type_e LastFrameFormatType = NDIlib_frame_format_type_max;
|
||||
|
||||
bool bIsCurrentlyConnected = false;
|
||||
|
||||
NDIlib_recv_instance_t p_receive_instance = nullptr;
|
||||
NDIlib_framesync_instance_t p_framesync_instance = nullptr;
|
||||
|
||||
FCriticalSection RenderSyncContext;
|
||||
FCriticalSection AudioSyncContext;
|
||||
FCriticalSection MetadataSyncContext;
|
||||
FCriticalSection ConnectionSyncContext;
|
||||
|
||||
TArray<UNDIMediaSoundWave*> AudioSourceCollection;
|
||||
|
||||
UNDIMediaTexture2D* InternalVideoTexture = nullptr;
|
||||
|
||||
FTextureRHIRef SourceTexture;
|
||||
FTextureRHIRef SourceAlphaTexture;
|
||||
FPooledRenderTargetDesc RenderTargetDescriptor;
|
||||
TRefCountPtr<IPooledRenderTarget> RenderTarget;
|
||||
enum class EDrawMode
|
||||
{
|
||||
Invalid,
|
||||
Progressive,
|
||||
ProgressiveAlpha,
|
||||
Interlaced,
|
||||
InterlacedAlpha
|
||||
};
|
||||
EDrawMode DrawMode = EDrawMode::Invalid;
|
||||
|
||||
FDelegateHandle FrameEndRTHandle;
|
||||
FDelegateHandle VideoCaptureEventHandle;
|
||||
};
|
||||
362
Plugins/NDIIO/Source/Core/Public/Objects/Media/NDIMediaSender.h
Normal file
362
Plugins/NDIIO/Source/Core/Public/Objects/Media/NDIMediaSender.h
Normal file
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
|
||||
|
||||
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
|
||||
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NDIIOPluginAPI.h>
|
||||
|
||||
#include <RendererInterface.h>
|
||||
#include <UObject/Object.h>
|
||||
#include <Misc/FrameRate.h>
|
||||
#include <Engine/TextureRenderTarget2D.h>
|
||||
#include <Sound/SoundSubmix.h>
|
||||
#include <Structures/NDIBroadcastConfiguration.h>
|
||||
#include <Objects/Media/NDIMediaTexture2D.h>
|
||||
#include <BaseMediaSource.h>
|
||||
#include <Misc/EngineVersionComparison.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "NDIMediaSender.generated.h"
|
||||
|
||||
/**
|
||||
A delegate used for notifications on property changes on the NDIMediaSender object
|
||||
*/
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIMediaSenderPropertyChanged, UNDIMediaSender*, Sender);
|
||||
|
||||
/**
|
||||
A delegate used for notifications on the NDIMediaSender object receiving metadata
|
||||
*/
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FNDIMediaSenderMetaDataReceived, UNDIMediaSender*, Sender, FString, Data);
|
||||
|
||||
/**
|
||||
Delegates to notify just before and after the NDIMediaSender sends a video, audio, or metadata frame
|
||||
*/
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIMediaSenderVideoPreSend, UNDIMediaSender*, Sender);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIMediaSenderVideoSent, UNDIMediaSender*, Sender);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIMediaSenderAudioPreSend, UNDIMediaSender*, Sender);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIMediaSenderAudioSent, UNDIMediaSender*, Sender);
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIMediaSenderMetaDataPreSend, UNDIMediaSender*, Sender);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIMediaSenderMetaDataSent, UNDIMediaSender*, Sender);
|
||||
|
||||
/**
|
||||
Defines a media object representing an NDI(R) Sender object. This object is used with the
|
||||
NDI Broadcast Component to send Audio / Video / Metadata to a 'receiving' NDI object.
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable, HideCategories = ("Platforms"), Category = "NDI IO",
|
||||
HideCategories = ("Information"), AutoCollapseCategories = ("Content"),
|
||||
META = (DisplayName = "NDI Sender Object"))
|
||||
class NDIIO_API UNDIMediaSender : public UBaseMediaSource
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
private:
|
||||
/** Describes a user-friendly name of the output stream to differentiate from other output streams on the current
|
||||
* machine */
|
||||
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Broadcast Settings",
|
||||
META = (DisplayName = "Source Name", AllowPrivateAccess = true))
|
||||
FString SourceName = TEXT("Unreal Engine Output");
|
||||
|
||||
/** Describes the output frame size while sending video frame over NDI */
|
||||
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Broadcast Settings",
|
||||
META = (DisplayName = "Frame Size", AllowPrivateAccess = true))
|
||||
FIntPoint FrameSize = FIntPoint(1920, 1080);
|
||||
|
||||
/** Represents the desired number of frames (per second) for video to be sent over NDI */
|
||||
UPROPERTY(BlueprintReadwrite, EditDefaultsOnly, Category = "Broadcast Settings",
|
||||
META = (DisplayName = "Frame Rate", AllowPrivateAccess = true))
|
||||
FFrameRate FrameRate = FFrameRate(60, 1);
|
||||
|
||||
/** Sets whether or not to output an alpha channel */
|
||||
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Broadcast Settings",
|
||||
META = (DisplayName="Output Alpha", AllowPrivateAccess = true))
|
||||
bool OutputAlpha = false;
|
||||
|
||||
UPROPERTY(BlueprintReadonly, VisibleAnywhere, Category = "Broadcast Settings",
|
||||
META = (DisplayName = "Alpha Remap Min", AllowPrivateAccess = true))
|
||||
float AlphaMin = 0.f;
|
||||
|
||||
UPROPERTY(BlueprintReadonly, VisibleAnywhere, Category = "Broadcast Settings",
|
||||
META = (DisplayName = "Alpha Remap Max", AllowPrivateAccess = true))
|
||||
float AlphaMax = 1.f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Broadcast Settings",
|
||||
META = (DisplayName="Enable Audio", AllowPrivateAccess = true))
|
||||
bool bEnableAudio = true;
|
||||
|
||||
/** Sets whether or not to present PTZ capabilities */
|
||||
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Broadcast Settings",
|
||||
META = (DisplayName="Enable PTZ", AllowPrivateAccess = true))
|
||||
bool bEnablePTZ = true;
|
||||
|
||||
/** Indicates the texture to send over NDI (optional) */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Content",
|
||||
AdvancedDisplay, META = (DisplayName = "Render Target (optional)", AllowPrivateAccess = true))
|
||||
UTextureRenderTarget2D* RenderTarget = nullptr;
|
||||
|
||||
/**
|
||||
Should perform the Linear to sRGB color space conversion
|
||||
*/
|
||||
UPROPERTY(BlueprintReadonly, VisibleAnywhere, Category = "Information",
|
||||
META = (DisplayName = "Perform Linear to sRGB?", AllowPrivateAccess = true))
|
||||
bool bPerformLinearTosRGB = true;
|
||||
|
||||
public:
|
||||
UPROPERTY()
|
||||
FNDIMediaSenderPropertyChanged OnBroadcastConfigurationChanged;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On MetaData Received by Sender", AllowPrivateAccess = true))
|
||||
FNDIMediaSenderMetaDataReceived OnSenderMetaDataReceived;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On Before Video Being Sent by Sender", AllowPrivateAccess = true))
|
||||
FNDIMediaSenderVideoPreSend OnSenderVideoPreSend;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On Video Sent by Sender", AllowPrivateAccess = true))
|
||||
FNDIMediaSenderVideoSent OnSenderVideoSent;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On Before Audio Being Sent by Sender", AllowPrivateAccess = true))
|
||||
FNDIMediaSenderAudioPreSend OnSenderAudioPreSend;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On Audio Sent by Sender", AllowPrivateAccess = true))
|
||||
FNDIMediaSenderAudioSent OnSenderAudioSent;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On Before MetaData Being Sent by Sender", AllowPrivateAccess = true))
|
||||
FNDIMediaSenderMetaDataPreSend OnSenderMetaDataPreSend;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On MetaData Sent by Sender", AllowPrivateAccess = true))
|
||||
FNDIMediaSenderMetaDataSent OnSenderMetaDataSent;
|
||||
|
||||
public:
|
||||
/**
|
||||
Attempts to perform initialization logic for creating a sender through the NDI(R) sdk api
|
||||
*/
|
||||
void Initialize(USoundSubmix* SubmixCapture);
|
||||
|
||||
/**
|
||||
Changes the name of the sender object as seen on the network for remote connections
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Change Source Name"))
|
||||
void ChangeSourceName(const FString& InSourceName);
|
||||
|
||||
/**
|
||||
Attempts to change the Broadcast information associated with this media object
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Change Broadcast Configuration"))
|
||||
void ChangeBroadcastConfiguration(const FNDIBroadcastConfiguration& InConfiguration);
|
||||
|
||||
/**
|
||||
This will send a metadata frame to all receivers
|
||||
The data is expected to be valid XML
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Send Metadata To Receivers"))
|
||||
void SendMetadataFrame(const FString& Data, bool AttachToVideoFrame = true);
|
||||
/**
|
||||
This will send a metadata frame to all receivers
|
||||
The data will be formatted as: <Element>ElementData</Element>
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Send Metadata To Receivers (Element + Data)"))
|
||||
void SendMetadataFrameAttr(const FString& Element, const FString& ElementData, bool AttachToVideoFrame = true);
|
||||
/**
|
||||
This will send a metadata frame to all receivers
|
||||
The data will be formatted as: <Element Key0="Value0" Key1="Value1" Keyn="Valuen"/>
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Send Metadata To Receivers (Element + Attributes)"))
|
||||
void SendMetadataFrameAttrs(const FString& Element, const TMap<FString,FString>& Attributes, bool AttachToVideoFrame = true);
|
||||
|
||||
/**
|
||||
Attempts to change the RenderTarget used in sending video frames over NDI
|
||||
*/
|
||||
void ChangeVideoTexture(UTextureRenderTarget2D* VideoTexture = nullptr);
|
||||
|
||||
/**
|
||||
Change the alpha remapping settings
|
||||
*/
|
||||
void ChangeAlphaRemap(float AlphaMinIn, float AlphaMaxIn);
|
||||
|
||||
/**
|
||||
Determines the current tally information. If you specify a timeout then it will wait until it has
|
||||
changed, otherwise it will simply poll it and return the current tally immediately
|
||||
|
||||
@param IsOnPreview - A state indicating whether this source in on preview of a receiver
|
||||
@param IsOnProgram - A state indicating whether this source is on program of a receiver
|
||||
@param TimeOut - Indicates the amount of time to wait (in milliseconds) until a change has occurred
|
||||
*/
|
||||
void GetTallyInformation(bool& IsOnPreview, bool& IsOnProgram, uint32 Timeout = 0);
|
||||
|
||||
/**
|
||||
Gets the current number of receivers connected to this source. This can be used to avoid rendering
|
||||
when nothing is connected to the video source. which can significantly improve the efficiency if
|
||||
you want to make a lot of sources available on the network
|
||||
*/
|
||||
void GetNumberOfConnections(int32& Result);
|
||||
|
||||
/**
|
||||
Attempts to immediately stop sending frames over NDI to any connected receivers
|
||||
*/
|
||||
void Shutdown();
|
||||
|
||||
/**
|
||||
Called before destroying the object. This is called immediately upon deciding to destroy the object,
|
||||
to allow the object to begin an asynchronous cleanup process.
|
||||
*/
|
||||
virtual void BeginDestroy() override;
|
||||
|
||||
/**
|
||||
Set whether or not a RGB to Linear conversion is made
|
||||
*/
|
||||
void PerformLinearTosRGBConversion(bool Value);
|
||||
|
||||
/**
|
||||
Set whether or not to enable PTZ support
|
||||
*/
|
||||
void EnablePTZ(bool Value);
|
||||
|
||||
/**
|
||||
Returns the Render Target used for sending a frame over NDI
|
||||
*/
|
||||
UTextureRenderTarget2D* GetRenderTarget();
|
||||
|
||||
const FIntPoint& GetFrameSize()
|
||||
{
|
||||
return this->FrameSize;
|
||||
}
|
||||
|
||||
const FFrameRate& GetFrameRate()
|
||||
{
|
||||
return this->FrameRate;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool CreateSender();
|
||||
|
||||
/**
|
||||
Attempts to get a metadata frame from the sender.
|
||||
If there is one, the data is broadcast through OnSenderMetaDataReceived.
|
||||
Returns true if metadata was received, false otherwise.
|
||||
*/
|
||||
bool GetMetadataFrame();
|
||||
|
||||
/**
|
||||
This will attempt to generate an audio frame, add the frame to the stack and return immediately,
|
||||
having scheduled the frame asynchronously.
|
||||
*/
|
||||
void TrySendAudioFrame(int64 time_code, float* AudioData, int32 NumSamples, int32 NumChannels, const int32 SampleRate, double AudioClock);
|
||||
|
||||
/**
|
||||
This will attempt to generate a video frame, add the frame to the stack and return immediately,
|
||||
having scheduled the frame asynchronously.
|
||||
*/
|
||||
void TrySendVideoFrame(int64 time_code = 0);
|
||||
|
||||
/**
|
||||
Perform the color conversion (if any) and bit copy from the gpu
|
||||
*/
|
||||
bool DrawRenderTarget(FRHICommandListImmediate& RHICmdList);
|
||||
|
||||
/**
|
||||
Change the render target configuration based on the passed in parameters
|
||||
|
||||
@param InFrameSize The frame size to resize the render target to
|
||||
@param InFrameRate The frame rate at which we should be sending frames via NDI
|
||||
*/
|
||||
void ChangeRenderTargetConfiguration(FIntPoint InFrameSize, FFrameRate InFrameRate);
|
||||
|
||||
virtual bool Validate() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual FString GetUrl() const override
|
||||
{
|
||||
return FString();
|
||||
}
|
||||
|
||||
FTextureResource* GetRenderTargetResource() const;
|
||||
|
||||
void PrepareDefaultTexture();
|
||||
|
||||
private:
|
||||
std::atomic<bool> bIsChangingBroadcastSize { false };
|
||||
|
||||
FTimecode LastRenderTime;
|
||||
|
||||
FTextureRHIRef DefaultVideoTextureRHI;
|
||||
|
||||
TArray<float> SendAudioData;
|
||||
|
||||
NDIlib_video_frame_v2_t NDI_video_frame;
|
||||
NDIlib_send_instance_t p_send_instance = nullptr;
|
||||
|
||||
FCriticalSection AudioSyncContext;
|
||||
FCriticalSection RenderSyncContext;
|
||||
|
||||
/**
|
||||
A texture with CPU readback
|
||||
*/
|
||||
class MappedTexture
|
||||
{
|
||||
private:
|
||||
FTextureRHIRef Texture = nullptr;
|
||||
void* pData = nullptr;
|
||||
std::string MetaData;
|
||||
FIntPoint FrameSize;
|
||||
|
||||
public:
|
||||
~MappedTexture();
|
||||
|
||||
void Create(FIntPoint FrameSize);
|
||||
void Destroy();
|
||||
|
||||
FIntPoint GetSizeXY() const;
|
||||
|
||||
void Resolve(FRHICommandListImmediate& RHICmdList, FRHITexture* SourceTextureRHI, const FResolveRect& Rect = FResolveRect(), const FResolveRect& DestRect = FResolveRect());
|
||||
|
||||
void Map(FRHICommandListImmediate& RHICmdList, int32& OutWidth, int32& OutHeight, int32& OutLineStride);
|
||||
void* MappedData() const;
|
||||
void Unmap(FRHICommandListImmediate& RHICmdList);
|
||||
|
||||
void AddMetaData(const FString& Data);
|
||||
const std::string& GetMetaData() const;
|
||||
|
||||
private:
|
||||
void PrepareTexture();
|
||||
};
|
||||
|
||||
/**
|
||||
Class for managing the sending of mapped texture data to an NDI video stream.
|
||||
Sending is done asynchronously, so mapping and unmapping of texture data must
|
||||
be managed so that CPU accessible texture content remains valid until the
|
||||
sending of the frame is guaranteed to have been completed. This is achieved
|
||||
by double-buffering readback textures.
|
||||
*/
|
||||
class MappedTextureASyncSender
|
||||
{
|
||||
private:
|
||||
MappedTexture MappedTextures[2];
|
||||
int32 CurrentIndex = 0;
|
||||
|
||||
public:
|
||||
void Create(FIntPoint FrameSize);
|
||||
void Destroy();
|
||||
|
||||
FIntPoint GetSizeXY() const;
|
||||
|
||||
void Resolve(FRHICommandListImmediate& RHICmdList, FRHITexture* SourceTextureRHI, const FResolveRect& Rect = FResolveRect(), const FResolveRect& DestRect = FResolveRect());
|
||||
|
||||
void Map(FRHICommandListImmediate& RHICmdList, int32& OutWidth, int32& OutHeight, int32& OutLineStride);
|
||||
void Send(FRHICommandListImmediate& RHICmdList, NDIlib_send_instance_t p_send_instance, NDIlib_video_frame_v2_t& p_video_data);
|
||||
void Flush(FRHICommandListImmediate& RHICmdList, NDIlib_send_instance_t p_send_instance);
|
||||
|
||||
void AddMetaData(const FString& Data);
|
||||
};
|
||||
|
||||
MappedTextureASyncSender ReadbackTextures;
|
||||
bool ReadbackTexturesHaveAlpha = false;
|
||||
FPooledRenderTargetDesc RenderTargetDescriptor;
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
|
||||
|
||||
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
|
||||
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <CoreMinimal.h>
|
||||
#include <Sound/SoundWaveProcedural.h>
|
||||
|
||||
#include "NDIMediaSoundWave.generated.h"
|
||||
|
||||
/**
|
||||
Defines a SoundWave object used by an NDI Media Receiver object for capturing audio from
|
||||
a network source
|
||||
*/
|
||||
UCLASS(NotBlueprintable, Category = "NDI IO", META = (DisplayName = "NDI Media Sound Wave"))
|
||||
class NDIIO_API UNDIMediaSoundWave : public USoundWaveProcedural
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
/**
|
||||
Set the Media Source of this object, so that when this object is called to 'GeneratePCMData' by the engine
|
||||
we can request the media source to provide the pcm data from the current connected source
|
||||
*/
|
||||
void SetConnectionSource(class UNDIMediaReceiver* InMediaSource = nullptr);
|
||||
|
||||
protected:
|
||||
/**
|
||||
Called by the engine to generate pcm data to be 'heard' by audio listener objects
|
||||
*/
|
||||
virtual int32 OnGeneratePCMAudio(TArray<uint8>& OutAudio, int32 NumSamples) override final;
|
||||
|
||||
virtual bool IsReadyForFinishDestroy() override final;
|
||||
|
||||
private:
|
||||
FCriticalSection SyncContext;
|
||||
class UNDIMediaReceiver* MediaSource = nullptr;
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
|
||||
|
||||
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
|
||||
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <CoreMinimal.h>
|
||||
#include <Engine/Texture.h>
|
||||
#include <Misc/EngineVersionComparison.h>
|
||||
#include <RHI.h>
|
||||
#include <RHICommandList.h>
|
||||
|
||||
#include "NDIMediaTexture2D.generated.h"
|
||||
|
||||
/**
|
||||
A Texture Object used by an NDI Media Receiver object for capturing video from
|
||||
a network source
|
||||
*/
|
||||
UCLASS(NotBlueprintType, NotBlueprintable, HideDropdown,
|
||||
HideCategories = (ImportSettings, Compression, Texture, Adjustments, Compositing, LevelOfDetail, Object),
|
||||
META = (DisplayName = "NDI Media Texture 2D"))
|
||||
class NDIIO_API UNDIMediaTexture2D : public UTexture
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
virtual float GetSurfaceHeight() const override;
|
||||
virtual float GetSurfaceWidth() const override;
|
||||
|
||||
virtual float GetSurfaceDepth() const;
|
||||
virtual uint32 GetSurfaceArraySize() const;
|
||||
|
||||
virtual ETextureClass GetTextureClass() const;
|
||||
|
||||
virtual void GetResourceSizeEx(FResourceSizeEx& CumulativeResourceSize) override;
|
||||
virtual EMaterialValueType GetMaterialType() const override;
|
||||
|
||||
virtual void UpdateTextureReference(FRHICommandList& RHICmdList, FTextureRHIRef Reference) final;
|
||||
|
||||
private:
|
||||
virtual class FTextureResource* CreateResource() override;
|
||||
|
||||
void SetMyResource(FTextureResource* ResourceIn);
|
||||
FTextureResource* GetMyResource();
|
||||
const FTextureResource* GetMyResource() const;
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright (C) 2024 Vizrt NDI AB. All rights reserved.
|
||||
|
||||
This file and its use within a Product is bound by the terms of NDI SDK license that was provided
|
||||
as part of the NDI SDK. For more information, please review the license and the NDI SDK documentation.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <CoreMinimal.h>
|
||||
#include <ExternalTexture.h>
|
||||
#include <TextureResource.h>
|
||||
#include <Misc/EngineVersionComparison.h>
|
||||
|
||||
/**
|
||||
A Texture Resource object used by the NDIMediaTexture2D object for capturing video
|
||||
from a network source
|
||||
*/
|
||||
class NDIIO_API FNDIMediaTextureResource : public FTextureResource
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Constructs a new instance of this object specifying a media texture owner
|
||||
|
||||
@param Owner The media object used as the owner for this object
|
||||
*/
|
||||
FNDIMediaTextureResource(class UNDIMediaTexture2D* Owner = nullptr);
|
||||
|
||||
#if (ENGINE_MAJOR_VERSION > 5) || ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 3)) // 5.3 or later
|
||||
/** FTextureResource Interface Implementation for 'InitDynamicRHI' */
|
||||
virtual void InitRHI(FRHICommandListBase& RHICmdList) override;
|
||||
|
||||
/** FTextureResource Interface Implementation for 'ReleaseDynamicRHI' */
|
||||
virtual void ReleaseRHI() override;
|
||||
#else
|
||||
/** FTextureResource Interface Implementation for 'InitDynamicRHI' */
|
||||
virtual void InitDynamicRHI() override;
|
||||
|
||||
/** FTextureResource Interface Implementation for 'ReleaseDynamicRHI' */
|
||||
virtual void ReleaseDynamicRHI() override;
|
||||
#endif
|
||||
|
||||
/** FTextureResource Interface Implementation for 'GetResourceSize' */
|
||||
SIZE_T GetResourceSize();
|
||||
|
||||
/** FTextureResource Interface Implementation for 'GetSizeX' */
|
||||
virtual uint32 GetSizeX() const override;
|
||||
|
||||
/** FTextureResource Interface Implementation for 'GetSizeY' */
|
||||
virtual uint32 GetSizeY() const override;
|
||||
|
||||
private:
|
||||
class UNDIMediaTexture2D* MediaTexture = nullptr;
|
||||
};
|
||||
Reference in New Issue
Block a user