First commit
This commit is contained in:
59
Plugins/NDIIO/Source/Core/Public/Actors/NDIBroadcastActor.h
Normal file
59
Plugins/NDIIO/Source/Core/Public/Actors/NDIBroadcastActor.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
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 <GameFramework/Actor.h>
|
||||
#include <Components/NDIViewportCaptureComponent.h>
|
||||
#include <Components/NDIPTZControllerComponent.h>
|
||||
#include <Sound/SoundSubmix.h>
|
||||
|
||||
#include "NDIBroadcastActor.generated.h"
|
||||
|
||||
/**
|
||||
A quick and easy way to capture the from the perspective of a camera that starts broadcasting the viewport
|
||||
immediate upon 'BeginPlay'
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable, Category = "NDI IO", META = (DisplayName = "NDI Broadcast Actor"))
|
||||
class NDIIO_API ANDIBroadcastActor : public AActor, public IPTZControllableInterface
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
private:
|
||||
/**
|
||||
The NDI Media Sender representing the configuration of the network source to send audio, video, and metadata
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditInstanceOnly, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI Media Source", AllowPrivateAccess = true))
|
||||
UNDIMediaSender* NDIMediaSource = nullptr;
|
||||
|
||||
/**
|
||||
A component used to capture an additional viewport for broadcasting over NDI
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "NDI IO",
|
||||
META = (DisplayName = "Viewport Capture Component", AllowPrivateAccess = true))
|
||||
UNDIViewportCaptureComponent* ViewportCaptureComponent = nullptr;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditInstanceOnly, Category = "NDI IO",
|
||||
META = (DisplayName = "Audio Submix Capture", AllowPrivateAccess = true))
|
||||
USoundSubmix* SubmixCapture = nullptr;
|
||||
|
||||
/**
|
||||
Component used for PTZ control
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "NDI IO",
|
||||
META = (DisplayName = "PTZ Controller", AllowPrivateAccess = true))
|
||||
UPTZController* PTZController = nullptr;
|
||||
|
||||
public:
|
||||
virtual void BeginPlay() override;
|
||||
|
||||
// IPTZControllableInterface
|
||||
virtual FPTZState GetPTZStateFromUE() const override;
|
||||
virtual void SetPTZStateToUE(const FPTZState& PTZState) override;
|
||||
};
|
||||
129
Plugins/NDIIO/Source/Core/Public/Actors/NDIReceiveActor.h
Normal file
129
Plugins/NDIIO/Source/Core/Public/Actors/NDIReceiveActor.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
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 <GameFramework/Actor.h>
|
||||
#include <Components/AudioComponent.h>
|
||||
#include <Components/StaticMeshComponent.h>
|
||||
#include <Components/NDIReceiverComponent.h>
|
||||
#include <Enumerations/NDIAudioChannels.h>
|
||||
|
||||
#include "NDIReceiveActor.generated.h"
|
||||
|
||||
UCLASS(HideCategories = (Activation, Rendering, AssetUserData, Material, Attachment, Actor, Input, Cooking, LOD,
|
||||
StaticMesh, Materials),
|
||||
Category = "NDI IO", META = (DisplayName = "NDI Receive Actor"))
|
||||
class NDIIO_API ANDIReceiveActor : public AActor
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
private:
|
||||
/** The desired width of the frame in cm, represented in the virtual scene */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Interp, BlueprintSetter = "SetFrameWidth", Category = "NDI IO",
|
||||
META = (DisplayName = "Frame Width", AllowPrivateAccess = true))
|
||||
float FrameWidth = 177.778;
|
||||
|
||||
/** The desired height of the frame in cm, represented in the virtual scene */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Interp, BlueprintSetter = "SetFrameHeight", Category = "NDI IO",
|
||||
META = (DisplayName = "Frame Height", AllowPrivateAccess = true))
|
||||
float FrameHeight = 100.0f;
|
||||
|
||||
/**
|
||||
Indicates that this object should play the audio.
|
||||
|
||||
*Note Audio played by this object will be played as a UI sound, and won't normalize the audio
|
||||
if the same 'MediaSource' object is being used as the audio source on multiple receivers.
|
||||
*/
|
||||
UPROPERTY(EditInstanceOnly, BlueprintSetter = "UpdateAudioPlayback", Category = "NDI IO",
|
||||
META = (DisplayName = "Enable Audio Playback?", AllowPrivateAccess = true))
|
||||
bool bEnableAudioPlayback = false;
|
||||
|
||||
UPROPERTY(EditInstanceOnly, BlueprintSetter = "UpdateAudioPlaybackChannels", Category = "NDI IO",
|
||||
META = (DisplayName = "Audio Playback Channels", AllowPrivateAccess = true))
|
||||
ENDIAudioChannels AudioPlaybackChannels = ENDIAudioChannels::Mono;
|
||||
|
||||
/** Enable/disable the use of the color channels (if there are any) */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, BlueprintSetter = "EnableColor", Category = "NDI IO",
|
||||
META = (DisplayName = "Enable Color?", AllowPrivateAccess = true))
|
||||
bool bEnableColor = true;
|
||||
|
||||
/** Enable/disable the use of the alpha channel (if there is one) */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, BlueprintSetter = "EnableAlpha", Category = "NDI IO",
|
||||
META = (DisplayName = "Enable Alpha?", AllowPrivateAccess = true))
|
||||
bool bEnableAlpha = true;
|
||||
|
||||
/** The Receiver object used to get Audio, Video, and Metadata from on the network */
|
||||
UPROPERTY(BlueprintReadWrite, EditInstanceOnly, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI Media Source", AllowPrivateAccess = true))
|
||||
UNDIMediaReceiver* NDIMediaSource = nullptr;
|
||||
|
||||
/** The component used to display the video received from the Media Sender object */
|
||||
UPROPERTY(Transient, META = (DisplayName = "Video Mesh Component"))
|
||||
UStaticMeshComponent* VideoMeshComponent = nullptr;
|
||||
|
||||
/** The component used to play the audio from the NDI Media source */
|
||||
UPROPERTY(BlueprintReadWrite, EditInstanceOnly, Category= "NDI IO", META = (DisplayName = "Audio Component", AllowPrivateAccess = true))
|
||||
UAudioComponent* AudioComponent = nullptr;
|
||||
|
||||
/** The audio sound wave which receives the audio from the NDI Media source */
|
||||
UPROPERTY(Transient, META = (DisplayName = "Soundwave"))
|
||||
UNDIMediaSoundWave* AudioSoundWave = nullptr;
|
||||
|
||||
private:
|
||||
/** The material we are trying to apply to the video mesh */
|
||||
class UMaterialInterface* VideoMaterial = nullptr;
|
||||
|
||||
/** The dynamic material to apply to the plane object of this actor */
|
||||
UPROPERTY()
|
||||
class UMaterialInstanceDynamic* VideoMaterialInstance = nullptr;
|
||||
|
||||
public:
|
||||
virtual void BeginPlay() override;
|
||||
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
virtual void Tick(float DeltaTime) override;
|
||||
|
||||
/**
|
||||
Attempts to set the desired frame size in cm, represented in the virtual scene
|
||||
*/
|
||||
void SetFrameSize(FVector2D InFrameSize);
|
||||
|
||||
/**
|
||||
Returns the current frame size of the 'VideoMeshComponent' for this object
|
||||
*/
|
||||
const FVector2D GetFrameSize() const;
|
||||
|
||||
private:
|
||||
UFUNCTION(BlueprintSetter)
|
||||
void SetFrameHeight(const float& InFrameHeight);
|
||||
|
||||
UFUNCTION(BlueprintSetter)
|
||||
void SetFrameWidth(const float& InFrameWidth);
|
||||
|
||||
UFUNCTION(BlueprintSetter)
|
||||
void UpdateAudioPlayback(const bool& Enabled);
|
||||
|
||||
UFUNCTION(BlueprintSetter)
|
||||
void UpdateAudioPlaybackChannels(const ENDIAudioChannels& Channels);
|
||||
|
||||
UFUNCTION(BlueprintSetter)
|
||||
void EnableColor(const bool& Enabled);
|
||||
|
||||
UFUNCTION(BlueprintSetter)
|
||||
void EnableAlpha(const bool& Enabled);
|
||||
|
||||
#if WITH_EDITORONLY_DATA
|
||||
|
||||
virtual void PreEditChange(FProperty* InProperty) override;
|
||||
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
|
||||
|
||||
#endif
|
||||
|
||||
void ApplyChannelsMode();
|
||||
bool bStoppedForChannelsMode = false;
|
||||
};
|
||||
@@ -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 <GenlockedTimecodeProvider.h>
|
||||
|
||||
#include <Objects/Media/NDIMediaReceiver.h>
|
||||
|
||||
#include "NDITimecodeProvider.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
Timecode provider from an NDI source
|
||||
*/
|
||||
UCLASS(Blueprintable, editinlinenew, meta=(DisplayName="NDI Timecode Provider"))
|
||||
class NDIIO_API UNDITimecodeProvider : public UGenlockedTimecodeProvider
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
private:
|
||||
/** The Receiver object used to get timecodes from */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI Media Source", AllowPrivateAccess = true))
|
||||
UNDIMediaReceiver* NDIMediaSource = nullptr;
|
||||
|
||||
public:
|
||||
//~ UTimecodeProvider interface
|
||||
virtual bool FetchTimecode(FQualifiedFrameTime& OutFrameTime) override;
|
||||
virtual ETimecodeProviderSynchronizationState GetSynchronizationState() const override;
|
||||
virtual bool Initialize(class UEngine* InEngine) override;
|
||||
virtual void Shutdown(class UEngine* InEngine) override;
|
||||
|
||||
//~ UObject interface
|
||||
virtual void BeginDestroy() override;
|
||||
|
||||
private:
|
||||
void ReleaseResources();
|
||||
|
||||
private:
|
||||
FDelegateHandle VideoCaptureEventHandle;
|
||||
FDelegateHandle ConnectedEventHandle;
|
||||
FDelegateHandle DisconnectedEventHandle;
|
||||
|
||||
mutable FCriticalSection StateSyncContext;
|
||||
ETimecodeProviderSynchronizationState State = ETimecodeProviderSynchronizationState::Closed;
|
||||
FQualifiedFrameTime MostRecentFrameTime;
|
||||
};
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
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 <Components/ActorComponent.h>
|
||||
#include <Objects/Media/NDIMediaSender.h>
|
||||
#include <Structures/NDIBroadcastConfiguration.h>
|
||||
|
||||
#include "NDIBroadcastComponent.generated.h"
|
||||
|
||||
/**
|
||||
Provides a wrapper to allow you to modify an NDI Media Sender object from blueprints and perform broadcasting
|
||||
functionality
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI Broadcast Component", BlueprintSpawnableComponent))
|
||||
class NDIIO_API UNDIBroadcastComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
private:
|
||||
/** The NDI Media Sender representing the configuration of the network source to send audio, video, and metadata */
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Properties",
|
||||
META = (DisplayName = "NDI Media Source", AllowPrivateAccess = true))
|
||||
UNDIMediaSender* NDIMediaSource = nullptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
Initialize this component with the media source required for sending NDI audio, video, and metadata.
|
||||
Returns false, if the MediaSource is already been set. This is usually the case when this component is
|
||||
initialized in Blueprints.
|
||||
*/
|
||||
bool Initialize(UNDIMediaSender* InMediaSource = nullptr);
|
||||
|
||||
/**
|
||||
Attempts to start broadcasting audio, video, and metadata via the 'NDIMediaSource' associated with this object
|
||||
|
||||
@param ErrorMessage The error message received when the media source is unable to start broadcasting
|
||||
@result Indicates whether this object successfully started broadcasting
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Start Broadcasting"))
|
||||
bool StartBroadcasting(FString& ErrorMessage);
|
||||
|
||||
/**
|
||||
Changes the name of the sender object as seen on the network for remote connections
|
||||
|
||||
@param InSourceName The new name of the source to be identified as on the network
|
||||
*/
|
||||
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
|
||||
|
||||
@param InConfiguration The new configuration to broadcast
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Change Broadcast Configuration"))
|
||||
void ChangeBroadcastConfiguration(const FNDIBroadcastConfiguration& InConfiguration);
|
||||
|
||||
/**
|
||||
Attempts to change the RenderTarget used in sending video frames over NDI
|
||||
|
||||
@param BroadcastTexture The texture to use as video, while broadcasting over NDI
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Change Broadcast Texture"))
|
||||
void ChangeBroadcastTexture(UTextureRenderTarget2D* BroadcastTexture = nullptr);
|
||||
|
||||
/**
|
||||
Determines the current tally information.
|
||||
|
||||
@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
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Get Tally Information"))
|
||||
void GetTallyInformation(bool& IsOnPreview, bool& IsOnProgram);
|
||||
|
||||
/**
|
||||
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
|
||||
|
||||
@param Result The total number of connected receivers attached to the broadcast of this object
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Get Number of Connections"))
|
||||
void GetNumberOfConnections(int32& Result);
|
||||
|
||||
/**
|
||||
Attempts to immediately stop sending frames over NDI to any connected receivers
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Stop Broadcasting"))
|
||||
void StopBroadcasting();
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
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 <Components/ActorComponent.h>
|
||||
#include <Structures/NDIConnectionInformation.h>
|
||||
|
||||
#include "NDIFinderComponent.generated.h"
|
||||
|
||||
/** Delegates **/
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIFinderServiceCollectionChangedDelegate, UNDIFinderComponent*,
|
||||
InComponent);
|
||||
|
||||
/** ******************* **/
|
||||
|
||||
/**
|
||||
A component used for essential functionality when dealing with the finder service. Allowing you to
|
||||
get a collection of sources found on the network.
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI Finder Component", BlueprintSpawnableComponent))
|
||||
class NDIIO_API UNDIFinderComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
/** A collection of the current sources and their information, found on the network */
|
||||
UPROPERTY()
|
||||
TArray<FNDIConnectionInformation> NetworkSourceCollection;
|
||||
|
||||
/** A delegate which is broadcast when any change to the network source collection has been detected */
|
||||
UPROPERTY(BlueprintAssignable, META = (DisplayName = "On Network Sources Changed", AllowPrivateAccess = true))
|
||||
FNDIFinderServiceCollectionChangedDelegate OnNetworkSourcesChanged;
|
||||
|
||||
public:
|
||||
/**
|
||||
Attempts to find a network source by the supplied name.
|
||||
|
||||
@param ConnectionInformation An existing source information structure which contains the source name
|
||||
@param InSourceName A string value representing the name of the source to find
|
||||
@result A value indicating whether a source with the supplied name was found
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Find Network Source by Name"))
|
||||
const bool FindNetworkSourceByName(FNDIConnectionInformation& ConnectionInformation,
|
||||
FString InSourceName = FString(""));
|
||||
|
||||
/**
|
||||
Returns the current collection of sources found on the network
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category = "NDI IO", META = (DisplayName = "Get Network Sources"))
|
||||
const TArray<FNDIConnectionInformation> GetNetworkSources();
|
||||
|
||||
protected:
|
||||
virtual void BeginPlay() override;
|
||||
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||
|
||||
/** An override function for when the network source collection has been changed */
|
||||
UFUNCTION(BlueprintImplementableEvent, META = (DisplayName = "On Network Sources Changed Event"))
|
||||
void OnNetworkSourcesChangedEvent();
|
||||
|
||||
private:
|
||||
/**
|
||||
An Event handler for when the NDI Finder Service notifies listeners that changes have been
|
||||
detected in the network source collection
|
||||
*/
|
||||
UFUNCTION()
|
||||
virtual void OnNetworkSourceCollectionChangedEvent() final;
|
||||
|
||||
private:
|
||||
FCriticalSection CollectionSyncContext;
|
||||
};
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
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 <UObject/Interface.h>
|
||||
#include <Components/ActorComponent.h>
|
||||
#include <Objects/Media/NDIMediaSender.h>
|
||||
|
||||
#include "NDIPTZControllerComponent.generated.h"
|
||||
|
||||
|
||||
USTRUCT(BlueprintType, Blueprintable, Category = "NDI IO", META = (DisplayName = "NDI PTZ State"))
|
||||
struct NDIIO_API FPTZState
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PTZ")
|
||||
float Pan;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PTZ")
|
||||
float Tilt;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PTZ")
|
||||
float FieldOfView;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PTZ")
|
||||
float FocusDistance;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PTZ")
|
||||
bool bAutoFocus;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PTZ")
|
||||
FTransform CameraTransform;
|
||||
|
||||
FPTZState()
|
||||
: Pan(0.f)
|
||||
, Tilt(0.f)
|
||||
, FieldOfView(90.f)
|
||||
, FocusDistance(0.5f)
|
||||
, bAutoFocus(false)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FNDIEventDelegate_OnPTZPanTiltSpeed, float, PanSpeed, float, TiltSpeed);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIEventDelegate_OnPTZZoomSpeed, float, ZoomSpeed);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FNDIEventDelegate_OnPTZFocus, bool, AutoMode, float, Distance);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIEventDelegate_OnPTZStore, int, Index);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIEventDelegate_OnPTZRecall, int, Index);
|
||||
|
||||
|
||||
|
||||
UINTERFACE(BlueprintType, Blueprintable, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI PTZ Controllable", BlueprintSpawnableComponent))
|
||||
class NDIIO_API UPTZControllableInterface : public UInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
};
|
||||
|
||||
class IPTZControllableInterface
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
virtual FPTZState GetPTZStateFromUE() const = 0;
|
||||
virtual void SetPTZStateToUE(const FPTZState& PTZState) = 0;
|
||||
};
|
||||
|
||||
|
||||
UCLASS(BlueprintType, Blueprintable, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI PTZ Controller", BlueprintSpawnableComponent))
|
||||
class UPTZController : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Enable PTZ", AllowPrivateAccess = true), Category="PTZ")
|
||||
bool EnablePTZ = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Pan Limit", AllowPrivateAccess = true), Category="PTZ")
|
||||
bool PTZWithPanLimit = false;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Pan Min Limit", UIMin="-180", UIMax="180", AllowPrivateAccess = true), Category="PTZ")
|
||||
float PTZPanMinLimit = -180.f;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Pan Max Limit", UIMin="-180", UIMax="180", AllowPrivateAccess = true), Category="PTZ")
|
||||
float PTZPanMaxLimit = 180.f;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Invert Pan", AllowPrivateAccess = true), Category="PTZ")
|
||||
bool bPTZPanInvert = true;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Tilt Limit", AllowPrivateAccess = true), Category="PTZ")
|
||||
bool PTZWithTiltLimit = true;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Tilt Min Limit", UIMin="-180", UIMax="180", AllowPrivateAccess = true), Category="PTZ")
|
||||
float PTZTiltMinLimit = -90.f;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Tilt Max Limit", UIMin="-180", UIMax="180", AllowPrivateAccess = true), Category="PTZ")
|
||||
float PTZTiltMaxLimit = 90.f;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Invert Tilt", AllowPrivateAccess = true), Category="PTZ")
|
||||
bool bPTZTiltInvert = false;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Field of View Limit", AllowPrivateAccess = true), Category="PTZ")
|
||||
bool PTZWithFoVLimit = false;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Field of View Min Limit", UIMin="5", UIMax="170", AllowPrivateAccess = true), Category="PTZ")
|
||||
float PTZFoVMinLimit = 5.f;
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Field of View Max Limit", UIMin="5", UIMax="170", AllowPrivateAccess = true), Category="PTZ")
|
||||
float PTZFoVMaxLimit = 170.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Preset Recall Easing", UIMin="0", UIMax="60", AllowPrivateAccess = true), Category="PTZ")
|
||||
float PTZRecallEasing = 2.f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, meta=(AllowPrivateAccess = true), Category="PTZ")
|
||||
float PTZPanSpeed = 0.f;
|
||||
UPROPERTY(BlueprintReadWrite, meta=(AllowPrivateAccess = true), Category="PTZ")
|
||||
float PTZTiltSpeed = 0.f;
|
||||
UPROPERTY(BlueprintReadWrite, meta=(AllowPrivateAccess = true), Category="PTZ")
|
||||
float PTZZoomSpeed = 0.f;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="PTZ Presets", AllowPrivateAccess = true), Category="PTZ")
|
||||
TArray<FPTZState> PTZStoredStates;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditInstanceOnly, Category = "NDI IO", META = (DisplayName = "NDI Media Source", AllowPrivateAccess = true))
|
||||
UNDIMediaSender* NDIMediaSource = nullptr;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On PTZ Pan Tilt Speed", AllowPrivateAccess = true))
|
||||
FNDIEventDelegate_OnPTZPanTiltSpeed OnPTZPanTiltSpeed;
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On PTZ Zoom Speed", AllowPrivateAccess = true))
|
||||
FNDIEventDelegate_OnPTZZoomSpeed OnPTZZoomSpeed;
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On PTZ Focus", AllowPrivateAccess = true))
|
||||
FNDIEventDelegate_OnPTZFocus OnPTZFocus;
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On PTZ Store", AllowPrivateAccess = true))
|
||||
FNDIEventDelegate_OnPTZStore OnPTZStore;
|
||||
UPROPERTY(BlueprintAssignable, Category="NDI Events", META = (DisplayName = "On PTZ Recall", AllowPrivateAccess = true))
|
||||
FNDIEventDelegate_OnPTZRecall OnPTZRecall;
|
||||
|
||||
public:
|
||||
/** Call with the PTZ metadata received from an NDI media sender */
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Receive Metadata From Sender"))
|
||||
void ReceiveMetaDataFromSender(UNDIMediaSender* Sender, FString Data);
|
||||
|
||||
public:
|
||||
UPTZController();
|
||||
virtual ~UPTZController();
|
||||
|
||||
/**
|
||||
Initialize this component with the required media source to receive metadata from.
|
||||
Returns false, if the MediaSource is already been set. This is usually the case when this component is
|
||||
initialized in Blueprints.
|
||||
*/
|
||||
bool Initialize(UNDIMediaSender* InMediaSource = nullptr);
|
||||
|
||||
void SetPTZPanTiltSpeed(float PanSpeed, float TiltSpeed);
|
||||
void SetPTZZoomSpeed(float ZoomSpeed);
|
||||
void SetPTZFocus(bool AutoMode, float Distance);
|
||||
void StorePTZState(int Index);
|
||||
void RecallPTZState(int Index);
|
||||
|
||||
FPTZState GetPTZStateFromUE() const;
|
||||
void SetPTZStateToUE(const FPTZState& PTZState);
|
||||
|
||||
protected:
|
||||
virtual void InitializeComponent() override;
|
||||
|
||||
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
protected:
|
||||
TSharedPtr<class NDIXmlParser> NDIMetadataParser;
|
||||
|
||||
struct FPTZStateInterp
|
||||
{
|
||||
FPTZState PTZTargetState;
|
||||
float EasingDuration { 0 };
|
||||
float EasingRemaining { 0 };
|
||||
};
|
||||
FPTZStateInterp PTZStateInterp;
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
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 <Components/ActorComponent.h>
|
||||
#include <Structures/NDIConnectionInformation.h>
|
||||
#include <Objects/Media/NDIMediaReceiver.h>
|
||||
|
||||
#include "NDIReceiverComponent.generated.h"
|
||||
|
||||
/**
|
||||
A component used to receive audio, video, and metadata over NDI
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI Receiver Component", BlueprintSpawnableComponent))
|
||||
class NDIIO_API UNDIReceiverComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
private:
|
||||
/** The NDI Media Receiver representing the configuration of the network source to receive audio, video, and
|
||||
* metadata from */
|
||||
UPROPERTY(EditDefaultsOnly, Category = "Properties",
|
||||
META = (DisplayName = "NDI Media Source", AllowPrivateAccess = true))
|
||||
UNDIMediaReceiver* NDIMediaSource = nullptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
Initialize this component with the media source required for receiving NDI audio, video, and metadata.
|
||||
Returns false, if the MediaSource is already been set. This is usually the case when this component is
|
||||
initialized in Blueprints.
|
||||
*/
|
||||
bool Initialize(UNDIMediaReceiver* InMediaSource = nullptr);
|
||||
|
||||
/**
|
||||
Begin receiving NDI audio, video, and metadata frames
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Start Receiver"))
|
||||
bool StartReceiver(const FNDIConnectionInformation& InConnectionInformation);
|
||||
|
||||
/**
|
||||
Attempt to change the connection for which to get audio, video, and metadata frame from
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Change Connection"))
|
||||
void ChangeConnection(const FNDIConnectionInformation& InConnectionInformation);
|
||||
|
||||
/**
|
||||
This will add a metadata frame and return immediately, having scheduled the frame asynchronously
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Send Metadata Frame"))
|
||||
void SendMetadataFrame(const FString& metadata);
|
||||
|
||||
/**
|
||||
This will setup the up-stream tally notifications. If no streams are connected, it will automatically send
|
||||
the tally state upon connection
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Send Tally Information"))
|
||||
void SendTallyInformation(const bool& IsOnPreview, const bool& IsOnProgram);
|
||||
|
||||
/**
|
||||
Attempts to stop receiving audio, video, and metadata frame from the connected source
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Shutdown Receiver"))
|
||||
void ShutdownReceiver();
|
||||
|
||||
public:
|
||||
/**
|
||||
Returns the current framerate of the connected source
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Get Current Frame Rate"))
|
||||
FFrameRate GetCurrentFrameRate() const;
|
||||
|
||||
/**
|
||||
Returns the current timecode of the connected source
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Get Current Timecode"))
|
||||
FTimecode GetCurrentTimecode() const;
|
||||
|
||||
/**
|
||||
Returns the current connection information of the connected source
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Get Current Connection Information"))
|
||||
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"))
|
||||
FNDIReceiverPerformanceData GetPerformanceData() const;
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
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 <UObject/UnrealType.h>
|
||||
#include <Objects/Media/NDIMediaSender.h>
|
||||
#include <Components/ActorComponent.h>
|
||||
|
||||
#include "NDITriCasterExtComponent.generated.h"
|
||||
|
||||
|
||||
USTRUCT(BlueprintType, Blueprintable, Category = "NDI IO", META = (DisplayName = "NDI TricasterExt"))
|
||||
struct NDIIO_API FTriCasterExt
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="TricasterExt")
|
||||
FString Value;
|
||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="TricasterExt")
|
||||
TMap<FName,FString> KeyValues;
|
||||
};
|
||||
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_FiveParams(FNDIEventDelegate_OnTriCasterExt, AActor*, Actor, UObject*, Object, FString, PropertyElementName, FString, PropertyValueStr, FTimespan, EasingDuration);
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FNDIEventDelegate_OnTriCasterExtCustom, const FTriCasterExt&, TCData);
|
||||
|
||||
|
||||
UCLASS(BlueprintType, Blueprintable, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI TricasterExt Component", BlueprintSpawnableComponent))
|
||||
class UTriCasterExtComponent : public UActorComponent
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
protected:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta=(DisplayName="Enable TricasterExt", AllowPrivateAccess = true), Category="TricasterExt")
|
||||
bool EnableTriCasterExt = true;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditInstanceOnly, Category = "NDI IO", META = (DisplayName = "NDI Media Source", AllowPrivateAccess = true))
|
||||
UNDIMediaSender* NDIMediaSource = nullptr;
|
||||
|
||||
UPROPERTY(BlueprintAssignable, BlueprintCallable, Category="NDI Events", META = (DisplayName = "On TricasterExt", AllowPrivateAccess = true))
|
||||
FNDIEventDelegate_OnTriCasterExt OnTriCasterExt;
|
||||
UPROPERTY(BlueprintAssignable, BlueprintCallable, Category="NDI Events", META = (DisplayName = "On TricasterExt Custom", AllowPrivateAccess = true))
|
||||
FNDIEventDelegate_OnTriCasterExtCustom OnTriCasterExtCustom;
|
||||
|
||||
public:
|
||||
/** Call with the TriCasterExt metadata received from an NDI media sender */
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Receive Metadata From Sender"))
|
||||
void ReceiveMetaDataFromSender(UNDIMediaSender* Sender, FString Data);
|
||||
|
||||
public:
|
||||
UTriCasterExtComponent();
|
||||
virtual ~UTriCasterExtComponent();
|
||||
|
||||
/**
|
||||
Initialize this component with the required media source to receive metadata from.
|
||||
Returns false, if the MediaSource is already been set. This is usually the case when this component is
|
||||
initialized in Blueprints.
|
||||
*/
|
||||
bool Initialize(UNDIMediaSender* InMediaSource = nullptr);
|
||||
|
||||
void TriCasterExt(AActor* Actor, UObject* Object, FProperty* Property, FString PropertyElementName, FString PropertyValueStr, FTimespan EasingDuration);
|
||||
void TriCasterExtCustom(const FTriCasterExt& TCData);
|
||||
|
||||
protected:
|
||||
virtual void InitializeComponent() override;
|
||||
|
||||
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
|
||||
|
||||
protected:
|
||||
TSharedPtr<class NDIXmlParser> NDIMetadataParser;
|
||||
|
||||
struct FTriCasterExtInterp
|
||||
{
|
||||
AActor* Actor;
|
||||
UObject* Object;
|
||||
FProperty* Property;
|
||||
FString PropertyElementName;
|
||||
FString PropertyValueStr;
|
||||
float EasingDuration;
|
||||
|
||||
float EasingRemaining;
|
||||
};
|
||||
TArray<FTriCasterExtInterp> TriCasterExtInterp;
|
||||
};
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
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 <CineCameraComponent.h>
|
||||
#include <Engine/TextureRenderTarget2D.h>
|
||||
#include <Components/SceneCaptureComponent2D.h>
|
||||
#include <Objects/Media/NDIMediaSender.h>
|
||||
#include <Misc/FrameRate.h>
|
||||
#include <Framework/Application/SlateApplication.h>
|
||||
#include <SceneManagement.h>
|
||||
#include <Slate/SceneViewport.h>
|
||||
#include <Widgets/SViewport.h>
|
||||
#include <Widgets/SWindow.h>
|
||||
|
||||
#include "NDIViewportCaptureComponent.generated.h"
|
||||
|
||||
|
||||
/**
|
||||
A component used to capture an additional viewport for broadcasting over NDI
|
||||
*/
|
||||
UCLASS(BlueprintType, Blueprintable, Category = "NDI IO",
|
||||
META = (DisplayName = "NDI Viewport Capture Component", BlueprintSpawnableComponent))
|
||||
class NDIIO_API UNDIViewportCaptureComponent : public USceneCaptureComponent2D
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
private:
|
||||
/**
|
||||
If true, will allow you to override the capture settings by ignoring the default Broadcast Settings
|
||||
in the NDI Media Sender, Potentially Requiring a texture rescale of the capture frame when broadcasting
|
||||
over NDI.
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Capture Settings", META = (AllowPrivateAccess = true))
|
||||
bool bOverrideBroadcastSettings = false;
|
||||
|
||||
/**
|
||||
Describes the Height and Width of the viewport frame to capture.
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Capture Settings",
|
||||
META = (DisplayName = "Capture Size", AllowPrivateAccess = true,
|
||||
EditCondition = "bOverrideBroadcastSettings"))
|
||||
FIntPoint CaptureSize = FIntPoint(1280, 720);
|
||||
|
||||
/**
|
||||
Represents the desired number of frames (per second) to capture the viewport
|
||||
*/
|
||||
UPROPERTY(BlueprintReadwrite, EditAnywhere, Category = "Capture Settings",
|
||||
META = (DisplayName = "Capture Rate", AllowPrivateAccess = true,
|
||||
EditCondition = "bOverrideBroadcastSettings"))
|
||||
FFrameRate CaptureRate = FFrameRate(60, 1);
|
||||
|
||||
/**
|
||||
The NDI Media Sender representing the configuration of the network source to send audio, video, and metadata
|
||||
*/
|
||||
UPROPERTY(BlueprintReadWrite, EditDefaultsOnly, Category = "Properties",
|
||||
META = (DisplayName = "NDI Media Source", AllowPrivateAccess = true))
|
||||
UNDIMediaSender* NDIMediaSource = nullptr;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Capture Settings",
|
||||
META = (DisplayName = "Alpha Remap Min", AllowPrivateAccess = true))
|
||||
float AlphaMin = 0.f;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Capture Settings",
|
||||
META = (DisplayName = "Alpha Remap Max", AllowPrivateAccess = true))
|
||||
float AlphaMax = 1.f;
|
||||
|
||||
public:
|
||||
/**
|
||||
Initialize this component with the media source required for sending NDI audio, video, and metadata.
|
||||
Returns false, if the MediaSource is already been set. This is usually the case when this component is
|
||||
initialized in Blueprints.
|
||||
*/
|
||||
bool Initialize(UNDIMediaSender* InMediaSource = nullptr);
|
||||
|
||||
/**
|
||||
Changes the name of the sender object as seen on the network for remote connections
|
||||
|
||||
@param InSourceName The new name of the source to be identified as on the network
|
||||
*/
|
||||
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
|
||||
|
||||
@param InConfiguration The new configuration to broadcast
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Change Broadcast Configuration"))
|
||||
void ChangeBroadcastConfiguration(const FNDIBroadcastConfiguration& InConfiguration);
|
||||
|
||||
/**
|
||||
Attempts to change the RenderTarget used in sending video frames over NDI
|
||||
|
||||
@param BroadcastTexture The texture to use as video, while broadcasting over NDI
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Change Broadcast Texture"))
|
||||
void ChangeBroadcastTexture(UTextureRenderTarget2D* BroadcastTexture = nullptr);
|
||||
|
||||
/**
|
||||
Change the capture settings of the viewport capture and overrides the NDI Media Sender settings
|
||||
|
||||
@param InCaptureSize The Capture size of the frame to capture of the viewport
|
||||
@param InCaptureRate A framerate at which to capture frames of the viewport
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Change Capture Settings"))
|
||||
void ChangeCaptureSettings(FIntPoint InCaptureSize, FFrameRate InCaptureRate);
|
||||
|
||||
/**
|
||||
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
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Get Tally Information"))
|
||||
void GetTallyInformation(bool& IsOnPreview, bool& IsOnProgram);
|
||||
|
||||
/**
|
||||
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
|
||||
|
||||
@param Result The total number of connected receivers attached to the broadcast of this object
|
||||
*/
|
||||
UFUNCTION(BlueprintCallable, Category = "NDI IO", META = (DisplayName = "Get Number of Connections"))
|
||||
void GetNumberOfConnections(int32& Result);
|
||||
|
||||
protected:
|
||||
virtual ~UNDIViewportCaptureComponent();
|
||||
|
||||
virtual void InitializeComponent() override;
|
||||
virtual void UninitializeComponent() override;
|
||||
|
||||
#if (ENGINE_MAJOR_VERSION > 5) || ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 6)) // 5.6 or later
|
||||
virtual void UpdateSceneCaptureContents(FSceneInterface* Scene, ISceneRenderBuilder& SceneRenderBuilder) override;
|
||||
#else
|
||||
virtual void UpdateSceneCaptureContents(FSceneInterface* Scene) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
UFUNCTION()
|
||||
void OnBroadcastConfigurationChanged(UNDIMediaSender* Sender);
|
||||
|
||||
private:
|
||||
FCriticalSection UpdateRenderContext;
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
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 "NDIAudioChannels.generated.h"
|
||||
|
||||
/**
|
||||
Receiver Bandwidth modes
|
||||
*/
|
||||
UENUM(BlueprintType, META = (DisplayName = "NDI Audio Channels"))
|
||||
enum class ENDIAudioChannels : uint8
|
||||
{
|
||||
/** Mono. */
|
||||
Mono = 0x00 UMETA(DisplayName = "Mono"),
|
||||
|
||||
/** Stereo. */
|
||||
Stereo = 0x01 UMETA(DisplayName = "Stereo"),
|
||||
|
||||
/** Whatever the number of channels in the source is. */
|
||||
Source = 0x02 UMETA(DisplayName = "Source"),
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
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 "NDISourceBandwidth.generated.h"
|
||||
|
||||
/**
|
||||
Receiver Bandwidth modes
|
||||
*/
|
||||
UENUM(BlueprintType, META = (DisplayName = "NDI Source Bandwidth"))
|
||||
enum class ENDISourceBandwidth : uint8
|
||||
{
|
||||
/** Receive metadata. */
|
||||
MetadataOnly = 0x00 UMETA(DisplayName = "Metadata Only"),
|
||||
|
||||
/** Receive metadata, audio */
|
||||
AudioOnly = 0x01 UMETA(DisplayName = "Audio Only"),
|
||||
|
||||
/** Receive metadata, audio, video at a lower bandwidth and resolution. */
|
||||
Lowest = 0x02 UMETA(DisplayName = "Lowest"),
|
||||
|
||||
// Receive metadata, audio, video at full resolution.
|
||||
Highest = 0x03 UMETA(DisplayName = "Highest")
|
||||
};
|
||||
34
Plugins/NDIIO/Source/Core/Public/NDIIOPluginAPI.h
Normal file
34
Plugins/NDIIO/Source/Core/Public/NDIIOPluginAPI.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
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 <vector>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#include <Windows/AllowWindowsPlatformTypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef NDI_SDK_ENABLED
|
||||
#error NDI(R) 6.x Runtime must be installed for the NDI(R) IO plugin to run properly.
|
||||
#endif
|
||||
|
||||
#ifdef NDI_SDK_ENABLED
|
||||
#include <Processing.NDI.Lib.h>
|
||||
#include <Processing.NDI.Lib.cplusplus.h>
|
||||
#endif
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#include <Windows/HideWindowsPlatformTypes.h>
|
||||
#endif
|
||||
|
||||
#define NDIIO_MODULE_NAME FName(TEXT("NDIIO"))
|
||||
61
Plugins/NDIIO/Source/Core/Public/NDIIOPluginModule.h
Normal file
61
Plugins/NDIIO/Source/Core/Public/NDIIOPluginModule.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
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 <vector>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <chrono>
|
||||
|
||||
#include <Engine/World.h>
|
||||
#include <Interfaces/IPluginManager.h>
|
||||
#include <Modules/ModuleManager.h>
|
||||
#include <IMediaPlayerFactory.h>
|
||||
|
||||
#include <NDIIOPluginSettings.h>
|
||||
|
||||
class NDIIO_API FNDIIOPluginModule
|
||||
: public IModuleInterface
|
||||
, public IMediaPlayerFactory
|
||||
{
|
||||
public:
|
||||
/** IModuleInterface implementation */
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
/** IMediaPlayerFactory implementation */
|
||||
virtual bool CanPlayUrl(const FString& Url, const IMediaOptions* /*Options*/, TArray<FText>* /*OutWarnings*/, TArray<FText>* OutErrors) const override;
|
||||
virtual TSharedPtr<IMediaPlayer, ESPMode::ThreadSafe> CreatePlayer(IMediaEventSink& EventSink) override;
|
||||
virtual FText GetDisplayName() const override;
|
||||
virtual FName GetPlayerName() const override;
|
||||
virtual FGuid GetPlayerPluginGUID() const override;
|
||||
virtual const TArray<FString>& GetSupportedPlatforms() const override;
|
||||
virtual bool SupportsFeature(EMediaFeature Feature) const override;
|
||||
|
||||
|
||||
bool BeginBroadcastingActiveViewport();
|
||||
void StopBroadcastingActiveViewport();
|
||||
|
||||
private:
|
||||
bool LoadModuleDependencies();
|
||||
void ShutdownModuleDependencies();
|
||||
|
||||
private:
|
||||
TSharedPtr<class FNDIFinderService> NDIFinderService = nullptr;
|
||||
TSharedPtr<class FNDIConnectionService> NDIConnectionService = nullptr;
|
||||
|
||||
void* NDI_LIB_HANDLE = nullptr;
|
||||
|
||||
/** List of platforms that the media player support. */
|
||||
TArray<FString> SupportedPlatforms;
|
||||
|
||||
/** List of supported URI schemes. */
|
||||
TArray<FString> SupportedUriSchemes;
|
||||
};
|
||||
52
Plugins/NDIIO/Source/Core/Public/NDIIOPluginSettings.h
Normal file
52
Plugins/NDIIO/Source/Core/Public/NDIIOPluginSettings.h
Normal file
@@ -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 <Misc/FrameRate.h>
|
||||
#include <UObject/Object.h>
|
||||
|
||||
#include "NDIIOPluginSettings.generated.h"
|
||||
|
||||
/**
|
||||
Settings for the Broadcasting of the Active Viewport configurable in the running editor of the application
|
||||
*/
|
||||
UCLASS(Config = Engine, DefaultConfig)
|
||||
class NDIIO_API UNDIIOPluginSettings : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(VisibleAnywhere, Category = "NDI IO", META = (DisplayName = "Description", MultiLine = true))
|
||||
FString Decription = TEXT(
|
||||
"These values define the 'Active Viewport' broadcast settings and does not define default values for outputs."
|
||||
"\r\n"
|
||||
"\r\nApplication Stream Name - The default name to use when broadcasting the Currently Active Viewport over "
|
||||
"NDI."
|
||||
"\r\nBroadcast Rate - Indicates the preferred frame rate to broadcast the Currently Active Viewport over NDI."
|
||||
"\r\nPreferred FrameSize - Indicates the preferred frame size to broadcast the Currently Active Viewport over "
|
||||
"NDI."
|
||||
"\r\nBegin Broadcast On Play - Starts the broadcast of the Currently Active Viewport immediately on Play."
|
||||
);
|
||||
|
||||
/** The default name to use when broadcasting the Currently Active Viewport over NDI. */
|
||||
UPROPERTY(Config, EditAnywhere, Category = "NDI IO")
|
||||
FString ApplicationStreamName = FString("Unreal Engine");
|
||||
|
||||
/** Indicates the preferred frame rate to broadcast the Currently Active Viewport over NDI. */
|
||||
UPROPERTY(Config, EditAnywhere, Category = "NDI IO", META = (DisplayName = "Broadcast Rate"))
|
||||
FFrameRate BroadcastRate = FFrameRate(60, 1);
|
||||
|
||||
/** Indicates the preferred frame size to broadcast the Currently Active Viewport over NDI. */
|
||||
UPROPERTY(Config, EditAnywhere, Category = "NDI IO", META = (DisplayName = "Preferred Broadcast Framesize"))
|
||||
FIntPoint PreferredFrameSize = FIntPoint(1920, 1080);
|
||||
|
||||
UPROPERTY(Config, EditAnywhere, Category = "NDI IO", META = (DisplayName = "Begin Broadcast On Play"))
|
||||
bool bBeginBroadcastOnPlay = false;
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
109
Plugins/NDIIO/Source/Core/Public/Services/NDIConnectionService.h
Normal file
109
Plugins/NDIIO/Source/Core/Public/Services/NDIConnectionService.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
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/TextureRenderTarget2D.h>
|
||||
#include <AudioDevice.h>
|
||||
#include <Misc/EngineVersionComparison.h>
|
||||
#if (ENGINE_MAJOR_VERSION > 5) || ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 3)) // 5.3 or later
|
||||
#include <ISubmixBufferListener.h>
|
||||
#endif
|
||||
#include <Widgets/SWindow.h>
|
||||
|
||||
DECLARE_EVENT_OneParam(FNDICoreDelegates, FNDIConnectionServiceSendVideoEvent, int64)
|
||||
DECLARE_EVENT_SixParams(FNDICoreDelegates, FNDIConnectionServiceSendAudioEvent, int64, float*, int32, int32, const int32, double)
|
||||
|
||||
/**
|
||||
A service which runs and triggers updates for interested parties to be notified of
|
||||
Audio and Video Frame events
|
||||
*/
|
||||
class NDIIO_API FNDIConnectionService final : public ISubmixBufferListener
|
||||
{
|
||||
public:
|
||||
static FNDIConnectionServiceSendVideoEvent EventOnSendVideoFrame;
|
||||
private:
|
||||
static TMap<USoundSubmix*, FNDIConnectionServiceSendAudioEvent> SubmixSendAudioFrameEvents;
|
||||
|
||||
public:
|
||||
/**
|
||||
Constructs a new instance of this object
|
||||
*/
|
||||
FNDIConnectionService();
|
||||
|
||||
// Begin the service
|
||||
bool Start();
|
||||
|
||||
// Stop the service
|
||||
void Shutdown();
|
||||
|
||||
bool BeginBroadcastingActiveViewport();
|
||||
void StopBroadcastingActiveViewport();
|
||||
|
||||
bool IsRunningInPIE() const
|
||||
{
|
||||
return bIsInPIEMode;
|
||||
}
|
||||
|
||||
template <typename UserClass>
|
||||
static void AddAudioSender(UserClass* InUserObject, USoundSubmix* Submix, typename TMemFunPtrType<false, UserClass, void (int64 /*time_code*/, float* /*AudioData*/, int32 /*NumSamples*/, int32 /*NumChannels*/, const int32 /*SampleRate*/, double /*AudioClock*/)>::Type InFunc)
|
||||
{
|
||||
FScopeLock Lock(&AudioSyncContext);
|
||||
|
||||
FNDIConnectionServiceSendAudioEvent& SendAudioEvent = SubmixSendAudioFrameEvents.FindOrAdd(Submix);
|
||||
SendAudioEvent.AddUObject(InUserObject, InFunc);
|
||||
}
|
||||
|
||||
template <typename UserClass>
|
||||
static void RemoveAudioSender(UserClass* InUserObject)
|
||||
{
|
||||
FScopeLock Lock(&AudioSyncContext);
|
||||
|
||||
for (auto it = SubmixSendAudioFrameEvents.CreateIterator(); it; ++it)
|
||||
{
|
||||
it->Value.RemoveAll(InUserObject);
|
||||
if (it->Value.IsBound() == false)
|
||||
it.RemoveCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Handler for when the render thread frame has ended
|
||||
void OnEndRenderFrame();
|
||||
|
||||
void BeginAudioCapture();
|
||||
void StopAudioCapture();
|
||||
|
||||
void OnPostEngineInit();
|
||||
void OnEnginePreExit();
|
||||
|
||||
// Handler for when the active viewport back buffer is about to be resized
|
||||
void OnActiveViewportBackbufferPreResize(void* Backbuffer);
|
||||
|
||||
// Handler for when the back buffer is read to present to the end user
|
||||
void OnActiveViewportBackbufferReadyToPresent(SWindow& Window, const FTextureRHIRef& Backbuffer);
|
||||
|
||||
FTextureResource* GetVideoTextureResource() const;
|
||||
|
||||
virtual void OnNewSubmixBuffer(const USoundSubmix* OwningSubmix, float* AudioData, int32 NumSamples, int32 NumChannels, const int32 SampleRate, double AudioClock) override final;
|
||||
#if (ENGINE_MAJOR_VERSION > 5) || ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 4)) // 5.4 or later
|
||||
virtual const FString& GetListenerName() const override final;
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool bIsInitialized = false;
|
||||
bool bIsAudioInitialized = false;
|
||||
bool bIsBroadcastingActiveViewport = false;
|
||||
bool bIsInPIEMode = false;
|
||||
|
||||
static FCriticalSection AudioSyncContext;
|
||||
static FCriticalSection RenderSyncContext;
|
||||
|
||||
UTextureRenderTarget2D* VideoTexture = nullptr;
|
||||
class UNDIMediaSender* ActiveViewportSender = nullptr;
|
||||
};
|
||||
62
Plugins/NDIIO/Source/Core/Public/Services/NDIFinderService.h
Normal file
62
Plugins/NDIIO/Source/Core/Public/Services/NDIFinderService.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
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 <HAL/Runnable.h>
|
||||
#include <HAL/ThreadSafeBool.h>
|
||||
#include <Structures/NDIConnectionInformation.h>
|
||||
|
||||
/**
|
||||
A Runnable object used for Finding NDI network Sources, and updating interested parties
|
||||
*/
|
||||
class NDIIO_API FNDIFinderService : public FRunnable
|
||||
{
|
||||
public:
|
||||
FNDIFinderService();
|
||||
|
||||
// Begin the service
|
||||
virtual bool Start();
|
||||
|
||||
// Stop the service
|
||||
virtual void Shutdown();
|
||||
|
||||
public:
|
||||
/** Get the available sources on the network */
|
||||
static const TArray<FNDIConnectionInformation> GetNetworkSourceCollection();
|
||||
|
||||
/** Call to update an existing collection of network sources to match the current collection */
|
||||
static bool UpdateSourceCollection(TArray<FNDIConnectionInformation>& InSourceCollection);
|
||||
|
||||
/** Event which is triggered when the collection of network sources has changed */
|
||||
DECLARE_EVENT(FNDICoreDelegates, FNDISourceCollectionChangedEvent)
|
||||
static FNDISourceCollectionChangedEvent EventOnNDISourceCollectionChanged;
|
||||
|
||||
protected:
|
||||
/** FRunnable Interface implementation for 'Init' */
|
||||
virtual bool Init() override;
|
||||
|
||||
/** FRunnable Interface implementation for 'Stop' */
|
||||
virtual void Stop() override;
|
||||
|
||||
/** FRunnable Interface implementation for 'Run' */
|
||||
virtual uint32 Run() override;
|
||||
|
||||
private:
|
||||
bool UpdateNetworkSourceCollection();
|
||||
|
||||
private:
|
||||
bool bShouldWaitOneFrame = true;
|
||||
bool bIsNetworkSourceCollectionDirty = false;
|
||||
|
||||
FThreadSafeBool bIsThreadRunning;
|
||||
FRunnableThread* p_RunnableThread = nullptr;
|
||||
|
||||
static TArray<FNDIConnectionInformation> NetworkSourceCollection;
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
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 <Misc/FrameRate.h>
|
||||
|
||||
#include "NDIBroadcastConfiguration.generated.h"
|
||||
|
||||
/**
|
||||
Describes essential properties used for modifying the broadcast configuration of an Sender object
|
||||
*/
|
||||
USTRUCT(BlueprintType, Blueprintable, Category = "NDI IO", META = (DisplayName = "NDI Broadcast Configuration"))
|
||||
struct NDIIO_API FNDIBroadcastConfiguration
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
/** Describes the output frame size while sending video frame over NDI */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Broadcast Settings", META = (DisplayName = "Frame Size"))
|
||||
FIntPoint FrameSize = FIntPoint(1920, 1080);
|
||||
|
||||
/** Represents the desired number of frames (per second) for video to be sent over NDI */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Broadcast Settings", META = (DisplayName = "Frame Rate"))
|
||||
FFrameRate FrameRate = FFrameRate(60, 1);
|
||||
|
||||
public:
|
||||
/** Constructs a new instance of this object */
|
||||
FNDIBroadcastConfiguration() = default;
|
||||
|
||||
/** Copies an existing instance to this object */
|
||||
FNDIBroadcastConfiguration(const FNDIBroadcastConfiguration& other);
|
||||
|
||||
/** Copies existing instance properties to this object */
|
||||
FNDIBroadcastConfiguration& operator=(const FNDIBroadcastConfiguration& other);
|
||||
|
||||
/** Destructs this object */
|
||||
virtual ~FNDIBroadcastConfiguration() = default;
|
||||
|
||||
/** Compares this object to 'other' and returns a determination of whether they are equal */
|
||||
bool operator==(const FNDIBroadcastConfiguration& other) const;
|
||||
|
||||
/** Compares this object to 'other" and returns a determination of whether they are NOT equal */
|
||||
bool operator!=(const FNDIBroadcastConfiguration& other) const;
|
||||
|
||||
protected:
|
||||
/** Attempts to serialize this object using an Archive object */
|
||||
virtual FArchive& Serialize(FArchive& Ar);
|
||||
|
||||
private:
|
||||
/** Operator override for serializing this object to an Archive object */
|
||||
friend class FArchive& operator<<(FArchive& Ar, FNDIBroadcastConfiguration& Input)
|
||||
{
|
||||
return Input.Serialize(Ar);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
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 <Enumerations/NDISourceBandwidth.h>
|
||||
#include <Serialization/Archive.h>
|
||||
|
||||
#include "NDIConnectionInformation.generated.h"
|
||||
|
||||
/**
|
||||
Describes essential properties used for connection objects over NDI
|
||||
*/
|
||||
USTRUCT(BlueprintType, Blueprintable, Category = "NDI IO", META = (DisplayName = "NDI Connection Information"))
|
||||
struct NDIIO_API FNDIConnectionInformation
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
/** A user-friendly name of the source */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Properties", META = (DisplayName = "Source Name"))
|
||||
FString SourceName = FString("");
|
||||
|
||||
/** The machine name of the source */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Properties", META = (DisplayName = "Machine Name"))
|
||||
FString MachineName = FString("");
|
||||
|
||||
/** The stream name of the source */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Properties", META = (DisplayName = "Stream Name"))
|
||||
FString StreamName = FString("");
|
||||
|
||||
/** A location on the network for which this source exists */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Properties", META = (DisplayName = "Url"))
|
||||
FString Url = FString("");
|
||||
|
||||
/** Indicates the current bandwidth mode used for this connection */
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Properties", META = (DisplayName = "Bandwidth"))
|
||||
ENDISourceBandwidth Bandwidth = ENDISourceBandwidth::Highest;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Properties", META = (DisplayName = "Mute Audio"))
|
||||
bool bMuteAudio = false;
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Properties", META = (DisplayName = "Mute Video"))
|
||||
bool bMuteVideo = false;
|
||||
|
||||
public:
|
||||
/** Constructs a new instance of this object */
|
||||
FNDIConnectionInformation() = default;
|
||||
|
||||
/** Copies an existing instance to this object */
|
||||
FNDIConnectionInformation(const FNDIConnectionInformation& other);
|
||||
|
||||
/** Copies existing instance properties to this object */
|
||||
FNDIConnectionInformation& operator=(const FNDIConnectionInformation& other);
|
||||
|
||||
/** Destructs this object */
|
||||
virtual ~FNDIConnectionInformation() = default;
|
||||
|
||||
/** Implicit conversion to a base NDI bandwidth value */
|
||||
operator NDIlib_recv_bandwidth_e() const;
|
||||
|
||||
/** Compares this object to 'other' and returns a determination of whether they are equal */
|
||||
bool operator==(const FNDIConnectionInformation& other) const;
|
||||
|
||||
/** Compares this object to 'other" and returns a determination of whether they are NOT equal */
|
||||
bool operator!=(const FNDIConnectionInformation& other) const;
|
||||
|
||||
public:
|
||||
/** Resets the current parameters to the default property values */
|
||||
void Reset();
|
||||
|
||||
/** Determines whether this object is valid connection information */
|
||||
bool IsValid() const;
|
||||
|
||||
FString GetNDIName() const;
|
||||
|
||||
protected:
|
||||
/** Attempts to serialize this object using an Archive object */
|
||||
virtual FArchive& Serialize(FArchive& Ar);
|
||||
|
||||
private:
|
||||
/** Operator override for serializing this object to an Archive object */
|
||||
friend class FArchive& operator<<(FArchive& Ar, FNDIConnectionInformation& Input)
|
||||
{
|
||||
return Input.Serialize(Ar);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
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 <Serialization/Archive.h>
|
||||
|
||||
#include "NDIReceiverPerformanceData.generated.h"
|
||||
|
||||
/**
|
||||
A structure holding data allowing you to determine the current performance levels of the receiver with the
|
||||
ability to detect whether frames has been dropped
|
||||
*/
|
||||
USTRUCT(BlueprintType, Blueprintable, Category = "NDI IO", META = (DisplayName = "NDI Receiver Performance Data"))
|
||||
struct NDIIO_API FNDIReceiverPerformanceData
|
||||
{
|
||||
GENERATED_USTRUCT_BODY()
|
||||
|
||||
public:
|
||||
/**
|
||||
The number of audio frames received from the NDI sender
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Information", META = (DisplayName = "Audio Frames"))
|
||||
int64 AudioFrames = 0;
|
||||
|
||||
/**
|
||||
The number of video frames dropped in transit from an NDI sender
|
||||
*/
|
||||
UPROPERTY(BlueprintReadonly, VisibleAnywhere, Category = "Information",
|
||||
META = (DisplayName = "Dropped Video Frames"))
|
||||
int64 DroppedVideoFrames = 0;
|
||||
|
||||
/**
|
||||
The number of audio frames dropped in transit from the NDI sender
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Information",
|
||||
META = (DisplayName = "Dropped Audio Frames"))
|
||||
int64 DroppedAudioFrames = 0;
|
||||
|
||||
/**
|
||||
The number of metadata frames dropped in transit from the NDI sender
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Information",
|
||||
META = (DisplayName = "Dropped Metadata Frames"))
|
||||
int64 DroppedMetadataFrames = 0;
|
||||
|
||||
/**
|
||||
The number of metadata frames received from the NDI sender
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Information", META = (DisplayName = "Metadata Frames"))
|
||||
int64 MetadataFrames = 0;
|
||||
|
||||
/**
|
||||
The number of video frames received from the NDI sender
|
||||
*/
|
||||
UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Information", META = (DisplayName = "Video Frames"))
|
||||
int64 VideoFrames = 0;
|
||||
|
||||
public:
|
||||
/** Constructs a new instance of this object */
|
||||
FNDIReceiverPerformanceData() = default;
|
||||
|
||||
/** Copies an existing instance to this object */
|
||||
FNDIReceiverPerformanceData(const FNDIReceiverPerformanceData& other);
|
||||
|
||||
/** Copies existing instance properties to this object */
|
||||
FNDIReceiverPerformanceData& operator=(const FNDIReceiverPerformanceData& other);
|
||||
|
||||
/** Destructs this object */
|
||||
virtual ~FNDIReceiverPerformanceData() = default;
|
||||
|
||||
/** Compares this object to 'other' and returns a determination of whether they are equal */
|
||||
bool operator==(const FNDIReceiverPerformanceData& other) const;
|
||||
|
||||
/** Compares this object to 'other" and returns a determination of whether they are NOT equal */
|
||||
bool operator!=(const FNDIReceiverPerformanceData& other) const;
|
||||
|
||||
public:
|
||||
/** Resets the current parameters to the default property values */
|
||||
void Reset();
|
||||
|
||||
protected:
|
||||
/** Attempts to serialize this object using an Archive object */
|
||||
virtual FArchive& Serialize(FArchive& Ar);
|
||||
|
||||
private:
|
||||
/** Operator override for serializing this object to an Archive object */
|
||||
friend class FArchive& operator<<(FArchive& Ar, FNDIReceiverPerformanceData& Input)
|
||||
{
|
||||
return Input.Serialize(Ar);
|
||||
}
|
||||
};
|
||||
131
Plugins/NDIIO/Source/Core/Public/Structures/NDIXml.h
Normal file
131
Plugins/NDIIO/Source/Core/Public/Structures/NDIXml.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
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 <FastXml.h>
|
||||
|
||||
class NDIXmlElementParser
|
||||
{
|
||||
public:
|
||||
virtual ~NDIXmlElementParser()
|
||||
{}
|
||||
|
||||
// Start parsing this element
|
||||
virtual bool ProcessOpen(const TCHAR* ElementName, const TCHAR* ElementData)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse an attribute of this element
|
||||
virtual bool ProcessAttribute(const TCHAR* AttributeName, const TCHAR* AttributeValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Start parsing a sub-element
|
||||
virtual TSharedRef<NDIXmlElementParser>* ProcessElement(const TCHAR* ElementName, const TCHAR* ElementData)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Finish parsing this element
|
||||
virtual bool ProcessClose(const TCHAR* ElementName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class NDIXmlElementParser_null : public NDIXmlElementParser
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
|
||||
class NDIXmlParser : public IFastXmlCallback
|
||||
{
|
||||
public:
|
||||
virtual ~NDIXmlParser()
|
||||
{}
|
||||
|
||||
|
||||
void AddElementParser(FName ElementName, TSharedRef<NDIXmlElementParser> ElementParser)
|
||||
{
|
||||
ElementParsers.Add(ElementName, ElementParser);
|
||||
}
|
||||
|
||||
virtual bool ProcessXmlDeclaration(const TCHAR* ElementData, int32 XmlFileLineNumber) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool ProcessElement(const TCHAR* ElementName, const TCHAR* ElementData, int32 XmlFileLineNumber) override
|
||||
{
|
||||
if(ElementParserStack.Num() == 0)
|
||||
{
|
||||
TSharedRef<NDIXmlElementParser>* ParserPtr = ElementParsers.Find(ElementName);
|
||||
if(ParserPtr == nullptr)
|
||||
ParserPtr = &NullParser;
|
||||
|
||||
ElementParserStack.Push(*ParserPtr);
|
||||
return (*ParserPtr)->ProcessOpen(ElementName, ElementData);
|
||||
}
|
||||
else
|
||||
{
|
||||
TSharedRef<NDIXmlElementParser>* ParserPtr = ElementParserStack.Last()->ProcessElement(ElementName, ElementData);
|
||||
if(ParserPtr == nullptr)
|
||||
ParserPtr = &NullParser;
|
||||
|
||||
ElementParserStack.Push(*ParserPtr);
|
||||
return (*ParserPtr)->ProcessOpen(ElementName, ElementData);
|
||||
}
|
||||
|
||||
//return false;
|
||||
}
|
||||
|
||||
virtual bool ProcessAttribute(const TCHAR* AttributeName, const TCHAR* AttributeValue) override
|
||||
{
|
||||
if(ElementParserStack.Num() == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ElementParserStack.Last()->ProcessAttribute(AttributeName, AttributeValue);
|
||||
}
|
||||
|
||||
//return false;
|
||||
}
|
||||
|
||||
virtual bool ProcessClose(const TCHAR* ElementName) override
|
||||
{
|
||||
if(ElementParserStack.Num() == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto Parser = ElementParserStack.Pop();
|
||||
return Parser->ProcessClose(ElementName);
|
||||
}
|
||||
|
||||
//return false;
|
||||
}
|
||||
|
||||
virtual bool ProcessComment(const TCHAR* Comment) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
TMap<FName, TSharedRef<NDIXmlElementParser> > ElementParsers;
|
||||
TArray<TSharedRef<NDIXmlElementParser> > ElementParserStack;
|
||||
|
||||
TSharedRef<NDIXmlElementParser> NullParser { MakeShareable(new NDIXmlElementParser_null()) };
|
||||
};
|
||||
Reference in New Issue
Block a user