// 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 VideoCodecState : IEquatable<VideoCodecState> {

		private int ref_count;
		private IntPtr _info;
		public Gst.Video.VideoInfo Info {
			get {
				return _info == IntPtr.Zero ? null : (Gst.Video.VideoInfo) GLib.Opaque.GetOpaque (_info, typeof (Gst.Video.VideoInfo), false);
			}
			set {
				_info = value == null ? IntPtr.Zero : value.Handle;
			}
		}
		private IntPtr _caps;
		public Gst.Caps Caps {
			get {
				return _caps == IntPtr.Zero ? null : (Gst.Caps) GLib.Opaque.GetOpaque (_caps, typeof (Gst.Caps), false);
			}
			set {
				_caps = value == null ? IntPtr.Zero : value.Handle;
			}
		}
		private IntPtr _codec_data;
		public Gst.Buffer CodecData {
			get {
				return _codec_data == IntPtr.Zero ? null : (Gst.Buffer) GLib.Opaque.GetOpaque (_codec_data, typeof (Gst.Buffer), false);
			}
			set {
				_codec_data = value == null ? IntPtr.Zero : value.Handle;
			}
		}
		private IntPtr _allocation_caps;
		public Gst.Caps AllocationCaps {
			get {
				return _allocation_caps == IntPtr.Zero ? null : (Gst.Caps) GLib.Opaque.GetOpaque (_allocation_caps, typeof (Gst.Caps), false);
			}
			set {
				_allocation_caps = value == null ? IntPtr.Zero : value.Handle;
			}
		}
		private IntPtr _mastering_display_info;

		public Gst.Video.VideoMasteringDisplayInfo mastering_display_info {
			get { return Gst.Video.VideoMasteringDisplayInfo.New (_mastering_display_info); }
		}
		private IntPtr _content_light_level;

		public Gst.Video.VideoContentLightLevel content_light_level {
			get { return Gst.Video.VideoContentLightLevel.New (_content_light_level); }
		}
		[MarshalAs (UnmanagedType.ByValArray, SizeConst=17)]
		private IntPtr[] Padding;

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

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

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

		public static GLib.GType GType { 
			get {
				IntPtr raw_ret = gst_video_codec_state_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_state_ref(IntPtr raw);

		public Gst.Video.VideoCodecState 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_state_ref(this_as_native);
			Gst.Video.VideoCodecState ret = Gst.Video.VideoCodecState.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_state_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_state_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.VideoCodecState target)
		{
			target = New (native);
		}

		public bool Equals (VideoCodecState other)
		{
			return true && ref_count.Equals (other.ref_count) && Info.Equals (other.Info) && Caps.Equals (other.Caps) && CodecData.Equals (other.CodecData) && AllocationCaps.Equals (other.AllocationCaps) && mastering_display_info.Equals (other.mastering_display_info) && content_light_level.Equals (other.content_light_level);
		}

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

		public override int GetHashCode ()
		{
			return this.GetType ().FullName.GetHashCode () ^ ref_count.GetHashCode () ^ Info.GetHashCode () ^ Caps.GetHashCode () ^ CodecData.GetHashCode () ^ AllocationCaps.GetHashCode () ^ mastering_display_info.GetHashCode () ^ content_light_level.GetHashCode ();
		}

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

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