[NdiMedia Plugin]Tried to output video frame but failed

Hello, we are trying to use the NdiMedia plugin to implment Ndi sending feature by ourselves. We added a class to NdiMedia plugin, which is called UNdiMediaSender. We managed to initialize NDI and create a sender instance inside the UNdiMediaSender class. However, when we try to send video frame using NDIlib_send_send_video_v2 or NDIlib_send_send_video_async_v2 method, UE4 crashed.

I’ve read another issue in which you mentioned that the sending feature is on the way, which is a cool news. At this moment, we want to know how to fix this crash problem. Thank you very much.

Our code is something like this: ( Sorry for the ugly layout )

Please search “Crash Happens Here” to locate the crash point.

NdiMediaSender.h

#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "NdiMediaSender.generated.h"

UCLASS(BlueprintType)
class NDIMEDIA_API UNdiMediaSender : public UObject
{
GENERATED_BODY()
public:
UNdiMediaSender();

public:
UFUNCTION(BlueprintCallable, Category = NDI)
void Initialize();

UFUNCTION(BlueprintCallable, Category = NDI)
void Tick();

public:
//~ UObject interface
virtual void BeginDestroy() override;

#if WITH_EDITOR
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif
};

NdiMediaSender.cpp

#include "NdiMediaSender.h"
#include "Ndi.h"
#include "NdiMediaPrivate.h"

static std::atomic exit_loop(false);
static void sigint_handler(int)
{
exit_loop = true;
}

NDIlib_send_create_t NDI_send_create_desc;
NDIlib_send_instance_t pNDI_send;
NDIlib_video_frame_v2_t NDI_video_frame;

const int xres = 720;
const int yres = 480;

UNdiMediaSender::UNdiMediaSender()
{
}

void UNdiMediaSender::Initialize()
{
if (!NDIlib_initialize())
{
UE_LOG(LogTemp, Warning, TEXT("Can not run NDI"));
return;
}
UE_LOG(LogTemp, Warning, TEXT("NDI library initialized"));
// Catch interrupt so that we can shut down gracefully
signal(SIGINT, sigint_handler);
// Create an NDI source that is called "My Video" and is clocked to the video.
NDI_send_create_desc.p_ndi_name = "My Video";
// We create the NDI sender
pNDI_send = NDIlib_send_create(&NDI_send_create_desc);
if (!pNDI_send) return;
UE_LOG(LogTemp, Warning, TEXT("NDI sender created"));
// We are going to create a 1920x1080 interlaced frame at 29.97Hz.
NDI_video_frame.xres = xres;
NDI_video_frame.yres = yres;
NDI_video_frame.FourCC = NDIlib_FourCC_type_BGRX;
NDI_video_frame.frame_format_type = NDIlib_frame_format_type_interleaved;
NDI_video_frame.p_data = (uint8_t*)malloc(xres * yres * 4);
NDI_video_frame.line_stride_in_bytes = xres * 4;
}

void UNdiMediaSender::Tick()
{
UE_LOG(LogTemp, Warning, TEXT("Tick"));
// Fill in the buffer. It is likely that you would do something much smarter than this.
memset((void*)NDI_video_frame.p_data, 255, xres * yres * 4);
UE_LOG(LogTemp, Warning, TEXT("memset done"));

// Crash Happens Here !
NDIlib_send_send_video_async_v2(pNDI_send, &NDI_video_frame);

UE_LOG(LogTemp, Warning, TEXT("video sent"));
}

/* UObject interface
*****************************************************************************/
void UNdiMediaSender::BeginDestroy()
{
Super::BeginDestroy();
// Free the video frame
free(NDI_video_frame.p_data);
// Destroy the NDI sender
NDIlib_send_destroy(pNDI_send);
// Not required, but nice
NDIlib_destroy();
}

#if WITH_EDITOR
void UNdiMediaSender::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
}
#endif //WITH_EDITOR

I have not tried to implement sending yet. Are you sure that pNDI_send and NDI_video_frame are initialized properly? The NDI SDK has a sample project for sending frames. Make sure you follow the steps correctly.

Apologies for the blatant self-promotion, but if you don’t mind using a 3rd party, you can use Lightact media server, which works with Unreal (and has NDI integrated).

Check out this video tutorial if you are interested. You’ll also need Spout-UE4 plugin to make this work.

This might be a bit late for you, but I managed to get NDI output on Windows working without the NDI plugin (at least the sample code you provided) by

  • placing the Processing.NDI.Lib.x64.dll into the ProjectName>Binaries>Win64 folder,

  • Creating folders ProjectName>ThirdParty>NDI that has an Include folder containing all of the Processing.* headers provided by the SDK, and a lib folder which contains the Processing.NDI.Lib.x64.lib provided by the SDK (though these could both be wherever you want I suppose, so long as you have their path in the build.cs below)

  • Modifying the project’s build.cs located inside of the source folder so that it includes the lines :

string depFolder = "C:/Path/To/Project/ProjectName/ThirdParty/NDI";

PublicIncludePaths.Add(Path.Combine(depFolder, "Include"));

PublicAdditionalLibraries.Add(Path.Combine(depFolder, "lib/x64/Processing.NDI.Lib.x64.lib"));

Hope this helps!

Edit: to use the Path.Combine functions, I believe you’d need to including using System and using System.IO at the top of your build.cs

Can you pls confirm how you got NDI sender from UE4 working? UE4.20?

Was the NDI UE4 plugin already working and then you added the class above? Or did you somehow just use above? I’m not clear how adding those additional files will create an NDI sender