// 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
{
	public class VideoFrameReleaseCallbackSingleton
		{
		[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
		public delegate void ReleaseCallback(IntPtr buffer, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SizeTMarshaler))]SizeT size, IntPtr alloc);
		public static ReleaseCallback _mReleaseCallback = releaseCallbackDelegate;
		private static Dictionary<IntPtr, VideoFrame.IConstructFromKnownFormatWithExternalBuffer> ReleaseCallbackMap = new Dictionary<IntPtr, VideoFrame.IConstructFromKnownFormatWithExternalBuffer>();
		private static Dictionary<IntPtr, GCHandle> GCHandleMap = new Dictionary<IntPtr, GCHandle>();
		private static Dictionary<IntPtr, byte[]> ByteArrayMap = new Dictionary<IntPtr, byte[]>();
		public static VideoFrame.IConstructFromKnownFormatWithExternalBuffer _mIConstructFromKnownFormatWithExternalBuffer;
		public static void addReleaseCallbackToMap(IntPtr buffer, ulong size, VideoFrame.IConstructFromKnownFormatWithExternalBuffer callback, GCHandle handle, byte[] byteArray)
		{
			ReleaseCallbackMap[buffer] = callback;
			GCHandleMap[buffer] = handle;
			ByteArrayMap[buffer] = byteArray;
		}
