【问题标题】:Stream Unity RenderTexture to Gstreamer将 Unity RenderTexture 流式传输到 Gstreamer
【发布时间】:2019-09-16 16:11:28
【问题描述】:

我想将相机视图导出到实现 GStreamer 管道的本机插件,该管道通过网络对渲染的纹理进行编码和流式传输到 Web 浏览器。我做了一些研究,发现最好的方法可能是在 Unity 中使用RenderTexture

但是,我不明白如何在本机插件中将此 RenderTexture 与 GStreamer 接口。我需要为此编写自己的 GStreamer 源元素吗?如果是,什么是一个好的起点?或者还有其他更直接的解决方案可以将 Unity 中的 Camera 视图导出到 GStreamer 中吗?

【问题讨论】:

    标签: unity3d gstreamer


    【解决方案1】:

    这是使用openGLappsrc 执行此操作的一种可能方法。 有关更多详细信息,请参阅 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 中),我将不胜感激。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-24
      • 2013-04-13
      • 1970-01-01
      • 2016-06-13
      • 1970-01-01
      • 2011-11-22
      • 2019-01-26
      • 2011-12-04
      相关资源
      最近更新 更多