First commit

This commit is contained in:
2025-09-04 16:16:17 +03:00
parent 25a1a8d36a
commit ae934d9718
506 changed files with 15576 additions and 2 deletions

View File

@@ -0,0 +1,201 @@
/*
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.
*/
#include <Objects/Libraries/NDIIOLibrary.h>
#include <Services/NDIFinderService.h>
#include <NDIIOPluginModule.h>
#include <FastXml.h>
const TArray<FNDIConnectionInformation> UNDIIOLibrary::K2_GetNDISourceCollection()
{
// Return the FinderServices current network source collection
return FNDIFinderService::GetNetworkSourceCollection();
}
const bool UNDIIOLibrary::K2_FindNetworkSourceByName(UObject* WorldContextObject,
FNDIConnectionInformation& ConnectionInformation,
FString InSourceName)
{
// Ensure that the passed in information is empty
ConnectionInformation.Reset();
// Get the current network source collection from the finder service.
const TArray<FNDIConnectionInformation> NetworkSourceCollection = FNDIFinderService::GetNetworkSourceCollection();
// Get the current number of network source items in the collection
int32 final_count = NetworkSourceCollection.Num();
// Ensure we have a wide range of items to search through.
int32 last_index = final_count;
// Since the Source collection returned is already sorted alphabetically do a binary search to speed things up.
// We are only going to do comparisons that are necessary using O(log(n)) time complexity
for (int32 current_index = 0; current_index < last_index; /* current_index changed in loop */)
{
// Ensure that the index is valid (this will protect against negative values)
if (NetworkSourceCollection.IsValidIndex(current_index))
{
// Get the source reference from the collection
FNDIConnectionInformation source_info = NetworkSourceCollection[current_index];
// do a comparison against the requested SourceName
if (int32 comparitor_value = InSourceName.Compare(source_info.SourceName, ESearchCase::IgnoreCase))
{
// Our search says that our source name is greater than the info we checked
if (comparitor_value <= 0)
{
// set the last index to the current index
last_index = current_index;
// get halfway between the last index and the 0th index
current_index = last_index / 2;
}
// Our search says that our source name is less than the info we checked
else if (comparitor_value > 0)
{
// move up half the number of items within the collection
current_index = (last_index + current_index + 1) / 2;
}
}
// We found a comparable source.
else
{
// Set the source information structure
ConnectionInformation = source_info;
// return success
return true;
}
}
// Something weird happened (maybe the first check was larger than the search term); just return a fail
else
return false;
}
return false;
}
bool UNDIIOLibrary::K2_BeginBroadcastingActiveViewport(UObject* WorldContextObject)
{
// Get the plugin module for the owner of this object
if (FNDIIOPluginModule* PluginModule = FModuleManager::GetModulePtr<FNDIIOPluginModule>("NDIIO"))
{
// Call the underlying functionality
return PluginModule->BeginBroadcastingActiveViewport();
}
return false;
}
void UNDIIOLibrary::K2_StopBroadcastingActiveViewport(UObject* WorldContextObject)
{
// Get the plugin module for the owner of this object
if (FNDIIOPluginModule* PluginModule = FModuleManager::GetModulePtr<FNDIIOPluginModule>("NDIIO"))
{
// Call the underlying functionality
PluginModule->StopBroadcastingActiveViewport();
}
}
UNDIMediaReceiver* UNDIIOLibrary::K2_GetNDIMediaReceiver(UNDIMediaReceiver* Receiver)
{
return Receiver;
}
UNDIMediaSender* UNDIIOLibrary::K2_GetNDIMediaSender(UNDIMediaSender* Sender)
{
return Sender;
}
const TArray<FNDIMetaDataElement> UNDIIOLibrary::K2_ParseNDIMetaData(FString Data)
{
class Parser : public IFastXmlCallback
{
public:
Parser(TArray<FNDIMetaDataElement>& ElementsIn)
: Elements(ElementsIn)
{}
virtual ~Parser()
{}
virtual bool ProcessXmlDeclaration(const TCHAR* ElementData, int32 XmlFileLineNumber) override
{
return true;
}
virtual bool ProcessElement(const TCHAR* ElementName, const TCHAR* ElementData, int32 XmlFileLineNumber) override
{
if(CurrentElementStack.Num() > 0)
return false;
FNDIMetaDataElement NewElement;
NewElement.ElementName = ElementName;
NewElement.Data = ElementData;
if(CurrentElementStack.Num() == 0)
{
Elements.Push(NewElement);
CurrentElementStack.Push(&Elements.Last());
}
return true;
}
virtual bool ProcessAttribute(const TCHAR* AttributeName, const TCHAR* AttributeValue) override
{
check(CurrentElementStack.Num() > 0);
FNDIMetaDataElement* CurrentElement = CurrentElementStack.Last();
CurrentElement->Attributes.Add(AttributeName, AttributeValue);
return true;
}
virtual bool ProcessClose(const TCHAR* ElementName) override
{
check(CurrentElementStack.Num() > 0);
CurrentElementStack.Pop();
return true;
}
virtual bool ProcessComment(const TCHAR* Comment) override
{
return true;
}
private:
TArray<FNDIMetaDataElement>& Elements;
TArray<FNDIMetaDataElement*> CurrentElementStack;
};
TArray<FNDIMetaDataElement> Elements;
Parser Parser(Elements);
FText OutErrorMessage;
int32 OutErrorLineNumber;
FFastXml::ParseXmlFile(&Parser,
nullptr, // XmlFilePath
Data.GetCharArray().GetData(), // XmlFileContents
nullptr, // FeedbackContext
false, // bShowSlowTaskDialog
false, // bShowCancelButton
OutErrorMessage, // OutErrorMessage
OutErrorLineNumber // OutErrorLineNumber
);
return Elements;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,77 @@
/*
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.
*/
#include <Objects/Media/NDIMediaSoundWave.h>
#include <Objects/Media/NDIMediaReceiver.h>
UNDIMediaSoundWave::UNDIMediaSoundWave(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
// Set the Default Values for this object
this->bLooping = false;
this->NumChannels = 1;
this->SampleRate = 48000;
this->Duration = INDEFINITELY_LOOPING_DURATION;
}
/**
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 UNDIMediaSoundWave::SetConnectionSource(UNDIMediaReceiver* InMediaSource)
{
// Ensure there is no thread contention for generating pcm data from the connection source
FScopeLock Lock(&SyncContext);
// Do we have a media source object to work with
if (this->MediaSource != nullptr)
{
// Are we already registered with the incoming media source object
if (this->MediaSource != InMediaSource)
{
// It doesn't look like we are registered with the incoming, make sure
// to unregistered with the previous source
this->MediaSource->UnregisterAudioWave(this);
}
}
// Ensure we have a reference to the media source object
this->MediaSource = InMediaSource;
}
/**
Called by the engine to generate pcm data to be 'heard' by audio listener objects
*/
int32 UNDIMediaSoundWave::OnGeneratePCMAudio(TArray<uint8>& OutAudio, int32 NumSamples)
{
// Ensure there is no thread contention for generating pcm data from the connection source
FScopeLock Lock(&SyncContext);
// set the default value, in case we have no connection source
int32 samples_generated = 0;
OutAudio.Reset();
OutAudio.AddZeroed(NumSamples * sizeof(int16));
// check the connection source and continue
if (this->MediaSource != nullptr)
{
samples_generated = MediaSource->GeneratePCMData(this, OutAudio.GetData(), NumSamples);
}
// return to the engine the number of samples actually generated
return samples_generated;
}
bool UNDIMediaSoundWave::IsReadyForFinishDestroy()
{
// Ensure that there is no thread contention for generating data
FScopeLock Lock(&SyncContext);
return USoundWaveProcedural::IsReadyForFinishDestroy();
}

View File

@@ -0,0 +1,153 @@
/*
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.
*/
#include <Objects/Media/NDIMediaTexture2D.h>
#include <Objects/Media/NDIMediaTextureResource.h>
#include <Misc/EngineVersionComparison.h>
UNDIMediaTexture2D::UNDIMediaTexture2D(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
this->SetMyResource(nullptr);
}
void UNDIMediaTexture2D::UpdateTextureReference(FRHICommandList& RHICmdList, FTextureRHIRef Reference)
{
if (GetMyResource() != nullptr)
{
if (Reference.IsValid() && GetMyResource()->TextureRHI != Reference)
{
GetMyResource()->TextureRHI = (FTextureRHIRef&)Reference;
RHIUpdateTextureReference(TextureReference.TextureReferenceRHI, GetMyResource()->TextureRHI);
}
else if (!Reference.IsValid())
{
if (FNDIMediaTextureResource* TextureResource = static_cast<FNDIMediaTextureResource*>(this->GetMyResource()))
{
ENQUEUE_RENDER_COMMAND(FNDIMediaTexture2DUpdateTextureReference)
([this](FRHICommandListImmediate& RHICmdList) {
static int32 DefaultWidth = 1280;
static int32 DefaultHeight = 720;
// Set the default video texture to reference nothing
TRefCountPtr<FRHITexture> RenderableTexture;
const FRHITextureCreateDesc CreateDesc = FRHITextureCreateDesc::Create2D(TEXT("NDIMediaTexture2DUpdateTextureReference"))
.SetExtent(DefaultWidth, DefaultHeight)
.SetFormat(EPixelFormat::PF_B8G8R8A8)
.SetNumMips(1)
.SetFlags(ETextureCreateFlags::Dynamic | ETextureCreateFlags::RenderTargetable)
.SetClearValue(FClearValueBinding(FLinearColor(0.0f, 0.0f, 0.0f)));
RenderableTexture = RHICreateTexture(CreateDesc);
GetMyResource()->TextureRHI = (FTextureRHIRef&)RenderableTexture;
RHIUpdateTextureReference(TextureReference.TextureReferenceRHI, GetMyResource()->TextureRHI);
});
// Make sure _RenderThread is executed before continuing
FlushRenderingCommands();
}
}
}
}
FTextureResource* UNDIMediaTexture2D::CreateResource()
{
if (this->GetMyResource() != nullptr)
{
delete this->GetMyResource();
this->SetMyResource(nullptr);
}
if (FNDIMediaTextureResource* TextureResource = new FNDIMediaTextureResource(this))
{
this->SetMyResource(TextureResource);
ENQUEUE_RENDER_COMMAND(FNDIMediaTexture2DUpdateTextureReference)
([this](FRHICommandListImmediate& RHICmdList) {
static int32 DefaultWidth = 1280;
static int32 DefaultHeight = 720;
// Set the default video texture to reference nothing
TRefCountPtr<FRHITexture> RenderableTexture;
const FRHITextureCreateDesc CreateDesc = FRHITextureCreateDesc::Create2D(TEXT("NDIMediaTexture2DCreateResourceTexture"))
.SetExtent(DefaultWidth, DefaultHeight)
.SetFormat(EPixelFormat::PF_B8G8R8A8)
.SetNumMips(1)
.SetFlags(ETextureCreateFlags::Dynamic | ETextureCreateFlags::RenderTargetable)
.SetClearValue(FClearValueBinding(FLinearColor(0.0f, 0.0f, 0.0f)));
RenderableTexture = RHICreateTexture(CreateDesc);
GetMyResource()->TextureRHI = (FTextureRHIRef&)RenderableTexture;
RHIUpdateTextureReference(TextureReference.TextureReferenceRHI, GetMyResource()->TextureRHI);
});
}
return this->GetMyResource();
}
void UNDIMediaTexture2D::GetResourceSizeEx(FResourceSizeEx& CumulativeResourceSize)
{
Super::GetResourceSizeEx(CumulativeResourceSize);
if (FNDIMediaTextureResource* CurrentResource = static_cast<FNDIMediaTextureResource*>(this->GetMyResource()))
{
CumulativeResourceSize.AddUnknownMemoryBytes(CurrentResource->GetResourceSize());
}
}
float UNDIMediaTexture2D::GetSurfaceHeight() const
{
return GetMyResource() != nullptr ? GetMyResource()->GetSizeY() : 0.0f;
}
float UNDIMediaTexture2D::GetSurfaceWidth() const
{
return GetMyResource() != nullptr ? GetMyResource()->GetSizeX() : 0.0f;
}
float UNDIMediaTexture2D::GetSurfaceDepth() const
{
return 0.0f;
}
uint32 UNDIMediaTexture2D::GetSurfaceArraySize() const
{
return 0;
}
EMaterialValueType UNDIMediaTexture2D::GetMaterialType() const
{
return MCT_Texture2D;
}
ETextureClass UNDIMediaTexture2D::GetTextureClass() const
{
return ETextureClass::Other2DNoSource;
}
void UNDIMediaTexture2D::SetMyResource(FTextureResource* ResourceIn)
{
SetResource(ResourceIn);
}
FTextureResource* UNDIMediaTexture2D::GetMyResource()
{
return GetResource();
}
const FTextureResource* UNDIMediaTexture2D::GetMyResource() const
{
return GetResource();
}

View File

@@ -0,0 +1,73 @@
/*
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.
*/
#include <Objects/Media/NDIMediaTextureResource.h>
#include <RHI.h>
#include <DeviceProfiles/DeviceProfile.h>
#include <DeviceProfiles/DeviceProfileManager.h>
#include <Objects/Media/NDIMediaTexture2D.h>
#include <RenderUtils.h>
/**
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::FNDIMediaTextureResource(UNDIMediaTexture2D* Owner)
{
this->MediaTexture = Owner;
}
#if (ENGINE_MAJOR_VERSION > 5) || ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 3)) // 5.3 or later
void FNDIMediaTextureResource::InitRHI(FRHICommandListBase& RHICmdList)
#else
void FNDIMediaTextureResource::InitDynamicRHI()
#endif
{
if (this->MediaTexture != nullptr)
{
FSamplerStateInitializerRHI SamplerStateInitializer(
(ESamplerFilter)UDeviceProfileManager::Get().GetActiveProfile()->GetTextureLODSettings()->GetSamplerFilter(
MediaTexture),
AM_Border, AM_Border, AM_Wrap);
SamplerStateRHI = RHICreateSamplerState(SamplerStateInitializer);
}
}
#if (ENGINE_MAJOR_VERSION > 5) || ((ENGINE_MAJOR_VERSION == 5) && (ENGINE_MINOR_VERSION >= 3)) // 5.3 or later
void FNDIMediaTextureResource::ReleaseRHI()
#else
void FNDIMediaTextureResource::ReleaseDynamicRHI()
#endif
{
// Release the TextureRHI bound by this object
this->TextureRHI.SafeRelease();
// Ensure that we have a owning media texture
if (this->MediaTexture != nullptr)
{
// Remove the texture reference associated with the owner texture object
RHIUpdateTextureReference(MediaTexture->TextureReference.TextureReferenceRHI, nullptr);
}
}
SIZE_T FNDIMediaTextureResource::GetResourceSize()
{
return CalcTextureSize(GetSizeX(), GetSizeY(), EPixelFormat::PF_A8R8G8B8, 1);
}
uint32 FNDIMediaTextureResource::GetSizeX() const
{
return this->TextureRHI.IsValid() ? TextureRHI->GetSizeXYZ().X : 0;
}
uint32 FNDIMediaTextureResource::GetSizeY() const
{
return this->TextureRHI.IsValid() ? TextureRHI->GetSizeXYZ().Y : 0;
}