Download

Converting a CaptureComponent2D's view to an array of JPEG data

Hi there!

I have smelted some random code together to get JPEG data from a RenderTarget from a CaptureComponent. It worked but it was causing the memory usage to grow wild as was calling this blueprint node in a frequent loop. The last two lines seem to prevent “memory leaks” (if it’s called that way):



OutTexture->ReleaseResource();
delete Data;


Personally, I have very little idea what’s going on in the code (typical blueprint guy). It took me hours to figure these two lines out. The problem now is that with the delete Data line addition, the editor crashes whenever I hit the “stop” button after “play in the editor”. Any ideas why is that and how to fix it?



bool UConstructFunctionLibrary::RenderTargetToStreamableFrame(UTextureRenderTarget2D* InTexture, TArray<uint8>& OutBuffer)
{
    FVector2D TextureSize = FVector2D(InTexture->SizeX, InTexture->SizeY);
    FTextureRenderTargetResource* RenderTargetRessource = InTexture->GameThread_GetRenderTargetResource();
    TArray<FColor> Pixels;
    RenderTargetRessource->ReadPixels(Pixels);

    UTexture2D* OutTexture = UTexture2D::CreateTransient(TextureSize.X, TextureSize.Y, EPixelFormat::PF_A32B32G32R32F);
    //OutTexture->UpdateResource();
    FTexture2DMipMap& Mip = OutTexture->PlatformData->Mips[0];
    void* Data = Mip.BulkData.Lock(LOCK_READ_WRITE);
    FMemory::Memcpy(Data, Pixels.GetData(), (TextureSize.X * TextureSize.Y * 4));
    Mip.BulkData.Unlock();
    OutTexture->UpdateResource();

    if (!OutTexture || !OutTexture->IsValidLowLevel())
    {
        UE_LOG(LogTemp, Error, TEXT("RenderTargetToStreamableFrame: Texture NULL or IsValidLowLevel == false"));
        return false;
    }

    //Get our wrapper module
    IImageWrapperModule& ImageWrapperModule = FModuleManager::LoadModuleChecked<IImageWrapperModule>(FName("ImageWrapper"));
    TSharedPtr<IImageWrapper> ImageWrapper = ImageWrapperModule.CreateImageWrapper(EImageFormat::JPEG);

    int32 Width = OutTexture->PlatformData->Mips[0].SizeX;
    int32 Height = OutTexture->PlatformData->Mips[0].SizeY;
    int32 DataLength = Width * Height * 4;

    void* TextureDataPointer = OutTexture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_ONLY);

    ImageWrapper->SetRaw(TextureDataPointer, DataLength, Width, Height, ERGBFormat::BGRA, 8);

    //This part can take a while, has performance implications
    OutBuffer = ImageWrapper->GetCompressed();

    OutTexture->PlatformData->Mips[0].BulkData.Unlock();

    ImageWrapper.Reset();

    OutTexture->ReleaseResource();
    delete Data;

    return true;
}


The crash report says:



LoginId:ccf57d8e45cd04e2702ff9a5a932250c
EpicAccountId:fa7ef2bacbf3487eaad1c86de97ea9b9

Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x0000018bc0203178

UE4Editor_Core
UE4Editor_Core
UE4Editor_Core
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_Engine
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_CoreUObject
UE4Editor_UnrealEd
UE4Editor_UnrealEd
UE4Editor_UnrealEd
UE4Editor
UE4Editor
UE4Editor
UE4Editor
UE4Editor
kernel32
ntdll