这是使用openGL 和appsrc 执行此操作的一种可能方法。
有关更多详细信息,请参阅 GitHub 上的 Unity low-level native plug-in interface documentation 和相应的 source code。还有一个很好的tutorial 介绍如何使用appsrc。
这里是需要做的简短总结:
统一(c#)
在 Unity 部分,您必须获取相机,创建 RenderTexture 并将其分配给相机。然后你必须将该纹理的GetNativeTexturePtr 提供给你的原生插件。以下是代码中最相关的部分:
...
[DllImport("YourPluginName")]
private static extern IntPtr GetRenderEventFunc();
[DllImport("YourPluginName")]
private static extern void SetTextureFromUnity(System.IntPtr texture, int w, int h);
...
IEnumerator Start()
{
CreateTextureAndPassToPlugin();
yield return StartCoroutine("CallPluginAtEndOfFrames");
}
private void CreateTextureAndPassToPlugin()
{
// get main camera and set its size
m_MainCamera = Camera.main;
m_MainCamera.pixelRect = new Rect(0, 0, 512, 512);
// create RenderTexture and assign it to the main camera
m_RenderTexture = new RenderTexture(m_MainCamera.pixelWidth, m_MainCamera.pixelHeight, 24, RenderTextureFormat.ARGB32);
m_RenderTexture.Create();
m_MainCamera.targetTexture = m_RenderTexture;
m_MainCamera.Render();
// Pass texture pointer to the plugin
SetTextureFromUnity(m_RenderTexture.GetNativeTexturePtr(), m_RenderTexture.width, m_RenderTexture.height);
}
private IEnumerator CallPluginAtEndOfFrames()
{
while(true)
{
// Wait until all frame rendering is done
yield return new WaitForEndOfFrame();
// Issue a plugin event with arbitrary integer identifier.
GL.IssuePluginEvent(GetRenderEventFunc(), m_EventID);
}
}
本机插件 (c++)
在这里,您必须存储纹理句柄,然后访问渲染线程上的像素数据,例如:
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API SetTextureFromUnity(void* textureHandle, int w, int h)
{
g_TextureHandle = textureHandle;
g_TextureWidth = w;
g_TextureHeight = h;
}
static void OnRenderEvent(int eventID)
{
uint32_t uiSize = g_TextureWidth * g_TextureHeight * 4; // RGBA = 4
unsigned char* pData = new unsigned char[uiSize];
GLuint gltex = (GLuint)(size_t)(g_TextureHandle);
glBindTexture(GL_TEXTURE_2D, gltex);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pData);
// now we have our pixel data in memory, we can now feed appsrc with it
...
}
extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFunc()
{
return OnRenderEvent;
}
一旦获得像素数据,您就可以将其包装到 GstBuffer 并使用 push-buffer 信号输入您的管道:
GstBuffer* pTextureBuffer = gst_buffer_new_wrapped(pData, uiSize);
...
g_signal_emit_by_name(pAppsrc, "push-buffer", pTextureBuffer, ...);
如果有人知道如何直接向管道提供 openGL 纹理句柄(无需将其复制到 RAM 中),我将不胜感激。