Context:
I’m working on Zoom SDK integration in UE4. On the current step I’ve got a raw video data in YUVI420 format and try to show it inside a widget contains UImage. Base texture working code example get for RGB.
Questions:
- How to convert this YUV data to RGB?
- Should I use shaders for this purposes?
Any help will be appreciated
CODE:
void UVideoFrameWidget::NativeConstruct()
{
Super::NativeConstruct();
Width = 640;
Height = 360;
// Comment here
RenderTargetTexture = UTexture2D::CreateTransient(Width, Height, PF_R8G8B8A8);
RenderTargetTexture->UpdateResource();
BufferSize = Width * Height * 4;
Buffer = new uint8[BufferSize];
for (uint32 i = 0; i < Width * Height; ++i)
{
Buffer[i * 4 + 0] = 0x32;
Buffer[i * 4 + 1] = 0x32;
Buffer[i * 4 + 2] = 0x32;
Buffer[i * 4 + 3] = 0xFF;
}
UpdateTextureRegion = new FUpdateTextureRegion2D(0, 0, 0, 0, Width, Height);
RenderTargetTexture->UpdateTextureRegions(0, 1, UpdateTextureRegion, Width * 4, (uint32)4, Buffer);
Brush.SetResourceObject(RenderTargetTexture);
RenderTargetImage->SetBrush(Brush);
}
void UVideoFrameWidget::NativeTick(const FGeometry& MyGeometry, float DeltaTime)
{
Super::NativeTick(MyGeometry, DeltaTime);
FScopeLock lock(&Mutex);
if (UpdateTextureRegion->Width != Width || UpdateTextureRegion->Height != Height)
{
FUpdateTextureRegion2D* NewUpdateTextureRegion = new FUpdateTextureRegion2D(0, 0, 0, 0, Width, Height);
UTexture2D* NewRenderTargetTexture = UTexture2D::CreateTransient(Width, Height, PF_R8G8B8A8);
NewRenderTargetTexture->UpdateResource();
NewRenderTargetTexture->UpdateTextureRegions(0, 1, NewUpdateTextureRegion, Width * 4, (uint32)4, Buffer);
Brush.SetResourceObject(NewRenderTargetTexture);
RenderTargetImage->SetBrush(Brush);
//UClass's such as UTexture2D are automatically garbage collected when there is no hard pointer references made to that object.
//So if you just leave it and don't reference it elsewhere then it will be destroyed automatically.
const FUpdateTextureRegion2D* TmpUpdateTextureRegion = UpdateTextureRegion;
RenderTargetTexture = NewRenderTargetTexture;
UpdateTextureRegion = NewUpdateTextureRegion;
delete TmpUpdateTextureRegion;
return;
}
RenderTargetTexture->UpdateTextureRegions(0, 1, UpdateTextureRegion, Width * 4, (uint32)4, Buffer);
}
void UVideoFrameWidget::UpdateBuffer(FZoomVideoRawData Video)
{
if (!Video.Data)
{
return;
}
auto DataSize = Video.Data->GetStreamWidth() * Video.Data->GetStreamHeight() / 2;
UE_LOG(LogTemp, Warning, TEXT("Widget received data with width: %d, height: %d"), Video.Data->GetStreamWidth(), Video.Data->GetStreamHeight())
if (BufferSize == DataSize)
{
FMemory::Memcpy(Buffer, Video.Data->GetBuffer(), DataSize);
}
else
{
delete[] Buffer;
BufferSize = DataSize;
Width = Video.Data->GetStreamWidth();
Height = Video.Data->GetStreamHeight();
Buffer = new uint8[BufferSize];
FMemory::Memcpy(Buffer, Video.Data->GetBuffer(), DataSize);
}
}
void UVideoFrameWidget::ResetBuffer()
{
for (uint32 i = 0; i < Width * Height; ++i)
{
Buffer[i * 4 + 0] = 0x32;
Buffer[i * 4 + 1] = 0x32;
Buffer[i * 4 + 2] = 0x32;
Buffer[i * 4 + 3] = 0xFF;
}
}