// 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 VideoDecoder : Gst.Element {

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

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

		[GLib.Property ("automatic-request-sync-point-flags")]
		public Gst.Video.VideoDecoderRequestSyncPointFlags AutomaticRequestSyncPointFlags {
			get {
				GLib.Value val = GetProperty ("automatic-request-sync-point-flags");
				Gst.Video.VideoDecoderRequestSyncPointFlags ret = (Gst.Video.VideoDecoderRequestSyncPointFlags) (Enum) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value((Enum) value);
				SetProperty("automatic-request-sync-point-flags", val);
				val.Dispose ();
			}
		}

		[GLib.Property ("automatic-request-sync-points")]
		public bool AutomaticRequestSyncPoints {
			get {
				GLib.Value val = GetProperty ("automatic-request-sync-points");
				bool ret = (bool) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value(value);
				SetProperty("automatic-request-sync-points", val);
				val.Dispose ();
			}
		}

		[GLib.Property ("discard-corrupted-frames")]
		public bool DiscardCorruptedFrames {
			get {
				GLib.Value val = GetProperty ("discard-corrupted-frames");
				bool ret = (bool) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value(value);
				SetProperty("discard-corrupted-frames", val);
				val.Dispose ();
			}
		}

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

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

		[GLib.Property ("max-errors")]
		public int MaxErrors {
			get  {
				int raw_ret = gst_video_decoder_get_max_errors(Handle);
				int ret = raw_ret;
				return ret;
			}
			set  {
				gst_video_decoder_set_max_errors(Handle, value);
			}
		}

		[GLib.Property ("min-force-key-unit-interval")]
		public ulong MinForceKeyUnitInterval {
			get {
				GLib.Value val = GetProperty ("min-force-key-unit-interval");
				ulong ret = (ulong) val;
				val.Dispose ();
				return ret;
			}
			set {
				GLib.Value val = new GLib.Value(value);
				SetProperty("min-force-key-unit-interval", val);
				val.Dispose ();
			}
		}

		[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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 ParseNativeDelegate Parse_cb_delegate;
		static ParseNativeDelegate ParseVMCallback {
			get {
				if (Parse_cb_delegate == null)
					Parse_cb_delegate = new ParseNativeDelegate (Parse_cb);
				return Parse_cb_delegate;
			}
		}

		static void OverrideParse (GLib.GType gtype)
		{
			OverrideParse (gtype, ParseVMCallback);
		}

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

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate int ParseNativeDelegate (IntPtr inst, IntPtr frame, IntPtr adapter, bool at_eos);

		static int Parse_cb (IntPtr inst, IntPtr frame, IntPtr adapter, bool at_eos)
		{
			try {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				Gst.FlowReturn __result;
				__result = __obj.OnParse (Gst.Video.VideoCodecFrame.New (frame), GLib.Object.GetObject(adapter) as Gst.Base.Adapter, at_eos);
				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.VideoDecoder), ConnectionMethod="OverrideParse")]
		protected virtual Gst.FlowReturn OnParse (Gst.Video.VideoCodecFrame frame, Gst.Base.Adapter adapter, bool at_eos)
		{
			return InternalParse (frame, adapter, at_eos);
		}

		private Gst.FlowReturn InternalParse (Gst.Video.VideoCodecFrame frame, Gst.Base.Adapter adapter, bool at_eos)
		{
			ParseNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("parse"));
				unmanaged = (ParseNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(ParseNativeDelegate));
			}
			if (unmanaged == null) return (Gst.FlowReturn) 0;

			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			int __result = unmanaged (this.Handle, native_frame, adapter == null ? IntPtr.Zero : adapter.Handle, at_eos);
			Marshal.FreeHGlobal (native_frame);
			return (Gst.FlowReturn) __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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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 DrainNativeDelegate Drain_cb_delegate;
		static DrainNativeDelegate DrainVMCallback {
			get {
				if (Drain_cb_delegate == null)
					Drain_cb_delegate = new DrainNativeDelegate (Drain_cb);
				return Drain_cb_delegate;
			}
		}

		static void OverrideDrain (GLib.GType gtype)
		{
			OverrideDrain (gtype, DrainVMCallback);
		}

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

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

		static int Drain_cb (IntPtr inst)
		{
			try {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				Gst.FlowReturn __result;
				__result = __obj.OnDrain ();
				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.VideoDecoder), ConnectionMethod="OverrideDrain")]
		protected virtual Gst.FlowReturn OnDrain ()
		{
			return InternalDrain ();
		}

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

			int __result = unmanaged (this.Handle);
			return (Gst.FlowReturn) __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 {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				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.VideoDecoder), 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;
		}

		static HandleMissingDataNativeDelegate HandleMissingData_cb_delegate;
		static HandleMissingDataNativeDelegate HandleMissingDataVMCallback {
			get {
				if (HandleMissingData_cb_delegate == null)
					HandleMissingData_cb_delegate = new HandleMissingDataNativeDelegate (HandleMissingData_cb);
				return HandleMissingData_cb_delegate;
			}
		}

		static void OverrideHandleMissingData (GLib.GType gtype)
		{
			OverrideHandleMissingData (gtype, HandleMissingDataVMCallback);
		}

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

		[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
		delegate bool HandleMissingDataNativeDelegate (IntPtr inst, ulong timestamp, ulong duration);

		static bool HandleMissingData_cb (IntPtr inst, ulong timestamp, ulong duration)
		{
			try {
				VideoDecoder __obj = GLib.Object.GetObject (inst, false) as VideoDecoder;
				bool __result;
				__result = __obj.OnHandleMissingData (timestamp, duration);
				return __result;
			} catch (Exception e) {
				GLib.ExceptionManager.RaiseUnhandledException (e, true);
				// NOTREACHED: above call does not return.
				throw e;
			}
		}

		[GLib.DefaultSignalHandler(Type=typeof(Gst.Video.VideoDecoder), ConnectionMethod="OverrideHandleMissingData")]
		protected virtual bool OnHandleMissingData (ulong timestamp, ulong duration)
		{
			return InternalHandleMissingData (timestamp, duration);
		}

		private bool InternalHandleMissingData (ulong timestamp, ulong duration)
		{
			HandleMissingDataNativeDelegate unmanaged = null;
			unsafe {
				IntPtr* raw_ptr = (IntPtr*)(((long) this.LookupGType().GetThresholdType().GetClassPtr()) + (long) class_abi.GetFieldOffset("handle_missing_data"));
				unmanaged = (HandleMissingDataNativeDelegate) Marshal.GetDelegateForFunctionPointer(*raw_ptr, typeof(HandleMissingDataNativeDelegate));
			}
			if (unmanaged == null) return false;

			bool __result = unmanaged (this.Handle, timestamp, duration);
			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"
							, "parse"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("parse"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // parse
							, "stop"
							, "set_format"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("set_format"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // set_format
							, "parse"
							, "reset"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("reset"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // reset
							, "set_format"
							, "finish"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("finish"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // finish
							, "reset"
							, "handle_frame"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("handle_frame"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // handle_frame
							, "finish"
							, "sink_event"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("sink_event"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // sink_event
							, "handle_frame"
							, "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"
							, "getcaps"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("getcaps"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // getcaps
							, "src_query"
							, "drain"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("drain"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // drain
							, "getcaps"
							, "transform_meta"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("transform_meta"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // transform_meta
							, "drain"
							, "handle_missing_data"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("handle_missing_data"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) // handle_missing_data
							, "transform_meta"
							, "padding"
							, (uint) Marshal.SizeOf(typeof(IntPtr))
							, 0
							),
						new GLib.AbiField("padding"
							, -1
							, (uint) Marshal.SizeOf(typeof(IntPtr)) * 13 // padding
							, "handle_missing_data"
							, 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_decoder_get_type();

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

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

		public void AddToFrame(int n_bytes) {
			gst_video_decoder_add_to_frame(Handle, n_bytes);
		}

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

		public Gst.Buffer AllocateOutputBuffer() {
			IntPtr raw_ret = gst_video_decoder_allocate_output_buffer(Handle);
			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_decoder_allocate_output_frame(IntPtr raw, IntPtr frame);

		public Gst.FlowReturn AllocateOutputFrame(Gst.Video.VideoCodecFrame frame) {
			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			int raw_ret = gst_video_decoder_allocate_output_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_decoder_allocate_output_frame_with_params(IntPtr raw, IntPtr frame, IntPtr parms);

		public Gst.FlowReturn AllocateOutputFrameWithParams(Gst.Video.VideoCodecFrame frame, Gst.BufferPoolAcquireParams parms) {
			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			IntPtr native_parms = GLib.Marshaller.StructureToPtrAlloc (parms);
			int raw_ret = gst_video_decoder_allocate_output_frame_with_params(Handle, native_frame, native_parms);
			Gst.FlowReturn ret = (Gst.FlowReturn) raw_ret;
			Marshal.FreeHGlobal (native_frame);
			Marshal.FreeHGlobal (native_parms);
			return ret;
		}

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

		public Gst.FlowReturn DropFrame(Gst.Video.VideoCodecFrame frame) {
			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			int raw_ret = gst_video_decoder_drop_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_decoder_drop_subframe(IntPtr raw, IntPtr frame);

		public Gst.FlowReturn DropSubframe(Gst.Video.VideoCodecFrame frame) {
			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			int raw_ret = gst_video_decoder_drop_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 int gst_video_decoder_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_decoder_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_decoder_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_decoder_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_decoder_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_decoder_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_decoder_get_buffer_pool(IntPtr raw);

		public Gst.BufferPool BufferPool { 
			get {
				IntPtr raw_ret = gst_video_decoder_get_buffer_pool(Handle);
				Gst.BufferPool ret = GLib.Object.GetObject(raw_ret, true) as Gst.BufferPool;
				return ret;
			}
		}

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

		public int EstimateRate { 
			get {
				int raw_ret = gst_video_decoder_get_estimate_rate(Handle);
				int ret = raw_ret;
				return ret;
			}
		}

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

		public Gst.Video.VideoCodecFrame GetFrame(int frame_number) {
			IntPtr raw_ret = gst_video_decoder_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_decoder_get_frames(IntPtr raw);

		public GLib.List[] Frames { 
			get {
				IntPtr raw_ret = gst_video_decoder_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 uint gst_video_decoder_get_input_subframe_index(IntPtr raw, IntPtr frame);

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

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern void gst_video_decoder_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_decoder_get_latency(Handle, out min_latency, out max_latency);
		}

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

		public long GetMaxDecodeTime(Gst.Video.VideoCodecFrame frame) {
			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			long raw_ret = gst_video_decoder_get_max_decode_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 bool gst_video_decoder_get_needs_format(IntPtr raw);

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

		public bool NeedsFormat { 
			get {
				bool raw_ret = gst_video_decoder_get_needs_format(Handle);
				bool ret = raw_ret;
				return ret;
			}
			set {
				gst_video_decoder_set_needs_format(Handle, value);
			}
		}

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

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

		public bool NeedsSyncPoint { 
			get {
				bool raw_ret = gst_video_decoder_get_needs_sync_point(Handle);
				bool ret = raw_ret;
				return ret;
			}
			set {
				gst_video_decoder_set_needs_sync_point(Handle, value);
			}
		}

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

		public Gst.Video.VideoCodecFrame OldestFrame { 
			get {
				IntPtr raw_ret = gst_video_decoder_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_decoder_get_output_state(IntPtr raw);

		public Gst.Video.VideoCodecState OutputState { 
			get {
				IntPtr raw_ret = gst_video_decoder_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_decoder_get_packetized(IntPtr raw);

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

		public bool Packetized { 
			get {
				bool raw_ret = gst_video_decoder_get_packetized(Handle);
				bool ret = raw_ret;
				return ret;
			}
			set {
				gst_video_decoder_set_packetized(Handle, value);
			}
		}

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

		public ulong PendingFrameSize { 
			get {
				UIntPtr raw_ret = gst_video_decoder_get_pending_frame_size(Handle);
				ulong ret = (ulong) raw_ret;
				return ret;
			}
		}

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

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

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

		public double QosProportion { 
			get {
				double raw_ret = gst_video_decoder_get_qos_proportion(Handle);
				double ret = raw_ret;
				return ret;
			}
		}

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

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

		public bool SubframeMode { 
			get {
				bool raw_ret = gst_video_decoder_get_subframe_mode(Handle);
				bool ret = raw_ret;
				return ret;
			}
			set {
				gst_video_decoder_set_subframe_mode(Handle, value);
			}
		}

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

		public Gst.FlowReturn HaveFrame() {
			int raw_ret = gst_video_decoder_have_frame(Handle);
			Gst.FlowReturn ret = (Gst.FlowReturn) raw_ret;
			return ret;
		}

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

		public Gst.FlowReturn HaveLastSubframe(Gst.Video.VideoCodecFrame frame) {
			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			int raw_ret = gst_video_decoder_have_last_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_decoder_merge_tags(IntPtr raw, IntPtr tags, int mode);

		public void MergeTags(Gst.TagList tags, Gst.TagMergeMode mode) {
			gst_video_decoder_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_decoder_negotiate(IntPtr raw);

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

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

		public Gst.Caps ProxyGetcaps(Gst.Caps caps, Gst.Caps filter) {
			IntPtr raw_ret = gst_video_decoder_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_decoder_release_frame(IntPtr raw, IntPtr frame);

		public void ReleaseFrame(Gst.Video.VideoCodecFrame frame) {
			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			gst_video_decoder_release_frame(Handle, native_frame);
			Marshal.FreeHGlobal (native_frame);
		}

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

		public void RequestSyncPoint(Gst.Video.VideoCodecFrame frame, Gst.Video.VideoDecoderRequestSyncPointFlags flags) {
			IntPtr native_frame = GLib.Marshaller.StructureToPtrAlloc (frame);
			gst_video_decoder_request_sync_point(Handle, native_frame, (int) flags);
			Marshal.FreeHGlobal (native_frame);
		}

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

		public void SetEstimateRate(bool enabled) {
			gst_video_decoder_set_estimate_rate(Handle, enabled);
		}

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_video_decoder_set_interlaced_output_state(IntPtr raw, int fmt, int interlace_mode, uint width, uint height, IntPtr reference);

		public Gst.Video.VideoCodecState SetInterlacedOutputState(Gst.Video.VideoFormat fmt, Gst.Video.VideoInterlaceMode interlace_mode, uint width, uint height, Gst.Video.VideoCodecState reference) {
			IntPtr native_reference = GLib.Marshaller.StructureToPtrAlloc (reference);
			IntPtr raw_ret = gst_video_decoder_set_interlaced_output_state(Handle, (int) fmt, (int) interlace_mode, width, height, native_reference);
			Gst.Video.VideoCodecState ret = Gst.Video.VideoCodecState.New (raw_ret);
			Marshal.FreeHGlobal (native_reference);
			return ret;
		}

		public Gst.Video.VideoCodecState SetInterlacedOutputState(Gst.Video.VideoFormat fmt, Gst.Video.VideoInterlaceMode interlace_mode, uint width, uint height) {
			return SetInterlacedOutputState (fmt, interlace_mode, width, height, Gst.Video.VideoCodecState.Zero);
		}

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

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

		[DllImport("gstvideo-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
		static extern IntPtr gst_video_decoder_set_output_state(IntPtr raw, int fmt, uint width, uint height, IntPtr reference);

		public Gst.Video.VideoCodecState SetOutputState(Gst.Video.VideoFormat fmt, uint width, uint height, Gst.Video.VideoCodecState reference) {
			IntPtr native_reference = GLib.Marshaller.StructureToPtrAlloc (reference);
			IntPtr raw_ret = gst_video_decoder_set_output_state(Handle, (int) fmt, width, height, native_reference);
			Gst.Video.VideoCodecState ret = Gst.Video.VideoCodecState.New (raw_ret);
			Marshal.FreeHGlobal (native_reference);
			return ret;
		}

		public Gst.Video.VideoCodecState SetOutputState(Gst.Video.VideoFormat fmt, uint width, uint height) {
			return SetOutputState (fmt, width, height, Gst.Video.VideoCodecState.Zero);
		}

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

		public bool UseDefaultPadAcceptcaps { 
			set {
				gst_video_decoder_set_use_default_pad_acceptcaps(Handle, value);
			}
		}


		static VideoDecoder ()
		{
			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(GstVideoDecoder_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(GstVideoDecoder_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(GstVideoDecoder_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 GstVideoDecoder_stream_lockAlign
		{
			sbyte f1;
			private GLib.RecMutex.ABI stream_lock;
		}

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

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


		// End of the ABI representation.

#endregion
	}
}
