// This file was generated by the Gtk# code generator.
// Any changes made will be lost if regenerated.

namespace Gst.Video {

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

#region Autogenerated code
	[StructLayout(LayoutKind.Sequential)]
	public partial struct VideoCodecFrame : IEquatable<VideoCodecFrame> {

		private int ref_count;
		private uint flags;
		public uint SystemFrameNumber;
		private uint decode_frame_number;
		private uint presentation_frame_number;
		public ulong Dts;
		public ulong Pts;
		public ulong Duration;
		public int DistanceFromSync;
		private IntPtr _input_buffer;
		public Gst.Buffer InputBuffer {
			get {
				return _input_buffer == IntPtr.Zero ? null : (Gst.Buffer) GLib.Opaque.GetOpaque (_input_buffer, typeof (Gst.Buffer), false);
			}
			set {
				_input_buffer = value == null ? IntPtr.Zero : value.Handle;
			}
		}
		private IntPtr _output_buffer;
		public Gst.Buffer OutputBuffer {
			get {
				return _output_buffer == IntPtr.Zero ? null : (Gst.Buffer) GLib.Opaque.GetOpaque (_output_buffer, typeof (Gst.Buffer), false);
			}
			set {
				_output_buffer = value == null ? IntPtr.Zero : value.Handle;
			}
		}
		public ulong Deadline;
		private IntPtr _events;
		private IntPtr _user_data;
		private GLib.DestroyNotify user_data_destroy_notify;

		public static Gst.Video.VideoCodecFrame Zero = new Gst.Video.VideoCodecFrame ();

		public static Gst.Video.VideoCodecFrame New(IntPtr raw) {
			if (raw == IntPtr.Zero)
				return Gst.Video.VideoCodecFrame.Zero;
			return (Gst.Video.VideoCodecFrame) Marshal.PtrToStructure (raw, typeof (Gst.Video.VideoCodecFrame));
		}

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_video_codec_frame_get_type();

		public static GLib.GType GType { 
			get {
				IntPtr raw_ret = gst_video_codec_frame_get_type();
				GLib.GType ret = new GLib.GType(raw_ret);
				return ret;
			}
		}

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_video_codec_frame_ref(IntPtr raw);

		public Gst.Video.VideoCodecFrame Ref() {
			IntPtr this_as_native = System.Runtime.InteropServices.Marshal.AllocHGlobal (System.Runtime.InteropServices.Marshal.SizeOf (this));
			System.Runtime.InteropServices.Marshal.StructureToPtr (this, this_as_native, false);
			IntPtr raw_ret = gst_video_codec_frame_ref(this_as_native);
			Gst.Video.VideoCodecFrame ret = Gst.Video.VideoCodecFrame.New (raw_ret);
			ReadNative (this_as_native, ref this);
			System.Runtime.InteropServices.Marshal.FreeHGlobal (this_as_native);
			return ret;
		}

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_video_codec_frame_set_user_data(IntPtr raw, IntPtr user_data, GLib.DestroyNotify notify);

		public void SetUserData(IntPtr user_data, GLib.DestroyNotify notify) {
			IntPtr this_as_native = System.Runtime.InteropServices.Marshal.AllocHGlobal (System.Runtime.InteropServices.Marshal.SizeOf (this));
			System.Runtime.InteropServices.Marshal.StructureToPtr (this, this_as_native, false);
			gst_video_codec_frame_set_user_data(this_as_native, user_data, notify);
			ReadNative (this_as_native, ref this);
			System.Runtime.InteropServices.Marshal.FreeHGlobal (this_as_native);
		}

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_video_codec_frame_unref(IntPtr raw);

		public void Unref() {
			IntPtr this_as_native = System.Runtime.InteropServices.Marshal.AllocHGlobal (System.Runtime.InteropServices.Marshal.SizeOf (this));
			System.Runtime.InteropServices.Marshal.StructureToPtr (this, this_as_native, false);
			gst_video_codec_frame_unref(this_as_native);
			ReadNative (this_as_native, ref this);
			System.Runtime.InteropServices.Marshal.FreeHGlobal (this_as_native);
		}

		static void ReadNative (IntPtr native, ref Gst.Video.VideoCodecFrame target)
		{
			target = New (native);
		}

		public bool Equals (VideoCodecFrame other)
		{
			return true && ref_count.Equals (other.ref_count) && flags.Equals (other.flags) && SystemFrameNumber.Equals (other.SystemFrameNumber) && decode_frame_number.Equals (other.decode_frame_number) && presentation_frame_number.Equals (other.presentation_frame_number) && Dts.Equals (other.Dts) && Pts.Equals (other.Pts) && Duration.Equals (other.Duration) && DistanceFromSync.Equals (other.DistanceFromSync) && InputBuffer.Equals (other.InputBuffer) && OutputBuffer.Equals (other.OutputBuffer) && Deadline.Equals (other.Deadline) && _events.Equals (other._events) && _user_data.Equals (other._user_data) && user_data_destroy_notify.Equals (other.user_data_destroy_notify);
		}

		public override bool Equals (object other)
		{
			return other is VideoCodecFrame && Equals ((VideoCodecFrame) other);
		}

		public override int GetHashCode ()
		{
			return this.GetType ().FullName.GetHashCode () ^ ref_count.GetHashCode () ^ flags.GetHashCode () ^ SystemFrameNumber.GetHashCode () ^ decode_frame_number.GetHashCode () ^ presentation_frame_number.GetHashCode () ^ Dts.GetHashCode () ^ Pts.GetHashCode () ^ Duration.GetHashCode () ^ DistanceFromSync.GetHashCode () ^ InputBuffer.GetHashCode () ^ OutputBuffer.GetHashCode () ^ Deadline.GetHashCode () ^ _events.GetHashCode () ^ _user_data.GetHashCode () ^ user_data_destroy_notify.GetHashCode ();
		}

		public static explicit operator GLib.Value (Gst.Video.VideoCodecFrame boxed)
		{
			GLib.Value val = GLib.Value.Empty;
			val.Init (Gst.Video.VideoCodecFrame.GType);
			val.Val = boxed;
			return val;
		}

		public static explicit operator Gst.Video.VideoCodecFrame (GLib.Value val)
		{
			return (Gst.Video.VideoCodecFrame) val.Val;
		}
#endregion
	}
}
