// 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
	public partial class VideoEncoder : Gst.Element, Gst.IPreset {

		protected VideoEncoder (IntPtr raw) : base(raw) {}

		protected VideoEncoder() : base(IntPtr.Zero)
		{
			CreateNativeObject (new string [0], new GLib.Value [0]);
		}

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

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

		[GLib.Property ("min-force-key-unit-interval")]
		public ulong MinForceKeyUnitInterval {
			get  {
				ulong raw_ret = gst_video_encoder_get_min_force_key_unit_interval(Handle);
				ulong ret = raw_ret;
				return ret;
			}
			set  {
				gst_video_encoder_set_min_force_key_unit_interval(Handle, value);
			}
		}

		[GLib.Property ("qos")]
		public bool Qos {
			get {
				GLib.Value val = GetProperty ("qos");
				bool ret = (bool) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value(value);
				SetProperty("qos", val);
				val.Dispose ();
			}
		}

		static OpenNativeDelegate Open_cb_delegate;
		static OpenNativeDelegate OpenVMCallback {
			get {
				if (Open_cb_delegate == null)
					Open_cb_delegate = new OpenNativeDelegate (Open_cb);
				return Open_cb_delegate;
			}
		}

		static void OverrideOpen (GLib.GType gtype)
		{
			OverrideOpen (gtype, OpenVMCallback);
		}

		static void OverrideOpen (GLib.GType gtype, OpenNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("open"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool OpenNativeDelegate (IntPtr inst);

		static bool Open_cb (IntPtr inst)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnOpen ();
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideOpen")]
		protected virtual bool OnOpen ()
		{
			return InternalOpen ();
		}

		private bool InternalOpen ()
		{
			OpenNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("open"));
				unmanaged = (OpenNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(OpenNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle);
			return __result;
		}

		static CloseNativeDelegate Close_cb_delegate;
		static CloseNativeDelegate CloseVMCallback {
			get {
				if (Close_cb_delegate == null)
					Close_cb_delegate = new CloseNativeDelegate (Close_cb);
				return Close_cb_delegate;
			}
		}

		static void OverrideClose (GLib.GType gtype)
		{
			OverrideClose (gtype, CloseVMCallback);
		}

		static void OverrideClose (GLib.GType gtype, CloseNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("close"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool CloseNativeDelegate (IntPtr inst);

		static bool Close_cb (IntPtr inst)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnClose ();
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideClose")]
		protected virtual bool OnClose ()
		{
			return InternalClose ();
		}

		private bool InternalClose ()
		{
			CloseNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("close"));
				unmanaged = (CloseNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(CloseNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle);
			return __result;
		}

		static StartNativeDelegate Start_cb_delegate;
		static StartNativeDelegate StartVMCallback {
			get {
				if (Start_cb_delegate == null)
					Start_cb_delegate = new StartNativeDelegate (Start_cb);
				return Start_cb_delegate;
			}
		}

		static void OverrideStart (GLib.GType gtype)
		{
			OverrideStart (gtype, StartVMCallback);
		}

		static void OverrideStart (GLib.GType gtype, StartNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("start"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool StartNativeDelegate (IntPtr inst);

		static bool Start_cb (IntPtr inst)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnStart ();
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideStart")]
		protected virtual bool OnStart ()
		{
			return InternalStart ();
		}

		private bool InternalStart ()
		{
			StartNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("start"));
				unmanaged = (StartNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(StartNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle);
			return __result;
		}

		static StopNativeDelegate Stop_cb_delegate;
		static StopNativeDelegate StopVMCallback {
			get {
				if (Stop_cb_delegate == null)
					Stop_cb_delegate = new StopNativeDelegate (Stop_cb);
				return Stop_cb_delegate;
			}
		}

		static void OverrideStop (GLib.GType gtype)
		{
			OverrideStop (gtype, StopVMCallback);
		}

		static void OverrideStop (GLib.GType gtype, StopNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("stop"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool StopNativeDelegate (IntPtr inst);

		static bool Stop_cb (IntPtr inst)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnStop ();
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideStop")]
		protected virtual bool OnStop ()
		{
			return InternalStop ();
		}

		private bool InternalStop ()
		{
			StopNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("stop"));
				unmanaged = (StopNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(StopNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle);
			return __result;
		}

		static SetFormatNativeDelegate SetFormat_cb_delegate;
		static SetFormatNativeDelegate SetFormatVMCallback {
			get {
				if (SetFormat_cb_delegate == null)
					SetFormat_cb_delegate = new SetFormatNativeDelegate (SetFormat_cb);
				return SetFormat_cb_delegate;
			}
		}

		static void OverrideSetFormat (GLib.GType gtype)
		{
			OverrideSetFormat (gtype, SetFormatVMCallback);
		}

		static void OverrideSetFormat (GLib.GType gtype, SetFormatNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("set_format"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool SetFormatNativeDelegate (IntPtr inst, IntPtr state);

		static bool SetFormat_cb (IntPtr inst, IntPtr state)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnSetFormat (Gst.Video.VideoCodecState.New (state));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideSetFormat")]
		protected virtual bool OnSetFormat (Gst.Video.VideoCodecState state)
		{
			return InternalSetFormat (state);
		}

		private bool InternalSetFormat (Gst.Video.VideoCodecState state)
		{
			SetFormatNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("set_format"));
				unmanaged = (SetFormatNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(SetFormatNativeDelegate));
			}
			if (unmanaged == null) return false;

			IntPtr native_state = GLib.Marshaller.StructureToPtrAlloc (state);
			bool __result = unmanaged (this.Handle, native_state);
			Marshal.FreeHGlobal (native_state);
			return __result;
		}

		static HandleFrameNativeDelegate HandleFrame_cb_delegate;
		static HandleFrameNativeDelegate HandleFrameVMCallback {
			get {
				if (HandleFrame_cb_delegate == null)
					HandleFrame_cb_delegate = new HandleFrameNativeDelegate (HandleFrame_cb);
				return HandleFrame_cb_delegate;
			}
		}

		static void OverrideHandleFrame (GLib.GType gtype)
		{
			OverrideHandleFrame (gtype, HandleFrameVMCallback);
		}

		static void OverrideHandleFrame (GLib.GType gtype, HandleFrameNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("handle_frame"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate int HandleFrameNativeDelegate (IntPtr inst, IntPtr frame);

		static int HandleFrame_cb (IntPtr inst, IntPtr frame)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				Gst.FlowReturn __result;
				__result = __obj.OnHandleFrame (Gst.Video.VideoCodecFrame.New (frame));
				return (int) __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideHandleFrame")]
		protected virtual Gst.FlowReturn OnHandleFrame (Gst.Video.VideoCodecFrame frame)
		{
			return InternalHandleFrame (frame);
		}

		private Gst.FlowReturn InternalHandleFrame (Gst.Video.VideoCodecFrame frame)
		{
			HandleFrameNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("handle_frame"));
				unmanaged = (HandleFrameNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(HandleFrameNativeDelegate));
			}
			if (unmanaged == null) return (Gst.FlowReturn) 0;

			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			int __result = unmanaged (this.Handle, native_frame);
			Marshal.FreeHGlobal (native_frame);
			return (Gst.FlowReturn) __result;
		}

		static ResetNativeDelegate Reset_cb_delegate;
		static ResetNativeDelegate ResetVMCallback {
			get {
				if (Reset_cb_delegate == null)
					Reset_cb_delegate = new ResetNativeDelegate (Reset_cb);
				return Reset_cb_delegate;
			}
		}

		static void OverrideReset (GLib.GType gtype)
		{
			OverrideReset (gtype, ResetVMCallback);
		}

		static void OverrideReset (GLib.GType gtype, ResetNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("reset"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool ResetNativeDelegate (IntPtr inst, bool hard);

		static bool Reset_cb (IntPtr inst, bool hard)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnReset (hard);
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideReset")]
		protected virtual bool OnReset (bool hard)
		{
			return InternalReset (hard);
		}

		private bool InternalReset (bool hard)
		{
			ResetNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("reset"));
				unmanaged = (ResetNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(ResetNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, hard);
			return __result;
		}

		static FinishNativeDelegate Finish_cb_delegate;
		static FinishNativeDelegate FinishVMCallback {
			get {
				if (Finish_cb_delegate == null)
					Finish_cb_delegate = new FinishNativeDelegate (Finish_cb);
				return Finish_cb_delegate;
			}
		}

		static void OverrideFinish (GLib.GType gtype)
		{
			OverrideFinish (gtype, FinishVMCallback);
		}

		static void OverrideFinish (GLib.GType gtype, FinishNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("finish"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate int FinishNativeDelegate (IntPtr inst);

		static int Finish_cb (IntPtr inst)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				Gst.FlowReturn __result;
				__result = __obj.OnFinish ();
				return (int) __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideFinish")]
		protected virtual Gst.FlowReturn OnFinish ()
		{
			return InternalFinish ();
		}

		private Gst.FlowReturn InternalFinish ()
		{
			FinishNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("finish"));
				unmanaged = (FinishNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(FinishNativeDelegate));
			}
			if (unmanaged == null) return (Gst.FlowReturn) 0;

			int __result = unmanaged (this.Handle);
			return (Gst.FlowReturn) __result;
		}

		static PrePushNativeDelegate PrePush_cb_delegate;
		static PrePushNativeDelegate PrePushVMCallback {
			get {
				if (PrePush_cb_delegate == null)
					PrePush_cb_delegate = new PrePushNativeDelegate (PrePush_cb);
				return PrePush_cb_delegate;
			}
		}

		static void OverridePrePush (GLib.GType gtype)
		{
			OverridePrePush (gtype, PrePushVMCallback);
		}

		static void OverridePrePush (GLib.GType gtype, PrePushNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("pre_push"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate int PrePushNativeDelegate (IntPtr inst, IntPtr frame);

		static int PrePush_cb (IntPtr inst, IntPtr frame)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				Gst.FlowReturn __result;
				__result = __obj.OnPrePush (Gst.Video.VideoCodecFrame.New (frame));
				return (int) __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverridePrePush")]
		protected virtual Gst.FlowReturn OnPrePush (Gst.Video.VideoCodecFrame frame)
		{
			return InternalPrePush (frame);
		}

		private Gst.FlowReturn InternalPrePush (Gst.Video.VideoCodecFrame frame)
		{
			PrePushNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("pre_push"));
				unmanaged = (PrePushNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(PrePushNativeDelegate));
			}
			if (unmanaged == null) return (Gst.FlowReturn) 0;

			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			int __result = unmanaged (this.Handle, native_frame);
			Marshal.FreeHGlobal (native_frame);
			return (Gst.FlowReturn) __result;
		}

		static GetcapsNativeDelegate Getcaps_cb_delegate;
		static GetcapsNativeDelegate GetcapsVMCallback {
			get {
				if (Getcaps_cb_delegate == null)
					Getcaps_cb_delegate = new GetcapsNativeDelegate (Getcaps_cb);
				return Getcaps_cb_delegate;
			}
		}

		static void OverrideGetcaps (GLib.GType gtype)
		{
			OverrideGetcaps (gtype, GetcapsVMCallback);
		}

		static void OverrideGetcaps (GLib.GType gtype, GetcapsNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("getcaps"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate IntPtr GetcapsNativeDelegate (IntPtr inst, IntPtr filter);

		static IntPtr Getcaps_cb (IntPtr inst, IntPtr filter)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				Gst.Caps __result;
				__result = __obj.OnGetcaps (filter == IntPtr.Zero ? null : (Gst.Caps) GLib.Opaque.GetOpaque (filter, typeof (Gst.Caps), false));
				return __result == null ? IntPtr.Zero : __result.OwnedCopy;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideGetcaps")]
		protected virtual Gst.Caps OnGetcaps (Gst.Caps filter)
		{
			return InternalGetcaps (filter);
		}

		private Gst.Caps InternalGetcaps (Gst.Caps filter)
		{
			GetcapsNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("getcaps"));
				unmanaged = (GetcapsNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(GetcapsNativeDelegate));
			}
			if (unmanaged == null) return null;

			IntPtr __result = unmanaged (this.Handle, filter == null ? IntPtr.Zero : filter.Handle);
			return __result == IntPtr.Zero ? null : (Gst.Caps) GLib.Opaque.GetOpaque (__result, typeof (Gst.Caps), true);
		}

		static SinkEventNativeDelegate SinkEvent_cb_delegate;
		static SinkEventNativeDelegate SinkEventVMCallback {
			get {
				if (SinkEvent_cb_delegate == null)
					SinkEvent_cb_delegate = new SinkEventNativeDelegate (SinkEvent_cb);
				return SinkEvent_cb_delegate;
			}
		}

		static void OverrideSinkEvent (GLib.GType gtype)
		{
			OverrideSinkEvent (gtype, SinkEventVMCallback);
		}

		static void OverrideSinkEvent (GLib.GType gtype, SinkEventNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("sink_event"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool SinkEventNativeDelegate (IntPtr inst, IntPtr evnt);

		static bool SinkEvent_cb (IntPtr inst, IntPtr evnt)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnSinkEvent (evnt == IntPtr.Zero ? null : (Gst.Event) GLib.Opaque.GetOpaque (evnt, typeof (Gst.Event), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideSinkEvent")]
		protected virtual bool OnSinkEvent (Gst.Event evnt)
		{
			return InternalSinkEvent (evnt);
		}

		private bool InternalSinkEvent (Gst.Event evnt)
		{
			SinkEventNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("sink_event"));
				unmanaged = (SinkEventNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(SinkEventNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, evnt == null ? IntPtr.Zero : evnt.Handle);
			return __result;
		}

		static SrcEventNativeDelegate SrcEvent_cb_delegate;
		static SrcEventNativeDelegate SrcEventVMCallback {
			get {
				if (SrcEvent_cb_delegate == null)
					SrcEvent_cb_delegate = new SrcEventNativeDelegate (SrcEvent_cb);
				return SrcEvent_cb_delegate;
			}
		}

		static void OverrideSrcEvent (GLib.GType gtype)
		{
			OverrideSrcEvent (gtype, SrcEventVMCallback);
		}

		static void OverrideSrcEvent (GLib.GType gtype, SrcEventNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("src_event"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool SrcEventNativeDelegate (IntPtr inst, IntPtr evnt);

		static bool SrcEvent_cb (IntPtr inst, IntPtr evnt)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnSrcEvent (evnt == IntPtr.Zero ? null : (Gst.Event) GLib.Opaque.GetOpaque (evnt, typeof (Gst.Event), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideSrcEvent")]
		protected virtual bool OnSrcEvent (Gst.Event evnt)
		{
			return InternalSrcEvent (evnt);
		}

		private bool InternalSrcEvent (Gst.Event evnt)
		{
			SrcEventNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("src_event"));
				unmanaged = (SrcEventNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(SrcEventNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, evnt == null ? IntPtr.Zero : evnt.Handle);
			return __result;
		}

		static NegotiateNativeDelegate Negotiate_cb_delegate;
		static NegotiateNativeDelegate NegotiateVMCallback {
			get {
				if (Negotiate_cb_delegate == null)
					Negotiate_cb_delegate = new NegotiateNativeDelegate (Negotiate_cb);
				return Negotiate_cb_delegate;
			}
		}

		static void OverrideNegotiate (GLib.GType gtype)
		{
			OverrideNegotiate (gtype, NegotiateVMCallback);
		}

		static void OverrideNegotiate (GLib.GType gtype, NegotiateNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("negotiate"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool NegotiateNativeDelegate (IntPtr inst);

		static bool Negotiate_cb (IntPtr inst)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnNegotiate ();
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideNegotiate")]
		protected virtual bool OnNegotiate ()
		{
			return InternalNegotiate ();
		}

		private bool InternalNegotiate ()
		{
			NegotiateNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("negotiate"));
				unmanaged = (NegotiateNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(NegotiateNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle);
			return __result;
		}

		static DecideAllocationNativeDelegate DecideAllocation_cb_delegate;
		static DecideAllocationNativeDelegate DecideAllocationVMCallback {
			get {
				if (DecideAllocation_cb_delegate == null)
					DecideAllocation_cb_delegate = new DecideAllocationNativeDelegate (DecideAllocation_cb);
				return DecideAllocation_cb_delegate;
			}
		}

		static void OverrideDecideAllocation (GLib.GType gtype)
		{
			OverrideDecideAllocation (gtype, DecideAllocationVMCallback);
		}

		static void OverrideDecideAllocation (GLib.GType gtype, DecideAllocationNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("decide_allocation"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool DecideAllocationNativeDelegate (IntPtr inst, IntPtr query);

		static bool DecideAllocation_cb (IntPtr inst, IntPtr query)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnDecideAllocation (query == IntPtr.Zero ? null : (Gst.Query) GLib.Opaque.GetOpaque (query, typeof (Gst.Query), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideDecideAllocation")]
		protected virtual bool OnDecideAllocation (Gst.Query query)
		{
			return InternalDecideAllocation (query);
		}

		private bool InternalDecideAllocation (Gst.Query query)
		{
			DecideAllocationNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("decide_allocation"));
				unmanaged = (DecideAllocationNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(DecideAllocationNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, query == null ? IntPtr.Zero : query.Handle);
			return __result;
		}

		static ProposeAllocationNativeDelegate ProposeAllocation_cb_delegate;
		static ProposeAllocationNativeDelegate ProposeAllocationVMCallback {
			get {
				if (ProposeAllocation_cb_delegate == null)
					ProposeAllocation_cb_delegate = new ProposeAllocationNativeDelegate (ProposeAllocation_cb);
				return ProposeAllocation_cb_delegate;
			}
		}

		static void OverrideProposeAllocation (GLib.GType gtype)
		{
			OverrideProposeAllocation (gtype, ProposeAllocationVMCallback);
		}

		static void OverrideProposeAllocation (GLib.GType gtype, ProposeAllocationNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("propose_allocation"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool ProposeAllocationNativeDelegate (IntPtr inst, IntPtr query);

		static bool ProposeAllocation_cb (IntPtr inst, IntPtr query)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnProposeAllocation (query == IntPtr.Zero ? null : (Gst.Query) GLib.Opaque.GetOpaque (query, typeof (Gst.Query), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideProposeAllocation")]
		protected virtual bool OnProposeAllocation (Gst.Query query)
		{
			return InternalProposeAllocation (query);
		}

		private bool InternalProposeAllocation (Gst.Query query)
		{
			ProposeAllocationNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("propose_allocation"));
				unmanaged = (ProposeAllocationNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(ProposeAllocationNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, query == null ? IntPtr.Zero : query.Handle);
			return __result;
		}

		static FlushNativeDelegate Flush_cb_delegate;
		static FlushNativeDelegate FlushVMCallback {
			get {
				if (Flush_cb_delegate == null)
					Flush_cb_delegate = new FlushNativeDelegate (Flush_cb);
				return Flush_cb_delegate;
			}
		}

		static void OverrideFlush (GLib.GType gtype)
		{
			OverrideFlush (gtype, FlushVMCallback);
		}

		static void OverrideFlush (GLib.GType gtype, FlushNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("flush"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool FlushNativeDelegate (IntPtr inst);

		static bool Flush_cb (IntPtr inst)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnFlush ();
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideFlush")]
		protected virtual bool OnFlush ()
		{
			return InternalFlush ();
		}

		private bool InternalFlush ()
		{
			FlushNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("flush"));
				unmanaged = (FlushNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(FlushNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle);
			return __result;
		}

		static SinkQueryNativeDelegate SinkQuery_cb_delegate;
		static SinkQueryNativeDelegate SinkQueryVMCallback {
			get {
				if (SinkQuery_cb_delegate == null)
					SinkQuery_cb_delegate = new SinkQueryNativeDelegate (SinkQuery_cb);
				return SinkQuery_cb_delegate;
			}
		}

		static void OverrideSinkQuery (GLib.GType gtype)
		{
			OverrideSinkQuery (gtype, SinkQueryVMCallback);
		}

		static void OverrideSinkQuery (GLib.GType gtype, SinkQueryNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("sink_query"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool SinkQueryNativeDelegate (IntPtr inst, IntPtr query);

		static bool SinkQuery_cb (IntPtr inst, IntPtr query)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnSinkQuery (query == IntPtr.Zero ? null : (Gst.Query) GLib.Opaque.GetOpaque (query, typeof (Gst.Query), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideSinkQuery")]
		protected virtual bool OnSinkQuery (Gst.Query query)
		{
			return InternalSinkQuery (query);
		}

		private bool InternalSinkQuery (Gst.Query query)
		{
			SinkQueryNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("sink_query"));
				unmanaged = (SinkQueryNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(SinkQueryNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, query == null ? IntPtr.Zero : query.Handle);
			return __result;
		}

		static SrcQueryNativeDelegate SrcQuery_cb_delegate;
		static SrcQueryNativeDelegate SrcQueryVMCallback {
			get {
				if (SrcQuery_cb_delegate == null)
					SrcQuery_cb_delegate = new SrcQueryNativeDelegate (SrcQuery_cb);
				return SrcQuery_cb_delegate;
			}
		}

		static void OverrideSrcQuery (GLib.GType gtype)
		{
			OverrideSrcQuery (gtype, SrcQueryVMCallback);
		}

		static void OverrideSrcQuery (GLib.GType gtype, SrcQueryNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("src_query"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool SrcQueryNativeDelegate (IntPtr inst, IntPtr query);

		static bool SrcQuery_cb (IntPtr inst, IntPtr query)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnSrcQuery (query == IntPtr.Zero ? null : (Gst.Query) GLib.Opaque.GetOpaque (query, typeof (Gst.Query), false));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideSrcQuery")]
		protected virtual bool OnSrcQuery (Gst.Query query)
		{
			return InternalSrcQuery (query);
		}

		private bool InternalSrcQuery (Gst.Query query)
		{
			SrcQueryNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("src_query"));
				unmanaged = (SrcQueryNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(SrcQueryNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, query == null ? IntPtr.Zero : query.Handle);
			return __result;
		}

		static TransformMetaNativeDelegate TransformMeta_cb_delegate;
		static TransformMetaNativeDelegate TransformMetaVMCallback {
			get {
				if (TransformMeta_cb_delegate == null)
					TransformMeta_cb_delegate = new TransformMetaNativeDelegate (TransformMeta_cb);
				return TransformMeta_cb_delegate;
			}
		}

		static void OverrideTransformMeta (GLib.GType gtype)
		{
			OverrideTransformMeta (gtype, TransformMetaVMCallback);
		}

		static void OverrideTransformMeta (GLib.GType gtype, TransformMetaNativeDelegate callback)
		{
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) gtype.GetClassPtr()) + (long) class_abi.GetFieldOffset("transform_meta"));
				*raw_ptr = Marshal.GetFunctionPointerForDelegate((Delegate) callback);
			}
		}

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool TransformMetaNativeDelegate (IntPtr inst, IntPtr frame, IntPtr meta);

		static bool TransformMeta_cb (IntPtr inst, IntPtr frame, IntPtr meta)
		{
			try {
				VideoEncoder __obj = GLib.Object.GetObject (inst, false) as VideoEncoder;
				bool __result;
				__result = __obj.OnTransformMeta (Gst.Video.VideoCodecFrame.New (frame), Gst.Meta.New (meta));
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoEncoder), ConnectionMethod="OverrideTransformMeta")]
		protected virtual bool OnTransformMeta (Gst.Video.VideoCodecFrame frame, Gst.Meta meta)
		{
			return InternalTransformMeta (frame, meta);
		}

		private bool InternalTransformMeta (Gst.Video.VideoCodecFrame frame, Gst.Meta meta)
		{
			TransformMetaNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("transform_meta"));
				unmanaged = (TransformMetaNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(TransformMetaNativeDelegate));
			}
			if (unmanaged == null) return false;

			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			IntPtr native_meta = GLib.Marshaller.StructureToPtrAlloc (meta);
			bool __result = unmanaged (this.Handle, native_frame, native_meta);
			Marshal.FreeHGlobal (native_frame);
			Marshal.FreeHGlobal (native_meta);
			return __result;
		}


		// Internal representation of the wrapped structure ABI.
		static GLib.AbiStruct _class_abi = null;
		static public new GLib.AbiStruct class_abi {
			get {
				if (_class_abi == null)
					_class_abi = new GLib.AbiStruct (new List<GLib.AbiField>{ 
						new GLib.AbiField("open"
							, Gst.Element.class_abi.Fields
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // open
							, null
							, "close"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("close"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // close
							, "open"
							, "start"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("start"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // start
							, "close"
							, "stop"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("stop"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // stop
							, "start"
							, "set_format"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("set_format"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // set_format
							, "stop"
							, "handle_frame"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("handle_frame"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // handle_frame
							, "set_format"
							, "reset"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("reset"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // reset
							, "handle_frame"
							, "finish"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("finish"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // finish
							, "reset"
							, "pre_push"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("pre_push"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // pre_push
							, "finish"
							, "getcaps"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("getcaps"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // getcaps
							, "pre_push"
							, "sink_event"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("sink_event"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // sink_event
							, "getcaps"
							, "src_event"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("src_event"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // src_event
							, "sink_event"
							, "negotiate"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("negotiate"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // negotiate
							, "src_event"
							, "decide_allocation"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("decide_allocation"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // decide_allocation
							, "negotiate"
							, "propose_allocation"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("propose_allocation"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // propose_allocation
							, "decide_allocation"
							, "flush"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("flush"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // flush
							, "propose_allocation"
							, "sink_query"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("sink_query"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // sink_query
							, "flush"
							, "src_query"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("src_query"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // src_query
							, "sink_query"
							, "transform_meta"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("transform_meta"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // transform_meta
							, "src_query"
							, "_gst_reserved"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("_gst_reserved"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) * 16 // _gst_reserved
							, "transform_meta"
							, null
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
					});

				return _class_abi;
			}
		}


		// End of the ABI representation.

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

		public static new GLib.GType GType { 
			get {
				IntPtr raw_ret = gst_video_encoder_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_encoder_allocate_output_buffer(IntPtr raw, UIntPtr size);

		public Gst.Buffer AllocateOutputBuffer(ulong size) {
			IntPtr raw_ret = gst_video_encoder_allocate_output_buffer(Handle, new UIntPtr (size));
			Gst.Buffer ret = raw_ret == IntPtr.Zero ? null : (Gst.Buffer) GLib.Opaque.GetOpaque (raw_ret, typeof (Gst.Buffer), true);
			return ret;
		}

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern int gst_video_encoder_allocate_output_frame(IntPtr raw, IntPtr frame, UIntPtr size);

		public Gst.FlowReturn AllocateOutputFrame(Gst.Video.VideoCodecFrame frame, ulong size) {
			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			int raw_ret = gst_video_encoder_allocate_output_frame(Handle, native_frame, new UIntPtr (size));
			Gst.FlowReturn ret = (Gst.FlowReturn) raw_ret;
			Marshal.FreeHGlobal (native_frame);
			return ret;
		}

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

		public Gst.FlowReturn FinishFrame(Gst.Video.VideoCodecFrame frame) {
			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			int raw_ret = gst_video_encoder_finish_frame(Handle, native_frame);
			Gst.FlowReturn ret = (Gst.FlowReturn) raw_ret;
			Marshal.FreeHGlobal (native_frame);
			return ret;
		}

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

		public Gst.FlowReturn FinishSubframe(Gst.Video.VideoCodecFrame frame) {
			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			int raw_ret = gst_video_encoder_finish_subframe(Handle, native_frame);
			Gst.FlowReturn ret = (Gst.FlowReturn) raw_ret;
			Marshal.FreeHGlobal (native_frame);
			return ret;
		}

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

		public void GetAllocator(out Gst.Allocator allocator, out Gst.AllocationParams parms) {
			IntPtr native_allocator;
			IntPtr native_parms = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (Gst.AllocationParams)));
			gst_video_encoder_get_allocator(Handle, out native_allocator, native_parms);
			allocator = GLib.Object.GetObject(native_allocator, true) as Gst.Allocator;
			parms = Gst.AllocationParams.New (native_parms);
			Marshal.FreeHGlobal (native_parms);
		}

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

		public Gst.Video.VideoCodecFrame GetFrame(int frame_number) {
			IntPtr raw_ret = gst_video_encoder_get_frame(Handle, frame_number);
			Gst.Video.VideoCodecFrame ret = Gst.Video.VideoCodecFrame.New (raw_ret);
			return ret;
		}

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

		public GLib.List[] Frames { 
			get {
				IntPtr raw_ret = gst_video_encoder_get_frames(Handle);
				GLib.List[] ret = (GLib.List[]) GLib.Marshaller.ListPtrToArray (raw_ret, typeof(GLib.List), true, true, typeof(GLib.List));
				return ret;
			}
		}

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_video_encoder_get_latency(IntPtr raw, out ulong min_latency, out ulong max_latency);

		public void GetLatency(out ulong min_latency, out ulong max_latency) {
			gst_video_encoder_get_latency(Handle, out min_latency, out max_latency);
		}

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

		public long GetMaxEncodeTime(Gst.Video.VideoCodecFrame frame) {
			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			long raw_ret = gst_video_encoder_get_max_encode_time(Handle, native_frame);
			long ret = raw_ret;
			Marshal.FreeHGlobal (native_frame);
			return ret;
		}

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

		public Gst.Video.VideoCodecFrame OldestFrame { 
			get {
				IntPtr raw_ret = gst_video_encoder_get_oldest_frame(Handle);
				Gst.Video.VideoCodecFrame ret = Gst.Video.VideoCodecFrame.New (raw_ret);
				return ret;
			}
		}

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

		public Gst.Video.VideoCodecState OutputState { 
			get {
				IntPtr raw_ret = gst_video_encoder_get_output_state(Handle);
				Gst.Video.VideoCodecState ret = Gst.Video.VideoCodecState.New (raw_ret);
				return ret;
			}
		}

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

		public bool IsQosEnabled { 
			get {
				bool raw_ret = gst_video_encoder_is_qos_enabled(Handle);
				bool ret = raw_ret;
				return ret;
			}
		}

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

		public void MergeTags(Gst.TagList tags, Gst.TagMergeMode mode) {
			gst_video_encoder_merge_tags(Handle, tags == null ? IntPtr.Zero : tags.Handle, (int) mode);
		}

		public void MergeTags(Gst.TagMergeMode mode) {
			MergeTags (null, mode);
		}

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

		public bool Negotiate() {
			bool raw_ret = gst_video_encoder_negotiate(Handle);
			bool ret = raw_ret;
			return ret;
		}

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

		public Gst.Caps ProxyGetcaps(Gst.Caps caps, Gst.Caps filter) {
			IntPtr raw_ret = gst_video_encoder_proxy_getcaps(Handle, caps == null ? IntPtr.Zero : caps.Handle, filter == null ? IntPtr.Zero : filter.Handle);
			Gst.Caps ret = raw_ret == IntPtr.Zero ? null : (Gst.Caps) GLib.Opaque.GetOpaque (raw_ret, typeof (Gst.Caps), true);
			return ret;
		}

		public Gst.Caps ProxyGetcaps() {
			return ProxyGetcaps (null, null);
		}

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

		public GLib.List Headers { 
			set {
				gst_video_encoder_set_headers(Handle, value == null ? IntPtr.Zero : value.Handle);
			}
		}

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

		public void SetLatency(ulong min_latency, ulong max_latency) {
			gst_video_encoder_set_latency(Handle, min_latency, max_latency);
		}

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

		public ulong MinPts { 
			set {
				gst_video_encoder_set_min_pts(Handle, value);
			}
		}

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

		public Gst.Video.VideoCodecState SetOutputState(Gst.Caps caps, Gst.Video.VideoCodecState reference) {
			caps.Owned = false;
			IntPtr native_reference = GLib.Marshaller.StructureToPtrAlloc (reference);
			IntPtr raw_ret = gst_video_encoder_set_output_state(Handle, caps == null ? IntPtr.Zero : caps.Handle, native_reference);
			Gst.Video.VideoCodecState ret = Gst.Video.VideoCodecState.New (raw_ret);
			Marshal.FreeHGlobal (native_reference);
			return ret;
		}

		public Gst.Video.VideoCodecState SetOutputState(Gst.Caps caps) {
			return SetOutputState (caps, Gst.Video.VideoCodecState.Zero);
		}

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

		public bool QosEnabled { 
			set {
				gst_video_encoder_set_qos_enabled(Handle, value);
			}
		}

		[DllImport("gstreamer-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_preset_delete_preset(IntPtr raw, IntPtr name);

		public bool DeletePreset(string name) {
			IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (name);
			bool raw_ret = gst_preset_delete_preset(Handle, native_name);
			bool ret = raw_ret;
			GLib.Marshaller.Free (native_name);
			return ret;
		}

		[DllImport("gstreamer-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_preset_get_meta(IntPtr raw, IntPtr name, IntPtr tag, out IntPtr value);

		public bool GetMeta(string name, string tag, out string value) {
			IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (name);
			IntPtr native_tag = GLib.Marshaller.StringToPtrGStrdup (tag);
			IntPtr native_value;
			bool raw_ret = gst_preset_get_meta(Handle, native_name, native_tag, out native_value);
			bool ret = raw_ret;
			GLib.Marshaller.Free (native_name);
			GLib.Marshaller.Free (native_tag);
			value = GLib.Marshaller.PtrToStringGFree(native_value);
			return ret;
		}

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

		public string[] PresetNames { 
			get {
				IntPtr raw_ret = gst_preset_get_preset_names(Handle);
				string[] ret = GLib.Marshaller.NullTermPtrToStringArray (raw_ret, true);
				return ret;
			}
		}

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

		public string[] PropertyNames { 
			get {
				IntPtr raw_ret = gst_preset_get_property_names(Handle);
				string[] ret = GLib.Marshaller.NullTermPtrToStringArray (raw_ret, true);
				return ret;
			}
		}

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

		public bool IsEditable { 
			get {
				bool raw_ret = gst_preset_is_editable(Handle);
				bool ret = raw_ret;
				return ret;
			}
		}

		[DllImport("gstreamer-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_preset_load_preset(IntPtr raw, IntPtr name);

		public bool LoadPreset(string name) {
			IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (name);
			bool raw_ret = gst_preset_load_preset(Handle, native_name);
			bool ret = raw_ret;
			GLib.Marshaller.Free (native_name);
			return ret;
		}

		[DllImport("gstreamer-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_preset_rename_preset(IntPtr raw, IntPtr old_name, IntPtr new_name);

		public bool RenamePreset(string old_name, string new_name) {
			IntPtr native_old_name = GLib.Marshaller.StringToPtrGStrdup (old_name);
			IntPtr native_new_name = GLib.Marshaller.StringToPtrGStrdup (new_name);
			bool raw_ret = gst_preset_rename_preset(Handle, native_old_name, native_new_name);
			bool ret = raw_ret;
			GLib.Marshaller.Free (native_old_name);
			GLib.Marshaller.Free (native_new_name);
			return ret;
		}

		[DllImport("gstreamer-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_preset_save_preset(IntPtr raw, IntPtr name);

		public bool SavePreset(string name) {
			IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (name);
			bool raw_ret = gst_preset_save_preset(Handle, native_name);
			bool ret = raw_ret;
			GLib.Marshaller.Free (native_name);
			return ret;
		}

		[DllImport("gstreamer-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern bool gst_preset_set_meta(IntPtr raw, IntPtr name, IntPtr tag, IntPtr value);

		public bool SetMeta(string name, string tag, string value) {
			IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (name);
			IntPtr native_tag = GLib.Marshaller.StringToPtrGStrdup (tag);
			IntPtr native_value = GLib.Marshaller.StringToPtrGStrdup (value);
			bool raw_ret = gst_preset_set_meta(Handle, native_name, native_tag, native_value);
			bool ret = raw_ret;
			GLib.Marshaller.Free (native_name);
			GLib.Marshaller.Free (native_tag);
			GLib.Marshaller.Free (native_value);
			return ret;
		}

		public bool SetMeta(string name, string tag) {
			return SetMeta (name, tag, null);
		}


		static VideoEncoder ()
		{
			GtkSharp.GstreamerSharp.ObjectManager.Initialize ();
		}

		// Internal representation of the wrapped structure ABI.
		static GLib.AbiStruct _abi_info = null;
		static public new GLib.AbiStruct abi_info {
			get {
				if (_abi_info == null)
					_abi_info = new GLib.AbiStruct (new List<GLib.AbiField>{ 
						new GLib.AbiField("sinkpad"
							, Gst.Element.abi_info.Fields
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // sinkpad
							, null
							, "srcpad"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("srcpad"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // srcpad
							, "sinkpad"
							, "stream_lock"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("stream_lock"
							, -1
							, (uint) Marshal.SizeOf(typeof(GLib.RecMutex.ABI)) // stream_lock
							, "srcpad"
							, "input_segment"
							, (long) Marshal.OffsetOf(typeof(GstVideoEncoder_stream_lockAlign), "stream_lock")
							, 0
							),
						new GLib.AbiField("input_segment"
							, -1
							, (uint) Marshal.SizeOf(typeof(Gst.Segment)) // input_segment
							, "stream_lock"
							, "output_segment"
							, (long) Marshal.OffsetOf(typeof(GstVideoEncoder_input_segmentAlign), "input_segment")
							, 0
							),
						new GLib.AbiField("output_segment"
							, -1
							, (uint) Marshal.SizeOf(typeof(Gst.Segment)) // output_segment
							, "input_segment"
							, "priv"
							, (long) Marshal.OffsetOf(typeof(GstVideoEncoder_output_segmentAlign), "output_segment")
							, 0
							),
						new GLib.AbiField("priv"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // priv
							, "output_segment"
							, "padding"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("padding"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) * 20 // padding
							, "priv"
							, null
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
					});

				return _abi_info;
			}
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct GstVideoEncoder_stream_lockAlign
		{
			sbyte f1;
			private GLib.RecMutex.ABI stream_lock;
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct GstVideoEncoder_input_segmentAlign
		{
			sbyte f1;
			private Gst.Segment input_segment;
		}

		[StructLayout(LayoutKind.Sequential)]
		public struct GstVideoEncoder_output_segmentAlign
		{
			sbyte f1;
			private Gst.Segment output_segment;
		}


		// End of the ABI representation.

#endregion
	}
}
