First commit
This commit is contained in:
@@ -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;
|
||||
}
|
||||
1525
Plugins/NDIIO/Source/Core/Classes/Objects/Media/NDIMediaReceiver.cpp
Normal file
1525
Plugins/NDIIO/Source/Core/Classes/Objects/Media/NDIMediaReceiver.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1368
Plugins/NDIIO/Source/Core/Classes/Objects/Media/NDIMediaSender.cpp
Normal file
1368
Plugins/NDIIO/Source/Core/Classes/Objects/Media/NDIMediaSender.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user