Skip to content

Instantly share code, notes, and snippets.

@icywind
Last active April 16, 2021 00:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save icywind/329b42b9525a5fd3b1579bb2731f86bf to your computer and use it in GitHub Desktop.
Save icywind/329b42b9525a5fd3b1579bb2731f86bf to your computer and use it in GitHub Desktop.
Use external video source to push video frame
#region =========== Push Video =================
public const TextureFormat ConvertFormat = TextureFormat.BGRA32; // RGBA will be compatible with Web
public const VIDEO_PIXEL_FORMAT PixelFormat = VIDEO_PIXEL_FORMAT.VIDEO_PIXEL_BGRA; // note: RGBA is available from v3.0.1 and on
Texture2D BufferTexture;
bool _isRunning;
IEnumerator CoShareRenderData()
{
if (ARCamera == null)
{
Debug.LogWarning("AR Camera is not present!");
yield break;
}
while (_isRunning)
{
yield return new WaitForEndOfFrame();
ShareRenderTexture();
}
Debug.LogWarning("CoShareRenderData ended.");
yield return null;
}
/// <summary>
/// Get the image from renderTexture. (AR Camera must assign a RenderTexture prefab in
/// its renderTexture field.)
/// </summary>
private void ShareRenderTexture()
{
RenderTexture.active = ARCamera.targetTexture; // the targetTexture holds render texture
Rect rect = new Rect(0, 0, ARCamera.targetTexture.width, ARCamera.targetTexture.height);
BufferTexture = new Texture2D(ARCamera.activeTexture.width, ARCamera.activeTexture.height, ConvertFormat, false);
BufferTexture.ReadPixels(rect, 0, 0);
BufferTexture.Apply();
byte[] bytes = BufferTexture.GetRawTextureData();
// sends the Raw data contained in bytes
StartCoroutine(PushFrame(bytes, (int)rect.width, (int)rect.height,
() =>
{
bytes = null;
Destroy(BufferTexture);
}));
RenderTexture.active = null;
}
int frameCnt = 0; // monotonic timestamp counter
/// <summary>
/// Push frame to the remote client. This is the same code that does ScreenSharing.
/// </summary>
/// <param name="bytes">raw video image data</param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="onFinish">callback upon finish of the function</param>
/// <returns></returns>
IEnumerator PushFrame(byte[] bytes, int width, int height, System.Action onFinish)
{
if (bytes == null || bytes.Length == 0)
{
Debug.LogError("Zero bytes found!!!!");
yield break;
}
IRtcEngine rtc = IRtcEngine.QueryEngine();
//if the engine is present
if (rtc != null)
{
//Create a new external video frame
ExternalVideoFrame externalVideoFrame = new ExternalVideoFrame();
//Set the buffer type of the video frame
externalVideoFrame.type = ExternalVideoFrame.VIDEO_BUFFER_TYPE.VIDEO_BUFFER_RAW_DATA;
// Set the video pixel format
externalVideoFrame.format = PixelFormat;
//apply raw data you are pulling from the rectangle you created earlier to the video frame
externalVideoFrame.buffer = bytes;
//Set the width of the video frame (in pixels)
externalVideoFrame.stride = width;
//Set the height of the video frame
externalVideoFrame.height = height;
//Remove pixels from the sides of the frame
externalVideoFrame.cropLeft = 10;
externalVideoFrame.cropTop = 10;
externalVideoFrame.cropRight = 10;
externalVideoFrame.cropBottom = 10;
//Rotate the video frame (0, 90, 180, or 270)
//externalVideoFrame.rotation = 90;
externalVideoFrame.rotation = 180;
// increment i with the video timestamp
externalVideoFrame.timestamp = frameCnt++;
//Push the external video frame with the frame we just created
int a =
rtc.PushVideoFrame(externalVideoFrame);
if (frameCnt % 500 == 0) Debug.Log(" pushVideoFrame(" + frameCnt + ") size:" + bytes.Length + " => " + a);
}
if (onFinish != null)
{
onFinish();
}
yield return null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment