// THESE ARE GLOBAL TO THE CLASS
// IN MY HEADER FILE
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Webcamera")
class UTexture2D* WebcameraTexture;
UTexture2D* Tex01;
UTexture2D* Tex02;
// ======================================
// Called every frame
void AWebCam::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
return;
if ((x++ % (30 * 5)) == 0)
{
if (ImageSwitch)
WebcameraTexture = Tex01;
else
WebcameraTexture = Tex02;
ImageSwitch = !ImageSwitch;
}
}
UE 5.2
C++ class in a Blueprint project.
(above code) I know I have the “plumbing” right in Unreal Engine blueprint…with dynamic instance material and texture parameter etc…
Because if I have
Tex01 = cat image
Tex02 = dog image…
My Tick() function will swap back and forth between dog and cat textures and it will update the material correctly when playing the “level”.
Now I have a directshow graph, and I have a capture buffer function I set to function in below code. It is a pass through function. I can just do nothing and return and the video will actually play…OUTSIDE of UE application. I only mention it, because that is 100% working fine. But of course the goal is to capture the video frames and “play” it on a texture. (yes, i know there are plugins that do this already).
I can change the video frame to be all blue, and it will display OUTSIDE of app as a blue screen video…
OK here is the capture frame function. Now one thing I noticed is that this is apparently called in the same thread the Tick() function gets called in so that I can do this with no problems…no need to lock texture…(NOTE this is not the Tick() function but my callback function. It works with no problems…exactly like Tick() version. Both TIck and Sample functions update the texture of material inside of Unreal app…not outside app.
void AWebCam::SampleCB(double SampleTime, IMediaSample* pSample)
{
if ((x++ % (30 * 5)) == 0)
{
if (ImageSwitch)
WebcameraTexture = Tex01;
else
WebcameraTexture = Tex02;
ImageSwitch = !ImageSwitch;
}
}
So here is actual function…I want to “play” a blue texture onto material inside of Unreal app. When that works, I will of course replace it with the actual image data from the video. This is code I grabbed from a dozen or more examples of the same thing…
void AWebCam::SampleCB(double SampleTime, IMediaSample* pSample)
{
HRESULT hr;
unsigned char* Buffer;
hr = pSample->GetPointer((BYTE**)&Buffer); // ACTUAL VIDEO FRAME (NOT USED YET)
if (hr != S_OK)
return;
// FILL BRGA BUFFER WITH BLUE COLOR
int32 w = Width;
int32 h = Height;
TArray<FColor> rawData;
for (int32 i = 0; i < (w * h); i++)
rawData.Add(FColor(0xFF, 0x00, 0x00, 0xFF));
// MAKE LOCAL TEXTURE OBJECT, LOCK IT
UTexture2D* texture = UTexture2D::CreateTransient(w, h);
FTexture2DMipMap& Mip = texture->PlatformData->Mips[0];
void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);
// BLIT THE BLUE DATA INTO TEXTURE
FMemory::Memcpy(Data, rawData.GetData(), (w * h * 4));
// UNLOCK
Mip.BulkData.Unlock();
//texture->UpdateResource(); // IF I UNCOMMENT THIS, IT THROWS AN EXCEPTION.
//WebcameraTexture = texture; // IF I UNCOMMENT THIS...NOTHING GETS UPDATED (IN THIS CASE TURNS BLUE
}
I have seen a dozen examples that are essentially the thing and done this way.
For some reason it is not working. What is wrong? Also, since I am running in same thread as Tick() function(called at different times of course), do I need to Lock anything at all?