pub const ext = @import("ext.zig");
const gstcuda = @This();

const std = @import("std");
const compat = @import("compat");
const gstvideo = @import("gstvideo1");
const gstbase = @import("gstbase1");
const gst = @import("gst1");
const gobject = @import("gobject2");
const glib = @import("glib2");
const gmodule = @import("gmodule2");
const gstgl = @import("gstgl1");
const cudagst = @import("cudagst1");
/// A `gst.Allocator` subclass for cuda memory
pub const CudaAllocator = extern struct {
    pub const Parent = gst.Allocator;
    pub const Implements = [_]type{};
    pub const Class = gstcuda.CudaAllocatorClass;
    f_parent: gst.Allocator,
    f_priv: ?*gstcuda.CudaAllocatorPrivate,
    f__gst_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {
        /// Controls the active state of `allocator`. Default `gstcuda.CudaAllocator` is
        /// stateless and therefore active state is ignored, but subclass implementation
        /// (e.g., `gstcuda.CudaPoolAllocator`) will require explicit active state control
        /// for its internal resource management.
        ///
        /// This method is conceptually identical to gst_buffer_pool_set_active method.
        pub const set_active = struct {
            pub fn call(p_class: anytype, p_allocator: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_active: c_int) c_int {
                return gobject.ext.as(CudaAllocator.Class, p_class).f_set_active.?(gobject.ext.as(CudaAllocator, p_allocator), p_active);
            }

            pub fn implement(p_class: anytype, p_implementation: *const fn (p_allocator: *@typeInfo(@TypeOf(p_class)).pointer.child.Instance, p_active: c_int) callconv(.c) c_int) void {
                gobject.ext.as(CudaAllocator.Class, p_class).f_set_active = @ptrCast(p_implementation);
            }
        };
    };

    pub const properties = struct {};

    pub const signals = struct {};

    extern fn gst_cuda_allocator_alloc(p_allocator: ?*CudaAllocator, p_context: *gstcuda.CudaContext, p_stream: ?*gstcuda.CudaStream, p_info: *const gstvideo.VideoInfo) ?*gst.Memory;
    pub const alloc = gst_cuda_allocator_alloc;

    /// Allocates a new memory that wraps the given CUDA device memory.
    ///
    /// `info` must represent actual memory layout, in other words, offset, stride
    /// and size fields of `info` should be matched with memory layout of `dev_ptr`
    ///
    /// By default, wrapped `dev_ptr` will be freed at the time when `gst.Memory`
    /// is freed if `notify` is `NULL`. Otherwise, if caller sets `notify`,
    /// freeing `dev_ptr` is callers responsibility and default `gstcuda.CudaAllocator`
    /// will not free it.
    extern fn gst_cuda_allocator_alloc_wrapped(p_allocator: ?*CudaAllocator, p_context: *gstcuda.CudaContext, p_stream: ?*gstcuda.CudaStream, p_info: *const gstvideo.VideoInfo, p_dev_ptr: cudagst.deviceptr, p_user_data: ?*anyopaque, p_notify: ?glib.DestroyNotify) *gst.Memory;
    pub const allocWrapped = gst_cuda_allocator_alloc_wrapped;

    /// Controls the active state of `allocator`. Default `gstcuda.CudaAllocator` is
    /// stateless and therefore active state is ignored, but subclass implementation
    /// (e.g., `gstcuda.CudaPoolAllocator`) will require explicit active state control
    /// for its internal resource management.
    ///
    /// This method is conceptually identical to gst_buffer_pool_set_active method.
    extern fn gst_cuda_allocator_set_active(p_allocator: *CudaAllocator, p_active: c_int) c_int;
    pub const setActive = gst_cuda_allocator_set_active;

    /// Allocates new `gst.Memory` object with CUDA virtual memory.
    extern fn gst_cuda_allocator_virtual_alloc(p_allocator: *CudaAllocator, p_context: *gstcuda.CudaContext, p_stream: *gstcuda.CudaStream, p_info: *const gstvideo.VideoInfo, p_prop: *const cudagst.memAllocationProp, p_granularity_flags: cudagst.memAllocationGranularity_flags) ?*gst.Memory;
    pub const virtualAlloc = gst_cuda_allocator_virtual_alloc;

    extern fn gst_cuda_allocator_get_type() usize;
    pub const getGObjectType = gst_cuda_allocator_get_type;

    extern fn g_object_ref(p_self: *gstcuda.CudaAllocator) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstcuda.CudaAllocator) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *CudaAllocator, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaBufferPool = extern struct {
    pub const Parent = gst.BufferPool;
    pub const Implements = [_]type{};
    pub const Class = gstcuda.CudaBufferPoolClass;
    f_parent: gst.BufferPool,
    f_context: ?*gstcuda.CudaContext,
    f_priv: ?*gstcuda.CudaBufferPoolPrivate,

    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    extern fn gst_cuda_buffer_pool_new(p_context: *gstcuda.CudaContext) *gstcuda.CudaBufferPool;
    pub const new = gst_cuda_buffer_pool_new;

    extern fn gst_cuda_buffer_pool_get_type() usize;
    pub const getGObjectType = gst_cuda_buffer_pool_get_type;

    extern fn g_object_ref(p_self: *gstcuda.CudaBufferPool) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstcuda.CudaBufferPool) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *CudaBufferPool, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaContext = extern struct {
    pub const Parent = gst.Object;
    pub const Implements = [_]type{};
    pub const Class = gstcuda.CudaContextClass;
    f_object: gst.Object,
    f_priv: ?*gstcuda.CudaContextPrivate,

    pub const virtual_methods = struct {};

    pub const properties = struct {
        pub const cuda_device_id = struct {
            pub const name = "cuda-device-id";

            pub const Type = c_uint;
        };

        /// The default stack size for each GPU thread.
        pub const default_gpu_stack_size = struct {
            pub const name = "default-gpu-stack-size";

            pub const Type = c_uint;
        };

        /// External resource interop API support
        pub const external_resource_interop = struct {
            pub const name = "external-resource-interop";

            pub const Type = c_int;
        };

        /// OS handle supportability in virtual memory management
        pub const os_handle = struct {
            pub const name = "os-handle";

            pub const Type = c_int;
        };

        pub const prefer_stream_ordered_alloc = struct {
            pub const name = "prefer-stream-ordered-alloc";

            pub const Type = c_int;
        };

        pub const stream_ordered_alloc = struct {
            pub const name = "stream-ordered-alloc";

            pub const Type = c_int;
        };

        /// Virtual memory management supportability
        pub const virtual_memory = struct {
            pub const name = "virtual-memory";

            pub const Type = c_int;
        };
    };

    pub const signals = struct {};

    /// Pops the current CUDA context from CPU thread
    extern fn gst_cuda_context_pop(p_cuda_ctx: *cudagst.context) c_int;
    pub const pop = gst_cuda_context_pop;

    /// Create `gstcuda.CudaContext` with given device_id
    extern fn gst_cuda_context_new(p_device_id: c_uint) ?*gstcuda.CudaContext;
    pub const new = gst_cuda_context_new;

    /// Note: The caller is responsible for ensuring that the CUcontext and CUdevice
    /// represented by `handle` and `device` stay alive while the returned
    /// `gstcuda.CudaContext` is active.
    extern fn gst_cuda_context_new_wrapped(p_handler: cudagst.context, p_device: cudagst.device) ?*gstcuda.CudaContext;
    pub const newWrapped = gst_cuda_context_new_wrapped;

    /// Query whether `ctx` can access any memory which belongs to `peer` directly.
    extern fn gst_cuda_context_can_access_peer(p_ctx: *CudaContext, p_peer: *gstcuda.CudaContext) c_int;
    pub const canAccessPeer = gst_cuda_context_can_access_peer;

    /// Get CUDA device context. Caller must not modify and/or destroy
    /// returned device context.
    extern fn gst_cuda_context_get_handle(p_ctx: *CudaContext) ?*anyopaque;
    pub const getHandle = gst_cuda_context_get_handle;

    /// Get required texture alignment by device
    extern fn gst_cuda_context_get_texture_alignment(p_ctx: *CudaContext) c_int;
    pub const getTextureAlignment = gst_cuda_context_get_texture_alignment;

    /// Pushes the given `ctx` onto the CPU thread's stack of current contexts.
    /// The specified context becomes the CPU thread's current context,
    /// so all CUDA functions that operate on the current context are affected.
    extern fn gst_cuda_context_push(p_ctx: *CudaContext) c_int;
    pub const push = gst_cuda_context_push;

    extern fn gst_cuda_context_get_type() usize;
    pub const getGObjectType = gst_cuda_context_get_type;

    extern fn g_object_ref(p_self: *gstcuda.CudaContext) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstcuda.CudaContext) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *CudaContext, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// A `gstcuda.CudaAllocator` subclass for cuda memory pool