#if __IOS__
[ObjCRuntime.MonoPInvokeCallback(typeof(ReleaseCallback))]
#endif
		private static void releaseCallbackDelegate(IntPtr buffer, [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(SizeTMarshaler))]SizeT size, IntPtr alloc)
		{
			if (ReleaseCallbackMap[buffer] != null)
			{
				VideoFrame.IConstructFromKnownFormatWithExternalBuffer callback = ReleaseCallbackMap[buffer];
				GCHandle pinnedArray = GCHandleMap[buffer];
				callback.ReleaseCallback(ByteArrayMap[buffer], size);
				ByteArrayMap.Remove(buffer);
				ReleaseCallbackMap.Remove(buffer);
				pinnedArray.Free();
				GCHandleMap.Remove(buffer);
			}
		}
	};
	/// <summary>
	/// This object represents a video frame.
	/// </summary>
	public class VideoFrame: IDisposable {
		private bool disposed = false; 
#if __IOS__
		const string importLib = "__Internal";
#else
		const string importLib = "libVidyoClient";
#endif
		private IntPtr objPtr; // opaque VidyoVideoFrame reference.
		private GCHandle objHandle; // weak VidyoVideoFrame reference.
		public IntPtr GetObjectPtr() {
			return objPtr;
		}
		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoVideoFrameConstructCopyNative(IntPtr other);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr VidyoVideoFrameConstructFromKnownFormatWithExternalBufferNative([MarshalAs(UnmanagedType.I4)]MediaFormat format, IntPtr buffer, uint size, VideoFrameReleaseCallbackSingleton.ReleaseCallback releaseCallback, uint width, uint height);

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

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

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

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

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

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern ulong VidyoVideoFrameGetElapsedTimeNative(IntPtr f);

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

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetHeightNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetHeightCbNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetHeightCrNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetHeightYNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetOffsetCbNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetOffsetCrNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetOffsetYNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetPitchCbNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetPitchCrNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetPitchYNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetSizeNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetSizeCbNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetSizeCrNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetSizeYNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern ulong VidyoVideoFrameGetTimestampNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetWidthNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetWidthCbNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetWidthCrNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		private static extern uint VidyoVideoFrameGetWidthYNative(IntPtr f);

		[DllImport(importLib, CallingConvention = CallingConvention.Cdecl)]
		[return: MarshalAs(UnmanagedType.I1)]
		private static extern Boolean VidyoVideoFrameSetTimePropertiesNative(IntPtr f, ulong elapsedTime, ulong timestamp);

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

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

		public interface IConstructFromKnownFormatWithExternalBuffer{

			void ReleaseCallback(byte[] buffer, SizeT size);
		}
		private IConstructFromKnownFormatWithExternalBuffer _mIConstructFromKnownFormatWithExternalBuffer;
		/// <summary>
		/// Constructs a video frame with externally-allocated memory to hold the frame's pixel data.
		/// </summary>
		/// <param name="x">A video frame object to construct.</param>
		/// <param name="format">The media format of the video frame.</param>
		/// <param name="buffer">A pointer to externally allocated memory that holds the pixel data.</param>
		/// <param name="size">The size, in bytes, of the frame data.</param>
		/// <param name="bufferAlloc">External allocator for frame-buffer data.</param>
		/// <param name="releaseCallback">A callback to be called on when external buffer may be reclaimed.</param>
		/// <param name="width">The width of the video media frame in pixels.</param>
		/// <param name="height">The height of the video media frame in pixels.</param>
		/// <param name="alloc">An allocator for non-frame-buffer data.</param>
		public VideoFrame(MediaFormat format, byte[] buffer, uint size, IConstructFromKnownFormatWithExternalBuffer _iIConstructFromKnownFormatWithExternalBuffer, uint width, uint height) {
			GCHandle pinnedArray = GCHandle.Alloc(buffer, GCHandleType.Pinned);
			IntPtr pointer = pinnedArray.AddrOfPinnedObject();
			VideoFrameReleaseCallbackSingleton.addReleaseCallbackToMap(pointer, size, _iIConstructFromKnownFormatWithExternalBuffer, pinnedArray, buffer);


			objPtr = VidyoVideoFrameConstructFromKnownFormatWithExternalBufferNative(format, pointer, size, VideoFrameReleaseCallbackSingleton._mReleaseCallback, width, height);
			objHandle = GCHandle.Alloc(this, GCHandleType.Weak);
			if (objPtr != IntPtr.Zero) {
				VidyoVideoFrameSetUserDataNative(objPtr, GCHandle.ToIntPtr(objHandle));
			}
		}
		public VideoFrame(IntPtr other){
			objPtr = VidyoVideoFrameConstructCopyNative(other);
			if (objPtr != IntPtr.Zero) {
				objHandle = GCHandle.Alloc(this, GCHandleType.Weak);
				VidyoVideoFrameSetUserDataNative(objPtr, GCHandle.ToIntPtr(objHandle));
			}
		}
		~VideoFrame(){
			Dispose(false);
		}
		public void Dispose(){
			Dispose(true);
			GC.SuppressFinalize(this);
		}

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

			disposed = true;
			if(objPtr != IntPtr.Zero) {
				VidyoVideoFrameSetUserDataNative(objPtr, IntPtr.Zero);
				VidyoVideoFrameDestructNative(objPtr);
				objPtr = IntPtr.Zero;
			}

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

		public byte[] GetData() {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr nativeData = VidyoVideoFrameGetDataNative(objPtr);
			int length = (int)VidyoVideoFrameGetSizeNative(objPtr);
			byte[] ret = new byte[length];
			Marshal.Copy(nativeData, ret, 0, length);

			return ret;
		}
		public byte[] GetDataCb() {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr nativeData = VidyoVideoFrameGetDataCbNative(objPtr);
			int length = (int)VidyoVideoFrameGetSizeCbNative(objPtr);
			byte[] ret = new byte[length];
			Marshal.Copy(nativeData, ret, 0, length);

			return ret;
		}
		public byte[] GetDataCr() {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr nativeData = VidyoVideoFrameGetDataCrNative(objPtr);
			int length = (int)VidyoVideoFrameGetSizeCrNative(objPtr);
			byte[] ret = new byte[length];
			Marshal.Copy(nativeData, ret, 0, length);

			return ret;
		}
		public byte[] GetDataY() {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr nativeData = VidyoVideoFrameGetDataYNative(objPtr);
			int length = (int)VidyoVideoFrameGetSizeYNative(objPtr);
			byte[] ret = new byte[length];
			Marshal.Copy(nativeData, ret, 0, length);

			return ret;
		}
		/// <summary>
		/// Gets the elapsed time since the beginning of frame capture that is increased by the duration of each frame.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public ulong GetElapsedTime() {
			if (objPtr == IntPtr.Zero) { return default; }

			ulong ret = VidyoVideoFrameGetElapsedTimeNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the format of the frame.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public String GetFormat() {
			if (objPtr == IntPtr.Zero) { return default; }

			IntPtr ret = VidyoVideoFrameGetFormatNative(objPtr);

			return (string)MarshalPtrToUtf8.GetInstance().MarshalNativeToManaged(ret);
		}
		/// <summary>
		/// Gets the height of the frame.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetHeight() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetHeightNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the height in bytes of the frame's Cb pixel data.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetHeightCb() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetHeightCbNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the height in bytes of the frame's Cr pixel data.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetHeightCr() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetHeightCrNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the height in bytes of the frame's Y pixel data.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetHeightY() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetHeightYNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the number of bytes from the Cb plane's payload to the start of the pixel data.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetOffsetCb() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetOffsetCbNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the number of bytes from the Cr plane's payload to the start of the pixel data.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetOffsetCr() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetOffsetCrNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the number of bytes from the Y plane's payload to the start of the pixel data.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetOffsetY() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetOffsetYNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the number of bytes between consecutive pixels in a row of the Cb plane.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetPitchCb() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetPitchCbNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the number of bytes between consecutive pixels in a row of the Cr plane.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetPitchCr() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetPitchCrNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the number of bytes between consecutive pixels in a row of the Y plane
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetPitchY() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetPitchYNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the size in bytes of the frame's payload.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetSize() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetSizeNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the size in bytes of the plane's payload.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetSizeCb() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetSizeCbNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the size in bytes of the Cr plane's payload.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetSizeCr() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetSizeCrNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the size in bytes of the plane's payload.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetSizeY() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetSizeYNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the wallclock timestamp associated with the creation of the audio frame object.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public ulong GetTimestamp() {
			if (objPtr == IntPtr.Zero) { return default; }

			ulong ret = VidyoVideoFrameGetTimestampNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the width of the frame.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetWidth() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetWidthNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the width in bytes of the frame's Cb pixel data.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetWidthCb() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetWidthCbNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the width in bytes of the frame's Cr pixel data.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetWidthCr() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetWidthCrNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Gets the width in bytes of the frame's Y pixel data.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		public uint GetWidthY() {
			if (objPtr == IntPtr.Zero) { return default; }

			uint ret = VidyoVideoFrameGetWidthYNative(objPtr);

			return ret;
		}
		/// <summary>
		/// Sets elapsedTime and timestamp of the video frame. In case elapsedTime and timestamp are equal to zero will set current monotonic and wall time.
		/// </summary>
		/// <param name="f">The VidyoVideoFrame object.</param>
		/// <param name="elapsedTime">The elapsed time of the video frame. If zero will set current monotonic time.</param>
		/// <param name="timestamp">Video frame timestamp. If zero will set current wall time.</param>
		public Boolean SetTimeProperties(ulong elapsedTime, ulong timestamp) {
			if (objPtr == IntPtr.Zero) { return default; }

			Boolean ret = VidyoVideoFrameSetTimePropertiesNative(objPtr, elapsedTime, timestamp);

			return ret;
		}
	};
}
