Skip to content

Instantly share code, notes, and snippets.

@icywind
Created December 10, 2019 04:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save icywind/41fcbbac76ed119c641820802be8531e to your computer and use it in GitHub Desktop.
Save icywind/41fcbbac76ed119c641820802be8531e to your computer and use it in GitHub Desktop.
Updated version of VideoSurface to use RawImage for rendering.
using UnityEngine;
using System.Runtime.InteropServices;
using UnityEngine.UI;
/**!! This version of the script is non-official. use it on your own risk! */
/*
* This example script demonstrates how to attachThis example
* video content to a 3D object (chenzhenyong@agora.io)
*
* Agora engine outputs one local preview video and some
* remote user video. User ID (int) is used to identify
* these video streams. 0 is used for local preview video
* stream, and other value stands for remote user video
* stream.
*/
public enum AgoraVideoSurfaceType
{
Renderer,
RawImage
};
public class VideoSurface : MonoBehaviour
{
private System.IntPtr data = Marshal.AllocHGlobal(1920 * 1080 * 4);
private int defWidth = 0;
private int defHeight = 0;
private Texture2D nativeTexture;
[SerializeField]
AgoraVideoSurfaceType VideoSurfaceType = AgoraVideoSurfaceType.Renderer;
/* only one of the following should be set, depends on VideoSurfaceType */
private Renderer mRenderer = null;
private RawImage mRawImage = null;
private bool _initialized = false;
void Start()
{
// render video
if (VideoSurfaceType == AgoraVideoSurfaceType.Renderer)
{
mRenderer = GetComponent<Renderer>();
}
if (mRenderer == null || VideoSurfaceType == AgoraVideoSurfaceType.RawImage)
{
mRawImage = GetComponent<RawImage>();
if (mRawImage != null)
{
// the variable may have been set to default enum but actually it is a RawImage
VideoSurfaceType = AgoraVideoSurfaceType.RawImage;
}
}
if (mRawImage == null && mRenderer == null)
{
Debug.LogError("Unable to find surface render in VideoSurface component.");
}
else
{
_initialized = true;
}
}
bool IsBlankTexture()
{
if (VideoSurfaceType == AgoraVideoSurfaceType.Renderer)
{
// if never assigned or assigned texture is not Texture2D, we will consider it blank and create a new one
return (mRenderer.material.mainTexture == null || !(mRenderer.material.mainTexture is Texture2D));
}
else
{
return (mRawImage.texture == null);
}
}
/// <summary>
/// nativeTexture at the calling point should have created with image data. This method
/// apply this reference to the surface renderer.
/// </summary>
void ApplyTexture()
{
if (VideoSurfaceType == AgoraVideoSurfaceType.Renderer)
{
mRenderer.material.mainTexture = nativeTexture;
}
else
{
mRawImage.texture = nativeTexture;
}
}
// Update is called once per frame
void Update()
{
agora_gaming_rtc.IRtcEngine engine = agora_gaming_rtc.IRtcEngine.QueryEngine();
if (engine == null || !_initialized)
{
return;
}
uint uid = mUid;
#if UNITY_STANDALONE_WIN || UNITY_EDITOR || UNITY_EDITOR_OSX || UNITY_STANDALONE_OSX || UNITY_ANDROID || UNITY_IOS || UNITY_IPHONE
if (mEnable)
{
// create texture if not existent
if ( IsBlankTexture() )
{
int tmpi = engine.UpdateTexture(0, uid, data, ref defWidth, ref defHeight);
if (tmpi == -1) {
return;
}
if (defWidth > 0 && defHeight > 0)
{
try
{
// create Texture in the first time update data
nativeTexture = new Texture2D((int)defWidth, (int)defHeight, TextureFormat.RGBA32, false);
nativeTexture.LoadRawTextureData(data, (int)defWidth * (int)defHeight * 4);
nativeTexture.Apply();
ApplyTexture();
}
catch (System.Exception e)
{
Debug.Log("Exception e = " + e);
}
}
}
else
{
int width = 0;
int height = 0;
int tmpi = engine.UpdateTexture(0, uid, data, ref width, ref height);
if (tmpi == -1) {
return;
}
if (width == defWidth && height == defHeight)
{
// Note that nativeTexture is being referenced in the renderer/raw image's texture.
// updating nativeTexture is updating renderer or raw image.
try
{
/*
* if width and height don't change, we only need to update data for texture, do not need to create Texture.
*/
nativeTexture.LoadRawTextureData(data, (int)width * (int)height * 4);
nativeTexture.Apply();
}
catch (System.Exception e)
{
Debug.Log("Exception e = " + e);
}
} else if (width > 0 && height > 0) {
try
{
/*
* if width or height changed, we need to create new texture.
*/
defWidth = width;
defHeight = height;
ApplyTexture();
}
catch (System.Exception e)
{
Debug.Log("Exception e = " + e);
Debug.LogWarning("Exception, got width = " + width + " height = " + height);
}
}
}
}
else // not mEnabled
{
nativeTexture = null;
ApplyTexture();
}
#endif
}
void OnDestroy()
{
Marshal.FreeHGlobal(data);
Debug.Log("VideoSurface Destroyed.");
}
// call this to render video stream from uid on this game object
public void SetForUser(uint uid)
{
mUid = uid;
Debug.Log("Set uid " + uid + " for gameObject" + gameObject.name);
}
/*
* if enable = true, the video will render. if enable = false, the video will stop render.
*/
public void SetEnable(bool enable)
{
mEnable = enable;
}
public void ResetTexture()
{
nativeTexture = new Texture2D ((int)defWidth, (int)defHeight, TextureFormat.RGBA32, false);
}
/*
* uid = 0, it means yourself but not others, you can get others uid by Agora Engine CallBack onUserJoined.
*/
private uint mUid = 0;
/*
*if disabled, then no rendering happens
*/
private bool mEnable = true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment