// DO NOT EDIT! This is an autogenerated file. All changes will be
// overwritten!

//	Copyright (c) 2023 Vidyo, Inc. All rights reserved.


using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;

namespace VidyoClient
{
	/// <summary>
	/// This object represents a camera which belongs to the remote participant.
	/// </summary>
	public class RemoteCamera: IDisposable {
		private bool disposed = false; 
#if __IOS__
		const string importLib = "__Internal";
#else
		const string importLib = "libVidyoClient";
#endif
		private IntPtr objPtr; // opaque VidyoRemoteCamera reference.
		private GCHandle objHandle; // weak VidyoRemoteCamera reference.
		private List<WeakReference> objects = new List<WeakReference>();

		private void DisposeWeakReferenceObjects() {
			foreach(var item in objects) {
				if (item == null || !item.IsAlive || item.Target == null) { continue; }
				switch (item.Target.GetType().Name) {
					case "Participant": ((Participant)item.Target).Dispose(false); break;
				}
			}
			objects.Clear();
		}
		public IntPtr GetObjectPtr() {
			return objPtr;
		}
		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraActivatePresetNative(IntPtr c, uint index);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern ulong VidyoRemoteCameraAddToLocalRendererNative(IntPtr c, IntPtr localRenderer, [MarshalAs(UnmanagedType.I4)]RemoteCameraMode mode);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoRemoteCameraConstructCopyNative(IntPtr other);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraControlPTZNudgeNative(IntPtr c, int pan, int tilt, int zoom);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraControlPTZStartNative(IntPtr c, [MarshalAs(UnmanagedType.I4)]CameraControlCapabilities.CameraControlDirection direction, ulong timeout);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraControlPTZStopNative(IntPtr c);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern void VidyoRemoteCameraDestructNative(IntPtr obj);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoRemoteCameraGetControlCapabilitiesNative(IntPtr c);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoRemoteCameraGetIdNative(IntPtr c);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern ulong VidyoRemoteCameraGetLocalRenderingStreamIdNative(IntPtr c, int index);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoRemoteCameraGetNameNative(IntPtr c);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I4)]
		private static extern RemoteCameraPosition VidyoRemoteCameraGetPositionNative(IntPtr c);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraIsControllableNative(IntPtr c);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraRegisterFrameEventListenerNative(IntPtr c, OnRemoteCameraFrame onFrame);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraRegisterFrameSizeListenerNative(IntPtr c, OnFrameSizeUpdate onFrameSizeUpdate);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraRegisterPresetEventListenerNative(IntPtr c, OnPresetUpdated onPresetUpdated);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraRemoveFromLocalRendererNative(IntPtr c, IntPtr localRenderer);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraSetPositionInLocalRendererNative(IntPtr c, IntPtr localRenderer, int x, int y, uint width, uint height, ulong frameInterval);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraShowCameraControlNative(IntPtr c, Boolean show);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraUnregisterFrameEventListenerNative(IntPtr c);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraUnregisterFrameSizeListenerNative(IntPtr c);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraUnregisterPresetEventListenerNative(IntPtr c);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoRemoteCameraViscaControlNative(IntPtr c, IntPtr viscaCmd, IntPtr viscaCmdId);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		public static extern IntPtr VidyoRemoteCameraGetUserDataNative(IntPtr obj);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		public static extern void VidyoRemoteCameraSetUserDataNative(IntPtr obj, IntPtr userData);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void OnFrameSizeUpdate(IntPtr c, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SizeTMarshaler))]SizeT width, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SizeTMarshaler))]SizeT height);
		private OnFrameSizeUpdate _mOnFrameSizeUpdate = OnFrameSizeUpdateDelegate;
		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void OnPresetUpdated(IntPtr c, IntPtr presets);
		private OnPresetUpdated _mOnPresetUpdated = OnPresetUpdatedDelegate;
		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoRemoteCameraOnPresetUpdatedGetpresetsArrayNative(IntPtr obj, ref int size);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoRemoteCameraOnPresetUpdatedFreepresetsArrayNative(IntPtr obj, int size);

		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		private delegate void OnRemoteCameraFrame(IntPtr c, IntPtr participant, IntPtr videoFrame);
		private OnRemoteCameraFrame _mOnRemoteCameraFrame = OnRemoteCameraFrameDelegate;
		/// <summary>
		/// 
		/// </summary>
		public enum RemoteCameraMode {
			/// <summary></summary>
			RemotecameramodeDynamic,
			/// <summary></summary>
			RemotecameramodeStatic
		}
		/// <summary>
		/// Position of the camera.
		/// </summary>
		public enum RemoteCameraPosition {
			/// <summary>Position is unknown.</summary>
			RemotecamerapositionUnknown,
			/// <summary>Facing towards the screen.</summary>
			RemotecamerapositionFront,
			/// <summary>Facing away from the screen.</summary>
			RemotecamerapositionBack
		}
		public interface IRegisterFrameEventListener{

			void OnRemoteCameraFrame(Participant participant, VideoFrame videoFrame);
		}
		public interface IRegisterFrameSizeListener{

			void OnFrameSizeUpdate(SizeT width, SizeT height);
		}
		public interface IRegisterPresetEventListener{

			void OnPresetUpdated(List<CameraPreset> presets);
		}
		private IRegisterFrameEventListener _mIRegisterFrameEventListener;
		private IRegisterFrameSizeListener _mIRegisterFrameSizeListener;
		private IRegisterPresetEventListener _mIRegisterPresetEventListener;
		public RemoteCamera(IntPtr other){
			objPtr = VidyoRemoteCameraConstructCopyNative(other);
			if (objPtr != IntPtr.Zero) {
				objHandle = GCHandle.Alloc(this, GCHandleType.Weak);
				VidyoRemoteCameraSetUserDataNative(objPtr, GCHandle.ToIntPtr(objHandle));
			}
		}
		~RemoteCamera(){
			Dispose(false);
		}
		public void Dispose(){
			Dispose(true);
			GC.SuppressFinalize(this);
		}

		public void Dispose(bool disposing){
			if(disposed) return;

			disposed = true;
			DisposeWeakReferenceObjects();
			if(objPtr != IntPtr.Zero) {
				VidyoRemoteCameraSetUserDataNative(objPtr, IntPtr.Zero);
				VidyoRemoteCameraDestructNative(objPtr);
				objPtr = IntPtr.Zero;
			}

			if(objHandle.IsAllocated) objHandle.Free();
		}

		/// <summary>
		/// Send the preset index to the remote camera.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		/// <param name="index">Represents the preset index.</param>
		public Boolean ActivatePreset(uint index) {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteCameraActivatePresetNative(objPtr, index);

			return ret;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		/// <param name="localRenderer"></param>
		/// <param name="mode"></param>
		public ulong AddToLocalRenderer(LocalRenderer localRenderer, RemoteCameraMode mode) {
			if (objPtr == IntPtr.Zero) { return default; }

			ulong ret = VidyoRemoteCameraAddToLocalRendererNative(objPtr, (localRenderer != null) ? localRenderer.GetObjectPtr():IntPtr.Zero, mode);

			return ret;
		}
		/// <summary>
		/// Send the PTZ Nudge commands to the remote camera.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		/// <param name="pan">Number of nudges to pan the camera.</param>
		/// <param name="tilt">Number of nudges to tilt the camera.</param>
		/// <param name="zoom">Number of nudges to zoom the camera.</param>
		public Boolean ControlPTZNudge(int pan, int tilt, int zoom) {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteCameraControlPTZNudgeNative(objPtr, pan, tilt, zoom);

			return ret;
		}
		/// <summary>
		/// Send the PTZ Start commands to the remote camera.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		/// <param name="direction">The VidyoCameraControlDirection enum that indicates direction of move.</param>
		/// <param name="timeout">Amount of time in nanoseconds at which camera will be moving in the specified directions.</param>
		public Boolean ControlPTZStart(CameraControlCapabilities.CameraControlDirection direction, ulong timeout) {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteCameraControlPTZStartNative(objPtr, direction, timeout);

			return ret;
		}
		/// <summary>
		/// Send the PTZ Stop commands to the remote camera.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		public Boolean ControlPTZStop() {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteCameraControlPTZStopNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets camera control capabilities.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		public CameraControlCapabilities GetControlCapabilities() {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr ret = VidyoRemoteCameraGetControlCapabilitiesNative(objPtr);
			CameraControlCapabilities csRet = new CameraControlCapabilities(ret);

			return csRet;
		}
		/// <summary>
		/// Gets the unique ID of the camera.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		public String GetId() {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr ret = VidyoRemoteCameraGetIdNative(objPtr);

			return (string)MarshalPtrToUtf8.GetInstance().MarshalNativeToManaged(ret);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		/// <param name="index"></param>
		public ulong GetLocalRenderingStreamId(int index) {
			if (objPtr == IntPtr.Zero) { return default; }

			ulong ret = VidyoRemoteCameraGetLocalRenderingStreamIdNative(objPtr, index);

			return ret;
		}
		/// <summary>
		/// Gets the name of the camera.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		public String GetName() {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr ret = VidyoRemoteCameraGetNameNative(objPtr);

			return (string)MarshalPtrToUtf8.GetInstance().MarshalNativeToManaged(ret);
		}
		/// <summary>
		/// Gets the position of the camera.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		public RemoteCameraPosition GetPosition() {
			if (objPtr == IntPtr.Zero) { return default; }

			RemoteCameraPosition ret = VidyoRemoteCameraGetPositionNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Checks if the remote camera is controllable.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		public Boolean IsControllable() {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteCameraIsControllableNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Registers to get notified about a new remote camera frame.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		/// <param name="onFrame">Callback that is triggered each time a remote camera produces a video frame.</param>
		public Boolean RegisterFrameEventListener(IRegisterFrameEventListener _iIRegisterFrameEventListener) {
			if (objPtr == IntPtr.Zero) { return default; }
			_mIRegisterFrameEventListener = _iIRegisterFrameEventListener;

			Boolean ret = VidyoRemoteCameraRegisterFrameEventListenerNative(objPtr, _mOnRemoteCameraFrame);

			return ret;
		}
		/// <summary>
		/// Registers to get notified about camera frame size changes.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		/// <param name="onFrameSizeUpdate">Callback that is triggered whenever frame size changes.</param>
		public Boolean RegisterFrameSizeListener(IRegisterFrameSizeListener _iIRegisterFrameSizeListener) {
			if (objPtr == IntPtr.Zero) { return default; }
			_mIRegisterFrameSizeListener = _iIRegisterFrameSizeListener;

			Boolean ret = VidyoRemoteCameraRegisterFrameSizeListenerNative(objPtr, _mOnFrameSizeUpdate);

			return ret;
		}
		/// <summary>
		/// Registers a callback to receive notifications about camera preset information.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		/// <param name="onPresetUpdated">Callback that is triggered whenever camera preset information changes.</param>
		public Boolean RegisterPresetEventListener(IRegisterPresetEventListener _iIRegisterPresetEventListener) {
			if (objPtr == IntPtr.Zero) { return default; }
			_mIRegisterPresetEventListener = _iIRegisterPresetEventListener;

			Boolean ret = VidyoRemoteCameraRegisterPresetEventListenerNative(objPtr, _mOnPresetUpdated);

			return ret;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		/// <param name="localRenderer"></param>
		public Boolean RemoveFromLocalRenderer(LocalRenderer localRenderer) {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteCameraRemoveFromLocalRendererNative(objPtr, (localRenderer != null) ? localRenderer.GetObjectPtr():IntPtr.Zero);

			return ret;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		/// <param name="localRenderer"></param>
		/// <param name="x"></param>
		/// <param name="y"></param>
		/// <param name="width"></param>
		/// <param name="height"></param>
		/// <param name="frameInterval"></param>
		public Boolean SetPositionInLocalRenderer(LocalRenderer localRenderer, int x, int y, uint width, uint height, ulong frameInterval) {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteCameraSetPositionInLocalRendererNative(objPtr, (localRenderer != null) ? localRenderer.GetObjectPtr():IntPtr.Zero, x, y, width, height, frameInterval);

			return ret;
		}
		/// <summary>
		/// Shows camera control when rendering remote camera.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		/// <param name="show">Show or hide camera controls.</param>
		public Boolean ShowCameraControl(Boolean show) {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteCameraShowCameraControlNative(objPtr, show);

			return ret;
		}
		/// <summary>
		/// Unregisters remote camera frame notifications.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		public Boolean UnregisterFrameEventListener() {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteCameraUnregisterFrameEventListenerNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Unregisters frame size event notifications.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		public Boolean UnregisterFrameSizeListener() {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteCameraUnregisterFrameSizeListenerNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Unregisters callback to get notified about camera preset information.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		public Boolean UnregisterPresetEventListener() {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoRemoteCameraUnregisterPresetEventListenerNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Sends the visca message to the remote camera.
		/// </summary>
		/// <param name="c">The VidyoRemoteCamera object.</param>
		/// <param name="viscaCmd">Represents the visca command, with maximum length as 128 characters. This should be any valid visca command.For example: "81 01 04 3f 02 02 ff"</param>
		/// <param name="viscaCmdId">Represents the visca command identifier, with maximum length as 128 characters. Application can set NULL OR any valid string identifier, which can be used at remote end for debugging.</param>
		public Boolean ViscaControl(String viscaCmd, String viscaCmdId) {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr nViscaCmd = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(viscaCmd ?? string.Empty);
			IntPtr nViscaCmdId = MarshalPtrToUtf8.GetInstance().MarshalManagedToNative(viscaCmdId ?? string.Empty);
			Boolean ret = VidyoRemoteCameraViscaControlNative(objPtr, nViscaCmd, nViscaCmdId);
			Marshal.FreeHGlobal(nViscaCmdId);
			Marshal.FreeHGlobal(nViscaCmd);

			return ret;
		}
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(OnFrameSizeUpdate))]
#endif
		private static void OnFrameSizeUpdateDelegate(IntPtr c, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SizeTMarshaler))]SizeT width, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SizeTMarshaler))]SizeT height){
			var csCPtr = c != IntPtr.Zero ? VidyoRemoteCameraGetUserDataNative(c) : IntPtr.Zero;
			if(csCPtr == IntPtr.Zero) return;
			var csC = (RemoteCamera)GCHandle.FromIntPtr(csCPtr).Target;

			csC?._mIRegisterFrameSizeListener?.OnFrameSizeUpdate(width, height);
		}
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(OnPresetUpdated))]
#endif
		private static void OnPresetUpdatedDelegate(IntPtr c, IntPtr presets){
			var csCPtr = c != IntPtr.Zero ? VidyoRemoteCameraGetUserDataNative(c) : IntPtr.Zero;
			if(csCPtr == IntPtr.Zero) return;
			var csC = (RemoteCamera)GCHandle.FromIntPtr(csCPtr).Target;

			List<CameraPreset> csPresets = new List<CameraPreset>();
			var nPresetsSize = 0;
			var nPresets = VidyoRemoteCameraOnPresetUpdatedGetpresetsArrayNative(presets, ref nPresetsSize);
			var nPresetsIndex = 0;
			while (nPresetsIndex < nPresetsSize) {
				CameraPreset csTpresets = new CameraPreset(Marshal.ReadIntPtr(nPresets + (nPresetsIndex * Marshal.SizeOf(nPresets))));
				csPresets.Add(csTpresets);
				nPresetsIndex++;
			}

			csC?._mIRegisterPresetEventListener?.OnPresetUpdated(csPresets);
			VidyoRemoteCameraOnPresetUpdatedFreepresetsArrayNative(nPresets, nPresetsSize);
		}
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(OnRemoteCameraFrame))]
#endif
		private static void OnRemoteCameraFrameDelegate(IntPtr c, IntPtr participant, IntPtr videoFrame){
			var csCPtr = c != IntPtr.Zero ? VidyoRemoteCameraGetUserDataNative(c) : IntPtr.Zero;
			if(csCPtr == IntPtr.Zero) return;
			var csC = (RemoteCamera)GCHandle.FromIntPtr(csCPtr).Target;

			Participant csParticipant = null;
			if(participant != IntPtr.Zero) {
				var csParticipantPtr = Participant.VidyoParticipantGetUserDataNative(participant);
				if (csParticipantPtr == IntPtr.Zero) {
					csParticipant = new Participant(participant);
					if (csParticipant != null) {
						csC?.objects?.Add(new WeakReference(csParticipant));
					}
				} else {
					csParticipant = (Participant)GCHandle.FromIntPtr(csParticipantPtr).Target;
				}
			}

			VideoFrame csVideoFrame = null;
			if(videoFrame != IntPtr.Zero) {
				var csVideoFramePtr = VideoFrame.VidyoVideoFrameGetUserDataNative(videoFrame);
				csVideoFrame = csVideoFramePtr == IntPtr.Zero ? new VideoFrame(videoFrame) : (VideoFrame)GCHandle.FromIntPtr(csVideoFramePtr).Target;
			}

			csC?._mIRegisterFrameEventListener?.OnRemoteCameraFrame(csParticipant, csVideoFrame);
		}
	};
}
