c++ - 使用本机插件在 Unity3D 中将 YUV 转换为 RGB 的更好方法
问题描述
我有一个在 UI 上播放视频的 Unity3D 应用程序。我发现自己需要找到一种将 YUV 视频缓冲区转换为 RGB 缓冲区的更好方法。我的情况是这样的:
- 带有渲染视频的 UI 图像的Unity3D
- 实际播放视频的 Gstreamer 外部进程
- 一个原生插件,从 Unity3D 调用,用于将视频 YUV 缓冲区转换为 RGBA 缓冲区
我的 C++/Native 插件部分与 YUV->RGBA 转换相关的代码:
unsigned char * rgba = (unsigned char*) obj->g_RgbaBuff;
unsigned char * yuv = (unsigned char*) obj->g_Buffer;
while ( ta < obj->g_BufferLength)
{
int ty = (int)yuv[i];
int tu = (int)yuv[i + 1];
int tY2 = (int)yuv[i + 2];
int tv = (int)yuv[i + 3];
int tp1 = (int)(1.164f * (ty - 16));
int tr = Clamp((int)tp1 + 1.596f * (tv - 128));
int tg = Clamp((int)tp1 - 0.813f * (tv - 128) - 0.391f * (tu - 128));
int tb = Clamp((int)tp1 + 2.018f * (tu - 128));
rgba[ta] = tb;
rgba[ta + 1] = tg;
rgba[ta + 2] = tr;
ta += 4;
int tp2 = (int)(1.164f * (tY2 - 16));
int tr2 = Clamp((int)tp2 + 1.596f * (tv - 128));
int tg2 = Clamp((int)tp2 - 0.813f * (tv - 128) - 0.391f * (tu - 128));
int tb2 = Clamp((int)tp2 + 2.018f * (tu - 128));
rgba[ta] = tb2;
rgba[ta + 1] = tg2;
rgba[ta + 2] = tr2;
ta += 4;
}
Unity3D 在 while 循环中调用此代码以不断更新我的图像的输出,该图像正确显示了视频。问题是,它真的很慢。当我打开多个视频时,我的 FPS 从 60 下降到 30 以下,只有三个 720p 视频。有没有办法在 GPU 上做到这一点?或者更聪明的方式来做到这一点。我应该以不同的方式处理它吗?
要将缓冲区渲染为纹理,我在本机代码中使用此代码,每帧都使用 Unity GL.IssuePluginEvent() 进行渲染
static void ModifyTexturePixels(void* textureHandle, int w, int h, void* rgbaBuff)
{
int textureRowPitch;
glBindTexture(GL_TEXTURE_2D, (GLuint)(size_t)textureHandle);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, rgbaBuff);
}
解决方案
推荐阅读
- c# - 使用 Autofac 将 IServiceProvider 注入工厂类
- c++ - System.Runtime.InteropServices.SEHException 与最新的 Crystal Report Runtime SP27
- java - 更快地遍历地图并匹配键中的模式
- delphi - 如何在 DrawAllPoints:= false 时绘制每个像素、巨大 TeeChart FastLine 系列的最小值和最大值?
- c# - C#如何获取两个字符之间的字符串?升C
- sql - 如何在 CASE 语句中创建多个可能重叠的条件并使用 GROUP BY
- android - 是否可以加载非 AutoML 训练的 tflite 模型以在 Android 上与 FirebaseAutoMLLocalModel 一起使用?
- html - 启用 GPU 加速的 div 滚动
- sql-server - 我可以更改 SSMS 中的“执行程序”弹出窗口吗?
- python - 在 postgres/python 中转义单引号