pub const CudaPoolAllocator = extern struct {
    pub const Parent = gstcuda.CudaAllocator;
    pub const Implements = [_]type{};
    pub const Class = gstcuda.CudaPoolAllocatorClass;
    f_parent: gstcuda.CudaAllocator,
    f_context: ?*gstcuda.CudaContext,
    f_stream: ?*gstcuda.CudaStream,
    f_info: gstvideo.VideoInfo,
    f_priv: ?*gstcuda.CudaPoolAllocatorPrivate,
    f__gst_reserved: [4]*anyopaque,

    pub const virtual_methods = struct {};

    pub const properties = struct {};

    pub const signals = struct {};

    /// Creates a new `gstcuda.CudaPoolAllocator` instance.
    extern fn gst_cuda_pool_allocator_new(p_context: *gstcuda.CudaContext, p_stream: ?*gstcuda.CudaStream, p_info: *const gstvideo.VideoInfo) *gstcuda.CudaPoolAllocator;
    pub const new = gst_cuda_pool_allocator_new;

    /// Creates a new `gstcuda.CudaPoolAllocator` instance for virtual memory allocation.
    extern fn gst_cuda_pool_allocator_new_for_virtual_memory(p_context: *gstcuda.CudaContext, p_stream: ?*gstcuda.CudaStream, p_info: *const gstvideo.VideoInfo, p_prop: *const cudagst.memAllocationProp, p_granularity_flags: cudagst.memAllocationGranularity_flags) *gstcuda.CudaPoolAllocator;
    pub const newForVirtualMemory = gst_cuda_pool_allocator_new_for_virtual_memory;

    /// Creates a new `gstcuda.CudaPoolAllocator` instance with given `config`
    extern fn gst_cuda_pool_allocator_new_full(p_context: *gstcuda.CudaContext, p_stream: ?*gstcuda.CudaStream, p_info: *const gstvideo.VideoInfo, p_config: ?*gst.Structure) *gstcuda.CudaPoolAllocator;
    pub const newFull = gst_cuda_pool_allocator_new_full;

    /// Acquires a `gst.Memory` from `allocator`. `memory` should point to a memory
    /// location that can hold a pointer to the new `gst.Memory`.
    extern fn gst_cuda_pool_allocator_acquire_memory(p_allocator: *CudaPoolAllocator, p_memory: **gst.Memory) gst.FlowReturn;
    pub const acquireMemory = gst_cuda_pool_allocator_acquire_memory;

    extern fn gst_cuda_pool_allocator_get_type() usize;
    pub const getGObjectType = gst_cuda_pool_allocator_get_type;

    extern fn g_object_ref(p_self: *gstcuda.CudaPoolAllocator) void;
    pub const ref = g_object_ref;

    extern fn g_object_unref(p_self: *gstcuda.CudaPoolAllocator) void;
    pub const unref = g_object_unref;

    pub fn as(p_instance: *CudaPoolAllocator, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaAllocatorClass = extern struct {
    pub const Instance = gstcuda.CudaAllocator;

    f_parent_class: gst.AllocatorClass,
    f_set_active: ?*const fn (p_allocator: *gstcuda.CudaAllocator, p_active: c_int) callconv(.c) c_int,
    f__gst_reserved: [20]*anyopaque,

    pub fn as(p_instance: *CudaAllocatorClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaAllocatorPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaBufferPoolClass = extern struct {
    pub const Instance = gstcuda.CudaBufferPool;

    f_parent_class: gst.BufferPoolClass,

    pub fn as(p_instance: *CudaBufferPoolClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaBufferPoolPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaContextClass = extern struct {
    pub const Instance = gstcuda.CudaContext;

    f_parent_class: gst.ObjectClass,

    pub fn as(p_instance: *CudaContextClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaContextPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaGraphicsResource = extern struct {
    f_cuda_context: ?*gstcuda.CudaContext,
    f_graphics_context: ?*gst.Object,
    f_type: gstcuda.CudaGraphicsResourceType,
    f_resource: cudagst.graphicsResource,
    f_flags: cudagst.graphicsRegisterFlags,
    f_registered: c_int,
    f_mapped: c_int,

    /// Create new `gstcuda.CudaGraphicsResource` with given `context` and `type`
    extern fn gst_cuda_graphics_resource_new(p_context: *gstcuda.CudaContext, p_graphics_context: ?*gst.Object, p_type: gstcuda.CudaGraphicsResourceType) *gstcuda.CudaGraphicsResource;
    pub const new = gst_cuda_graphics_resource_new;

    /// Free `resource`
    extern fn gst_cuda_graphics_resource_free(p_resource: *CudaGraphicsResource) void;
    pub const free = gst_cuda_graphics_resource_free;

    /// Map previously registered resource with map flags
    extern fn gst_cuda_graphics_resource_map(p_resource: *CudaGraphicsResource, p_stream: cudagst.stream, p_flags: cudagst.graphicsMapResourceFlags) cudagst.graphicsResource;
    pub const map = gst_cuda_graphics_resource_map;

    /// `resource` a `gstcuda.CudaGraphicsResource`
    /// Register the `buffer` for access by CUDA.
    /// Must be called from the gl context thread with current cuda context was
    /// pushed on the current thread
    extern fn gst_cuda_graphics_resource_register_gl_buffer(p_resource: *CudaGraphicsResource, p_buffer: c_uint, p_flags: cudagst.graphicsRegisterFlags) c_int;
    pub const registerGlBuffer = gst_cuda_graphics_resource_register_gl_buffer;

    /// Unmap previously mapped resource
    extern fn gst_cuda_graphics_resource_unmap(p_resource: *CudaGraphicsResource, p_stream: cudagst.stream) void;
    pub const unmap = gst_cuda_graphics_resource_unmap;

    /// Unregister previously registered resource.
    /// For GL resource, this method must be called from gl context thread.
    /// Also, current cuda context should be pushed on the current thread
    /// before calling this method.
    extern fn gst_cuda_graphics_resource_unregister(p_resource: *CudaGraphicsResource) void;
    pub const unregister = gst_cuda_graphics_resource_unregister;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaMemory = extern struct {
    f_mem: gst.Memory,
    f_context: ?*gstcuda.CudaContext,
    f_info: gstvideo.VideoInfo,
    f_priv: ?*gstcuda.CudaMemoryPrivate,
    f__gst_reserved: [4]*anyopaque,

    /// Ensures that the `gstcuda.CudaAllocator` is initialized and ready to be used.
    extern fn gst_cuda_memory_init_once() void;
    pub const initOnce = gst_cuda_memory_init_once;

    /// Exports virtual memory handle to OS specific handle.
    ///
    /// On Windows, `os_handle` should be pointer to HANDLE (i.e., void **), and
    /// pointer to file descriptor (i.e., int *) on Linux.
    ///
    /// The returned `os_handle` is owned by `mem` and therefore caller shouldn't
    /// close the handle.
    extern fn gst_cuda_memory_export(p_mem: *CudaMemory, p_os_handle: ?*anyopaque) c_int;
    pub const @"export" = gst_cuda_memory_export;

    /// Query allocation method
    extern fn gst_cuda_memory_get_alloc_method(p_mem: *CudaMemory) gstcuda.CudaMemoryAllocMethod;
    pub const getAllocMethod = gst_cuda_memory_get_alloc_method;

    /// Gets CUDA stream object associated with `mem`
    extern fn gst_cuda_memory_get_stream(p_mem: *CudaMemory) ?*gstcuda.CudaStream;
    pub const getStream = gst_cuda_memory_get_stream;

    /// Creates CUtexObject with given parameters
    extern fn gst_cuda_memory_get_texture(p_mem: *CudaMemory, p_plane: c_uint, p_filter_mode: cudagst.filter_mode, p_texture: *cudagst.texObject) c_int;
    pub const getTexture = gst_cuda_memory_get_texture;

    /// Gets back user data pointer stored via `gstcuda.CudaMemory.setTokenData`
    extern fn gst_cuda_memory_get_token_data(p_mem: *CudaMemory, p_token: i64) ?*anyopaque;
    pub const getTokenData = gst_cuda_memory_get_token_data;

    /// Gets user data pointer stored via `gstcuda.CudaAllocator.allocWrapped`
    extern fn gst_cuda_memory_get_user_data(p_mem: *CudaMemory) ?*anyopaque;
    pub const getUserData = gst_cuda_memory_get_user_data;

    /// Sets an opaque user data on a `gstcuda.CudaMemory`
    extern fn gst_cuda_memory_set_token_data(p_mem: *CudaMemory, p_token: i64, p_data: ?*anyopaque, p_notify: glib.DestroyNotify) void;
    pub const setTokenData = gst_cuda_memory_set_token_data;

    /// Performs synchronization if needed
    extern fn gst_cuda_memory_sync(p_mem: *CudaMemory) void;
    pub const sync = gst_cuda_memory_sync;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaMemoryPool = extern struct {
    f_parent: gst.MiniObject,
    f_context: ?*gstcuda.CudaContext,
    f_priv: ?*gstcuda.CudaMemoryPoolPrivate,

    /// Creates a new `gstcuda.CudaMemoryPool` with `props`. If `props` is `NULL`,
    /// non-exportable pool property will be used.
    extern fn gst_cuda_memory_pool_new(p_context: *gstcuda.CudaContext, p_props: ?*const cudagst.memPoolProps) ?*gstcuda.CudaMemoryPool;
    pub const new = gst_cuda_memory_pool_new;

    /// Get CUDA memory pool handle
    extern fn gst_cuda_memory_pool_get_handle(p_pool: *CudaMemoryPool) cudagst.memoryPool;
    pub const getHandle = gst_cuda_memory_pool_get_handle;

    /// Increase the reference count of `pool`.
    extern fn gst_cuda_memory_pool_ref(p_pool: *CudaMemoryPool) *gstcuda.CudaMemoryPool;
    pub const ref = gst_cuda_memory_pool_ref;

    /// Decrease the reference count of `pool`.
    extern fn gst_cuda_memory_pool_unref(p_pool: *CudaMemoryPool) void;
    pub const unref = gst_cuda_memory_pool_unref;

    extern fn gst_cuda_memory_pool_get_type() usize;
    pub const getGObjectType = gst_cuda_memory_pool_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaMemoryPoolPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaMemoryPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaPoolAllocatorClass = extern struct {
    pub const Instance = gstcuda.CudaPoolAllocator;

    f_parent_class: gstcuda.CudaAllocatorClass,
    f__gst_reserved: [4]*anyopaque,

    pub fn as(p_instance: *CudaPoolAllocatorClass, comptime P_T: type) *P_T {
        return gobject.ext.as(P_T, p_instance);
    }

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaPoolAllocatorPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaStream = extern struct {
    f_parent: gst.MiniObject,
    f_context: ?*gstcuda.CudaContext,
    f_priv: ?*gstcuda.CudaStreamPrivate,

    /// Creates a new `gstcuda.CudaStream`
    extern fn gst_cuda_stream_new(p_context: *gstcuda.CudaContext) ?*gstcuda.CudaStream;
    pub const new = gst_cuda_stream_new;

    /// Get CUDA stream handle
    extern fn gst_cuda_stream_get_handle(p_stream: ?*CudaStream) cudagst.stream;
    pub const getHandle = gst_cuda_stream_get_handle;

    /// Increase the reference count of `stream`.
    extern fn gst_cuda_stream_ref(p_stream: *CudaStream) *gstcuda.CudaStream;
    pub const ref = gst_cuda_stream_ref;

    /// Decrease the reference count of `stream`.
    extern fn gst_cuda_stream_unref(p_stream: *CudaStream) void;
    pub const unref = gst_cuda_stream_unref;

    extern fn gst_cuda_stream_get_type() usize;
    pub const getGObjectType = gst_cuda_stream_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaStreamPrivate = opaque {
    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaGraphicsResourceType = enum(c_int) {
    none = 0,
    gl_buffer = 1,
    d3d11_resource = 2,
    egl_resource = 3,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// CUDA memory allocation method
pub const CudaMemoryAllocMethod = enum(c_int) {
    unknown = 0,
    malloc = 1,
    mmap = 2,
    _,

    extern fn gst_cuda_memory_alloc_method_get_type() usize;
    pub const getGObjectType = gst_cuda_memory_alloc_method_get_type;

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

pub const CudaQuarkId = enum(c_int) {
    graphics_resource = 0,
    max = 1,
    _,

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// CUDA memory transfer flags
pub const CudaMemoryTransfer = packed struct(c_uint) {
    _padding0: bool = false,
    _padding1: bool = false,
    _padding2: bool = false,
    _padding3: bool = false,
    _padding4: bool = false,
    _padding5: bool = false,
    _padding6: bool = false,
    _padding7: bool = false,
    _padding8: bool = false,
    _padding9: bool = false,
    _padding10: bool = false,
    _padding11: bool = false,
    _padding12: bool = false,
    _padding13: bool = false,
    _padding14: bool = false,
    _padding15: bool = false,
    _padding16: bool = false,
    _padding17: bool = false,
    _padding18: bool = false,
    _padding19: bool = false,
    download: bool = false,
    upload: bool = false,
    sync: bool = false,
    _padding23: bool = false,
    _padding24: bool = false,
    _padding25: bool = false,
    _padding26: bool = false,
    _padding27: bool = false,
    _padding28: bool = false,
    _padding29: bool = false,
    _padding30: bool = false,
    _padding31: bool = false,

    pub const flags_download: CudaMemoryTransfer = @bitCast(@as(c_uint, 1048576));
    pub const flags_upload: CudaMemoryTransfer = @bitCast(@as(c_uint, 2097152));
    pub const flags_sync: CudaMemoryTransfer = @bitCast(@as(c_uint, 4194304));

    test {
        @setEvalBranchQuota(100_000);
        std.testing.refAllDecls(@This());
    }
};

/// Gets configured allocation method
extern fn gst_buffer_pool_config_get_cuda_alloc_method(p_config: *gst.Structure) gstcuda.CudaMemoryAllocMethod;
pub const bufferPoolConfigGetCudaAllocMethod = gst_buffer_pool_config_get_cuda_alloc_method;

extern fn gst_buffer_pool_config_get_cuda_stream(p_config: *gst.Structure) ?*gstcuda.CudaStream;
pub const bufferPoolConfigGetCudaStream = gst_buffer_pool_config_get_cuda_stream;

extern fn gst_buffer_pool_config_get_cuda_stream_ordered_alloc(p_config: *gst.Structure, p_enabled: *c_int) c_int;
pub const bufferPoolConfigGetCudaStreamOrderedAlloc = gst_buffer_pool_config_get_cuda_stream_ordered_alloc;

/// Sets allocation method
extern fn gst_buffer_pool_config_set_cuda_alloc_method(p_config: *gst.Structure, p_method: gstcuda.CudaMemoryAllocMethod) void;
pub const bufferPoolConfigSetCudaAllocMethod = gst_buffer_pool_config_set_cuda_alloc_method;

/// Sets `stream` on `config`
extern fn gst_buffer_pool_config_set_cuda_stream(p_config: *gst.Structure, p_stream: *gstcuda.CudaStream) void;
pub const bufferPoolConfigSetCudaStream = gst_buffer_pool_config_set_cuda_stream;

/// Sets stream ordered allocation option
extern fn gst_buffer_pool_config_set_cuda_stream_ordered_alloc(p_config: *gst.Structure, p_stream_ordered: c_int) void;
pub const bufferPoolConfigSetCudaStreamOrderedAlloc = gst_buffer_pool_config_set_cuda_stream_ordered_alloc;

/// Clears a reference to a `gstcuda.CudaMemoryPool`.
extern fn gst_clear_cuda_memory_pool(p_pool: **gstcuda.CudaMemoryPool) void;
pub const clearCudaMemoryPool = gst_clear_cuda_memory_pool;

/// Clears a reference to a `gstcuda.CudaStream`.
extern fn gst_clear_cuda_stream(p_stream: **gstcuda.CudaStream) void;
pub const clearCudaStream = gst_clear_cuda_stream;

extern fn gst_context_new_cuda_context(p_cuda_ctx: *gstcuda.CudaContext) *gst.Context;
pub const contextNewCudaContext = gst_context_new_cuda_context;

/// Creates new user token value
extern fn gst_cuda_create_user_token() i64;
pub const cudaCreateUserToken = gst_cuda_create_user_token;

/// Perform the steps necessary for retrieving a `gstcuda.CudaContext` from the
/// surrounding elements or from the application using the `gst.Context` mechanism.
///
/// If the content of `cuda_ctx` is not `NULL`, then no `gst.Context` query is
/// necessary for `gstcuda.CudaContext`.
extern fn gst_cuda_ensure_element_context(p_element: *gst.Element, p_device_id: c_int, p_cuda_ctx: **gstcuda.CudaContext) c_int;
pub const cudaEnsureElementContext = gst_cuda_ensure_element_context;

extern fn gst_cuda_handle_context_query(p_element: *gst.Element, p_query: *gst.Query, p_cuda_ctx: ?*gstcuda.CudaContext) c_int;
pub const cudaHandleContextQuery = gst_cuda_handle_context_query;

/// Helper function for implementing `gst.ElementClass.virtual_methods.set_context` in
/// CUDA capable elements.
///
/// Retrieves the `gstcuda.CudaContext` in `context` and places the result in `cuda_ctx`.
extern fn gst_cuda_handle_set_context(p_element: *gst.Element, p_context: *gst.Context, p_device_id: c_int, p_cuda_ctx: **gstcuda.CudaContext) c_int;
pub const cudaHandleSetContext = gst_cuda_handle_set_context;

/// Loads the cuda library
extern fn gst_cuda_load_library() c_int;
pub const cudaLoadLibrary = gst_cuda_load_library;

extern fn gst_cuda_nvrtc_compile(p_source: [*:0]const u8) [*:0]u8;
pub const cudaNvrtcCompile = gst_cuda_nvrtc_compile;

extern fn gst_cuda_nvrtc_compile_cubin(p_source: [*:0]const u8, p_device: c_int) [*:0]u8;
pub const cudaNvrtcCompileCubin = gst_cuda_nvrtc_compile_cubin;

/// Loads the nvrtc library.
extern fn gst_cuda_nvrtc_load_library() c_int;
pub const cudaNvrtcLoadLibrary = gst_cuda_nvrtc_load_library;

extern fn gst_cuda_quark_from_id(p_id: gstcuda.CudaQuarkId) glib.Quark;
pub const cudaQuarkFromId = gst_cuda_quark_from_id;

/// Sets global need-pool callback function
extern fn gst_cuda_register_allocator_need_pool_callback(p_callback: gstcuda.CudaMemoryAllocatorNeedPoolCallback, p_user_data: ?*anyopaque, p_notify: ?glib.DestroyNotify) void;
pub const cudaRegisterAllocatorNeedPoolCallback = gst_cuda_register_allocator_need_pool_callback;

/// Check if `mem` is a cuda memory
extern fn gst_is_cuda_memory(p_mem: *gst.Memory) c_int;
pub const isCudaMemory = gst_is_cuda_memory;

/// Called to request cuda memory pool object. If callee returns a memory pool,
/// `allocator` will allocate memory via cuMemAllocFromPoolAsync.
/// Otherwise device default memory pool will be used with cuMemAllocAsync method
pub const CudaMemoryAllocatorNeedPoolCallback = *const fn (p_allocator: *gstcuda.CudaAllocator, p_context: *gstcuda.CudaContext, p_user_data: ?*anyopaque) callconv(.c) ?*gstcuda.CudaMemoryPool;

/// Name of the caps feature for indicating the use of `gstcuda.CudaMemory`
pub const CAPS_FEATURE_MEMORY_CUDA_MEMORY = "memory:CUDAMemory";
/// `G_TYPE_BOOLEAN` Allows stream ordered allocation. Default is `FALSE`
pub const CUDA_ALLOCATOR_OPT_STREAM_ORDERED = "GstCudaAllocator.stream-ordered";
pub const CUDA_CONTEXT_TYPE = "gst.cuda.context";
/// Name of cuda memory type
pub const CUDA_MEMORY_TYPE_NAME = "gst.cuda.memory";
/// Flag indicating that we should map the CUDA device memory
/// instead of to system memory.
///
/// Combining `GST_MAP_CUDA` with `GST_MAP_WRITE` has the same semantics as though
/// you are writing to CUDA device/host memory.
/// Conversely, combining `GST_MAP_CUDA` with
/// `GST_MAP_READ` has the same semantics as though you are reading from
/// CUDA device/host memory
pub const MAP_CUDA = 131072;

test {
    @setEvalBranchQuota(100_000);
    std.testing.refAllDecls(@This());
    std.testing.refAllDecls(ext);
}
