pub const ext = @import("ext.zig");
const gstanalytics = @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");
/// Type of analytics meta data
pub const MtdType = usize;

/// Handle containing data required to use gst_analytics_cls_mtd APIs. This type
/// is generally expected to be allocated on the stack.
pub const ClsMtd = extern struct {
    /// Instance identifier
    f_id: c_uint,
    /// Instance of `gstanalytics.RelationMeta` where the analytics-metadata
    /// identified by `id` is stored.
    f_meta: ?*gstanalytics.RelationMeta,

    /// Get an id identifying `gstanalytics.Mtd` type.
    extern fn gst_analytics_cls_mtd_get_mtd_type() gstanalytics.MtdType;
    pub const getMtdType = gst_analytics_cls_mtd_get_mtd_type;

    extern fn gst_analytics_cls_mtd_get_index_by_quark(p_handle: *const ClsMtd, p_quark: glib.Quark) c_int;
    pub const getIndexByQuark = gst_analytics_cls_mtd_get_index_by_quark;

    extern fn gst_analytics_cls_mtd_get_length(p_handle: *const ClsMtd) usize;
    pub const getLength = gst_analytics_cls_mtd_get_length;

    /// Get confidence level for class at `index`
    extern fn gst_analytics_cls_mtd_get_level(p_handle: *const ClsMtd, p_index: usize) f32;
    pub const getLevel = gst_analytics_cls_mtd_get_level;

    extern fn gst_analytics_cls_mtd_get_quark(p_handle: *const ClsMtd, p_index: usize) glib.Quark;
    pub const getQuark = gst_analytics_cls_mtd_get_quark;

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

/// Handle containing data required to use gst_analytics_mtd API. This type
/// is generally expected to be allocated on the stack.
pub const Mtd = extern struct {
    /// Instance identifier
    f_id: c_uint,
    /// Instance of `gstanalytics.RelationMeta` where the analytics-metadata
    /// identified by `id` is stored.
    f_meta: ?*gstanalytics.RelationMeta,

    /// Gets the string version of the name of this type of analytics data
    extern fn gst_analytics_mtd_type_get_name(p_type: gstanalytics.MtdType) [*:0]const u8;
    pub const typeGetName = gst_analytics_mtd_type_get_name;

    /// Get instance id
    extern fn gst_analytics_mtd_get_id(p_instance: *const Mtd) c_uint;
    pub const getId = gst_analytics_mtd_get_id;

    extern fn gst_analytics_mtd_get_mtd_type(p_instance: *const Mtd) gstanalytics.MtdType;
    pub const getMtdType = gst_analytics_mtd_get_mtd_type;

    /// Get instance size
    extern fn gst_analytics_mtd_get_size(p_instance: *const Mtd) usize;
    pub const getSize = gst_analytics_mtd_get_size;

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

/// This structure must be provided when registering a new type of Mtd. It must
/// have a static lifetime (never be freed).
pub const MtdImpl = extern struct {
    /// The name of the metadata type
    f_name: ?[*:0]const u8,
    /// A pointer to a function that will be called
    /// when the containing meta is transform to potentially copy the data
    /// into a new Mtd into the new meta.
    f_mtd_meta_transform: ?*const fn (p_transbuf: *gst.Buffer, p_transmtd: *gstanalytics.Mtd, p_buffer: *gst.Buffer, p_type: glib.Quark, p_data: *anyopaque) callconv(.c) c_int,
    /// A pointer to a function that will be called when the
    /// containing meta is cleared to potetially do cleanup (ex. _unref or release)
    /// resources it was using.
    f_mtd_meta_clear: ?*const fn (p_buffer: *gst.Buffer, p_mtd: *gstanalytics.Mtd) callconv(.c) void,
    f__reserved: [19]*anyopaque,

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

/// Handle containing data required to use gst_analytics_od_mtd APIs. This type
/// is generally expected to be allocated on the stack.
pub const ODMtd = extern struct {
    /// Instance identifier
    f_id: c_uint,
    /// Instance of `gstanalytics.RelationMeta` where the analytics-metadata
    /// identified by `id` is stored.
    f_meta: ?*gstanalytics.RelationMeta,

    /// Get an id that represent object-detection metadata type
    extern fn gst_analytics_od_mtd_get_mtd_type() gstanalytics.MtdType;
    pub const getMtdType = gst_analytics_od_mtd_get_mtd_type;

    /// Retrieve location confidence level.
    extern fn gst_analytics_od_mtd_get_confidence_lvl(p_instance: *const ODMtd, p_loc_conf_lvl: *f32) c_int;
    pub const getConfidenceLvl = gst_analytics_od_mtd_get_confidence_lvl;

    /// Retrieve location and location confidence level.
    extern fn gst_analytics_od_mtd_get_location(p_instance: *const ODMtd, p_x: *c_int, p_y: *c_int, p_w: *c_int, p_h: *c_int, p_loc_conf_lvl: ?*f32) c_int;
    pub const getLocation = gst_analytics_od_mtd_get_location;

    /// Quark of the class of object associated with this location.
    extern fn gst_analytics_od_mtd_get_obj_type(p_handle: *const ODMtd) glib.Quark;
    pub const getObjType = gst_analytics_od_mtd_get_obj_type;

    /// Retrieve oriented location and location confidence level.
    extern fn gst_analytics_od_mtd_get_oriented_location(p_instance: *const ODMtd, p_x: *c_int, p_y: *c_int, p_w: *c_int, p_h: *c_int, p_r: *f32, p_loc_conf_lvl: ?*f32) c_int;
    pub const getOrientedLocation = gst_analytics_od_mtd_get_oriented_location;

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

/// An opaque `gst.Meta` that can be used to hold various types of results
/// from analysis processes.
///
/// The content should be accessed through the API.
pub const RelationMeta = opaque {
    /// Get the meta info
    extern fn gst_analytics_relation_meta_get_info() *const gst.MetaInfo;
    pub const getInfo = gst_analytics_relation_meta_get_info;

    /// Add analytic classification metadata to `instance`.
    extern fn gst_analytics_relation_meta_add_cls_mtd(p_instance: *RelationMeta, p_length: usize, p_confidence_levels: [*]f32, p_class_quarks: [*]glib.Quark, p_cls_mtd: *gstanalytics.ClsMtd) c_int;
    pub const addClsMtd = gst_analytics_relation_meta_add_cls_mtd;

    /// Add a relatable metadata to `meta`. This method is meant to be used by
    /// new struct sub-classing GstAnalyticsRelatableMtd.
    extern fn gst_analytics_relation_meta_add_mtd(p_meta: *RelationMeta, p_impl: *const gstanalytics.MtdImpl, p_size: usize, p_rlt_mtd: ?*gstanalytics.Mtd) ?*anyopaque;
    pub const addMtd = gst_analytics_relation_meta_add_mtd;

    extern fn gst_analytics_relation_meta_add_od_mtd(p_instance: *RelationMeta, p_type: glib.Quark, p_x: c_int, p_y: c_int, p_w: c_int, p_h: c_int, p_loc_conf_lvl: f32, p_od_mtd: ?*gstanalytics.ODMtd) c_int;
    pub const addOdMtd = gst_analytics_relation_meta_add_od_mtd;

    /// Add analytic classification metadata to `instance`.
    extern fn gst_analytics_relation_meta_add_one_cls_mtd(p_instance: *RelationMeta, p_confidence_level: f32, p_class_quark: glib.Quark, p_cls_mtd: *gstanalytics.ClsMtd) c_int;
    pub const addOneClsMtd = gst_analytics_relation_meta_add_one_cls_mtd;

    extern fn gst_analytics_relation_meta_add_oriented_od_mtd(p_instance: *RelationMeta, p_type: glib.Quark, p_x: c_int, p_y: c_int, p_w: c_int, p_h: c_int, p_r: f32, p_loc_conf_lvl: f32, p_od_mtd: ?*gstanalytics.ODMtd) c_int;
    pub const addOrientedOdMtd = gst_analytics_relation_meta_add_oriented_od_mtd;

    /// Add analytics segmentation metadata to `instance`. The rectangle (`masks_loc_x`,
    /// `mask_loc_y`, `mask_loc_w`, `mask_loc_h`) define a area of the image that
    /// correspond to the segmentation masks stored in `buffer`. For example if the
    /// segmentation masks stored in `buffer` describe the segmented regions for the
    /// entire image the rectangular area will be (`masks_loc_x` = 0, `masks_loc_y` = 0,
    /// `masks_loc_w` = image_width, `masks_loc_h` = image_height).
    extern fn gst_analytics_relation_meta_add_segmentation_mtd(p_instance: *RelationMeta, p_buffer: *gst.Buffer, p_segmentation_type: gstanalytics.SegmentationType, p_region_count: usize, p_region_ids: [*]c_uint, p_masks_loc_x: c_int, p_masks_loc_y: c_int, p_masks_loc_w: c_uint, p_masks_loc_h: c_uint, p_segmentation_mtd: *gstanalytics.SegmentationMtd) c_int;
    pub const addSegmentationMtd = gst_analytics_relation_meta_add_segmentation_mtd;

    extern fn gst_analytics_relation_meta_add_tracking_mtd(p_instance: *RelationMeta, p_tracking_id: u64, p_tracking_first_seen: gst.ClockTime, p_trk_mtd: *gstanalytics.TrackingMtd) c_int;
    pub const addTrackingMtd = gst_analytics_relation_meta_add_tracking_mtd;

    /// Verify existence of relation(s) between `an_meta_first_d` and
    /// `an_meta_second_id` according to relation condition `cond_types`. It optionally
    /// also return a shortest path of relations ( compliant with `cond_types`)
    /// between `an_meta_first_id` and `an_meta_second_id`.
    extern fn gst_analytics_relation_meta_exist(p_rmeta: *const RelationMeta, p_an_meta_first_id: c_uint, p_an_meta_second_id: c_uint, p_max_relation_span: c_int, p_cond_types: gstanalytics.RelTypes, p_relations_path: ?**glib.Array) c_int;
    pub const exist = gst_analytics_relation_meta_exist;

    /// Fill `rlt` if a analytics-meta with id == `an_meta_id` exist in `meta` instance,
    /// otherwise this method return FALSE and `rlt` is invalid.
    extern fn gst_analytics_relation_meta_get_cls_mtd(p_meta: *RelationMeta, p_an_meta_id: c_uint, p_rlt: *gstanalytics.ClsMtd) c_int;
    pub const getClsMtd = gst_analytics_relation_meta_get_cls_mtd;

    extern fn gst_analytics_relation_meta_get_direct_related(p_meta: *RelationMeta, p_an_meta_id: c_uint, p_relation_type: gstanalytics.RelTypes, p_type: gstanalytics.MtdType, p_state: *anyopaque, p_rlt_mtd: *gstanalytics.Mtd) c_int;
    pub const getDirectRelated = gst_analytics_relation_meta_get_direct_related;

    /// Fill `rlt` if a analytics-meta with id == `an_meta_id` exist in `meta` instance,
    /// otherwise this method return FALSE and `rlt` is invalid.
    extern fn gst_analytics_relation_meta_get_mtd(p_meta: *RelationMeta, p_an_meta_id: c_uint, p_type: gstanalytics.MtdType, p_rlt: *gstanalytics.Mtd) c_int;
    pub const getMtd = gst_analytics_relation_meta_get_mtd;

    extern fn gst_analytics_relation_meta_get_mtd_data(p_meta: *const RelationMeta, p_an_meta_id: c_uint) ?*anyopaque;
    pub const getMtdData = gst_analytics_relation_meta_get_mtd_data;

    /// Fill `rlt` if a analytics-meta with id == `an_meta_id` exist in `meta` instance,
    /// otherwise this method return FALSE and `rlt` is invalid.
    extern fn gst_analytics_relation_meta_get_od_mtd(p_meta: *RelationMeta, p_an_meta_id: c_uint, p_rlt: *gstanalytics.ODMtd) c_int;
    pub const getOdMtd = gst_analytics_relation_meta_get_od_mtd;

    /// Get relations between first and second analysis-meta.
    /// Ids (`an_meta_first_id` and `an_meta_second_id`) must be from a call to
    /// `gst_analytics_mtd_get_id` (handle).
    extern fn gst_analytics_relation_meta_get_relation(p_meta: *const RelationMeta, p_an_meta_first_id: c_uint, p_an_meta_second_id: c_uint) gstanalytics.RelTypes;
    pub const getRelation = gst_analytics_relation_meta_get_relation;

    /// Fill `rlt` if a analytics-meta with id == `an_meta_id` exist in `meta` instance,
    /// otherwise this method return FALSE and `rlt` is invalid.
    extern fn gst_analytics_relation_meta_get_segmentation_mtd(p_meta: *RelationMeta, p_an_meta_id: c_uint, p_rlt: *gstanalytics.SegmentationMtd) c_int;
    pub const getSegmentationMtd = gst_analytics_relation_meta_get_segmentation_mtd;

    /// Fill `rlt` if a analytics-meta with id == `an_meta_id` exist in `meta` instance,
    /// otherwise this method return FALSE and `rlt` is invalid.
    extern fn gst_analytics_relation_meta_get_tracking_mtd(p_meta: *RelationMeta, p_an_meta_id: c_uint, p_rlt: *gstanalytics.TrackingMtd) c_int;
    pub const getTrackingMtd = gst_analytics_relation_meta_get_tracking_mtd;

    extern fn gst_analytics_relation_meta_iterate(p_meta: *RelationMeta, p_state: ?*anyopaque, p_type: gstanalytics.MtdType, p_rlt_mtd: *gstanalytics.Mtd) c_int;
    pub const iterate = gst_analytics_relation_meta_iterate;

    /// Sets the relation (`gstanalytics.RelTypes`) between `an_meta_first` and
    ///    `an_meta_second`.
    /// Ids must have been obtained a call to
    ///    `gst_analytics_mtd_get_id`(handle).
    extern fn gst_analytics_relation_meta_set_relation(p_meta: *RelationMeta, p_type: gstanalytics.RelTypes, p_an_meta_first_id: c_uint, p_an_meta_second_id: c_uint) c_int;
    pub const setRelation = gst_analytics_relation_meta_set_relation;

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

/// GstAnalyticsRelationMeta initialization parameters.
pub const RelationMetaInitParams = extern struct {
    /// Initial relations order.
    f_initial_relation_order: usize,
    /// Buffer size in bytes to store relatable metadata
    f_initial_buf_size: usize,

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

/// This type of metadata holds information on which pixels belongs to
///  a region of the image representing a type of object.
///
///  It supports two types of segmentation, semantic or instance:
///   * Semantic: All objects of the same type have the same id
///   * Instance: Each instance of an object has a different id
///
///  The results of the segmentation are stored in a `gst.Buffer` that has a
///  `gstvideo.VideoMeta` associated with it. This buffer is stored in the
///  GstAnalyticsSegmentationMtd using
///  `gstanalytics.RelationMeta.addSegmentationMtd``gstanalytics.RelationMeta.addSegmentationMtd`. The `gst.Buffer`
///  containing the segmentation mask is image-like but the color values are
///  arbitrary values, referred by region-id in this API, without meaning beyond
///  specifying that two pixels in the original image with the same values in
///  their corresponding mask value belong to the same region.
///
///  To further describe a region, the `gstanalytics.SegmentationMtd` can be
///  associated with other `gstanalytics.Mtd`. Since region ids are
///  generated by the segmentation process itself and are not always sequential,
///  we use a map of indexes to region ids starting with 0 without discontinuity
///  which facilitate N-to-N mapping with other `gstanalytics.Mtd`. For
///  example it can be associated with `gstanalytics.ClsMtd` to describe the class
///  of object matching the pixels of a segmented region.
///
///  Example: Associate Instance Segmentation with Classification
///
///  In the following example the segmentation process will fill segmask with
///  values of 0 for background, 12 for the first region which correspond to a
///  to a strawberry, 7 for the second region that also correspond to  a
///  strawberry in the image and 31 for the third region that correspond to a
///  leaf in the image.
///  region_ids is fill during segmentation post-processing
///
///  region_ids:
///  |region-index | region-id |
///  |-------------|-----------|
///  | 0           | 0         |
///  | 1           | 12        |
///  | 2           | 7         |
///  | 3           | 31        |
///
///  region_count = 4
///
///  ``` C
///    GstAnalyticsSegmentationMtd segmtd;
///    GstAnalyticsClassificationMtd clsmtd;
///    GstBuffer *segmask, *img;
///    guint *region_ids;
///    gsize region_count, class_count;
///    gfloat *class_confidence;
///    GQuark *classes;
///
///    ... (segmentation filling segmask based on img)
///
///    gst_analytics_relation_meta_add_segmentation_mtd (rmeta, segmask,
///      GST_SEGMENTATION_TYPE_INSTANCE, region_count, region_ids, &segmtd);
///    class_count = region_count;
///
///    ... (class-index must match and correspond to region-index)
///    classes [0]  = g_quark_from_string ("background");
///    classes [1]  = g_quark_from_string ("strawberry");
///    classes [2] = g_quark_from_string ("strawberry");
///    classes [3] = g_quark_from_string ("leaf");
///
///    ... (set confidence level for each class associated with a region
///    ... where -1.0 mean undefined.)
///    class_confidence [0] = -1.0;
///    class_confidence [1] = 0.6;
///    class_confidence [2] = 0.9;
///    class_confidence [3] = 0.8;
///
///    gst_analytics_relation_meta_add_cls_mtd (rmeta, class_count,
///      class_confidence, classes, &clsmtd);
///
///    gst_analytics_relation_meta_set_relation (rmeta,
///     GST_ANALYTICS_REL_TYPE_RELATE_TO, segmtd.id, clsmtd.id);
///  ```
///
///  Example: Associate Semantic Segmentation with Classification
///  Assuming the same context as for Instance Segmentation above but instead
///  a semantic segmentation is performed, therefore region-id-12 and region-id-7
///  are now represented by the same region-id-12
///
///  region_ids: (here
///  |region-index | region-id |
///  |-------------|-----------|
///  | 0           | 0         |
///  | 1           | 12        |
///  | 2           | 31        |
///
///  Code remain the same except that we set all confidence level to undefined
///  (-1.0).
///
///  ```
///    ... (class-index must match and correspond to region-index)
///    classes [0]  = g_quark_from_string ("background");
///    classes [1]  = g_quark_from_string ("strawberry");
///    classes [2] = g_quark_from_string ("leaf");
///
///    ... (set confidence level for each class associated with a region
///    ... where -1.0 mean undefined.)
///    class_confidence [0] = -1.0;
///    class_confidence [1] = -1.0;
///    class_confidence [2] = -1.0;
///
///    gst_analytics_relation_meta_add_cls_mtd (rmeta, class_count,
///      class_confidence, classes, &clsmtd);
///
///    gst_analytics_relation_meta_set_relation (rmeta,
///     GST_ANALYTICS_REL_TYPE_RELATE_TO, segmtd.id, clsmtd.id);
///  ```
///
///  Example: Retrieving class associated with a segmentation region-id-12
///  This the typical case for an overlay as we visit the segmentation mask we
///  we find region-id values
///
///  ```
///  gsize idx;
///  gst_analytics_segmentation_mtd_get_region_index (&segmtd, &idx, 12);
///  gst_analytics_relation_meta_get_direct_related (rmeta, segmtd.id,
///    GST_ANALYTICS_REL_TYPE_RELATE_TO, gst_analytics_cls_mtd_get_type (),
///    NULL, &clsmtd);
///
///   GQuark region_class = gst_analytics_cls_mtd_get_quark (&segmtd, idx)
///   ...
///  ```
///
///  Since: 1.26
pub const SegmentationMtd = extern struct {
    /// Instance identifier
    f_id: c_uint,
    /// Instance of `gstanalytics.RelationMeta` where the analytics-metadata
    /// identified by `id` is stored.
    f_meta: ?*gstanalytics.RelationMeta,

    /// Get an instance of `gstanalytics.MtdType` that represent segmentation
    /// metadata type.
    extern fn gst_analytics_segmentation_mtd_get_mtd_type() gstanalytics.MtdType;
    pub const getMtdType = gst_analytics_segmentation_mtd_get_mtd_type;

    /// Get segmentation mask data.
    extern fn gst_analytics_segmentation_mtd_get_mask(p_handle: *const SegmentationMtd, p_masks_loc_x: ?*c_int, p_masks_loc_y: ?*c_int, p_masks_loc_w: ?*c_uint, p_masks_loc_h: ?*c_uint) *gst.Buffer;
    pub const getMask = gst_analytics_segmentation_mtd_get_mask;

    /// Get the regions count.
    extern fn gst_analytics_segmentation_mtd_get_region_count(p_handle: *const SegmentationMtd) usize;
    pub const getRegionCount = gst_analytics_segmentation_mtd_get_region_count;

    /// Get id of the region corresponding to `index`, which should be
    /// smaller than the return value of
    /// `gstanalytics.SegmentationMtd.getRegionCount`
    extern fn gst_analytics_segmentation_mtd_get_region_id(p_handle: *const SegmentationMtd, p_index: usize) c_uint;
    pub const getRegionId = gst_analytics_segmentation_mtd_get_region_id;

    /// Get region index of the region identified by `id`.
    extern fn gst_analytics_segmentation_mtd_get_region_index(p_handle: *const SegmentationMtd, p_index: *usize, p_id: c_uint) c_int;
    pub const getRegionIndex = gst_analytics_segmentation_mtd_get_region_index;

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

/// Hold tensor data
pub const Tensor = extern struct {
    /// semantically identify the contents of the tensor
    f_id: glib.Quark,
    /// Indicate tensor layout
    f_layout: gstanalytics.TensorLayout,
    /// `gstanalytics.TensorDataType` of tensor data
    f_data_type: gstanalytics.TensorDataType,
    /// `gst.Buffer` holding tensor data
    f_data: ?*gst.Buffer,
    /// Indicate tensor elements layout in memory.
    f_dims_order: gstanalytics.TensorDimOrder,
    /// number of tensor dimensions
    f_num_dims: usize,
    /// number of tensor dimensions
    f_dims: ?[*]usize,

    /// Allocate a tensor with `num_dims` dimensions.
    extern fn gst_tensor_alloc(p_num_dims: usize) *gstanalytics.Tensor;
    pub const alloc = gst_tensor_alloc;

    /// Allocates a new `gstanalytics.Tensor` of `dims_order` ROW_MAJOR or COLUMN_MAJOR and
    /// with an interleaved layout
    extern fn gst_tensor_new_simple(p_id: glib.Quark, p_data_type: gstanalytics.TensorDataType, p_data: *gst.Buffer, p_dims_order: gstanalytics.TensorDimOrder, p_num_dims: usize, p_dims: [*]usize) *gstanalytics.Tensor;
    pub const newSimple = gst_tensor_new_simple;

    /// Create a copy of `tensor`.
    extern fn gst_tensor_copy(p_tensor: ?*const Tensor) ?*gstanalytics.Tensor;
    pub const copy = gst_tensor_copy;

    /// Free tensor
    extern fn gst_tensor_free(p_tensor: *Tensor) void;
    pub const free = gst_tensor_free;

    /// Gets the dimensions of the tensor.
    extern fn gst_tensor_get_dims(p_tensor: *Tensor, p_num_dims: *usize) [*]usize;
    pub const getDims = gst_tensor_get_dims;

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

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

pub const TensorMeta = extern struct {
    /// parent
    f_meta: gst.Meta,
    /// number of tensors
    f_num_tensors: usize,
    f_tensors: ?**gstanalytics.Tensor,

    extern fn gst_tensor_meta_get_info() *const gst.MetaInfo;
    pub const getInfo = gst_tensor_meta_get_info;

    /// Retrieves a tensor from the `gstanalytics.TensorMeta`, the index must be
    /// smaller than `gstanalytics.TensorMeta.num_tensors`
    extern fn gst_tensor_meta_get(p_tmeta: *TensorMeta, p_index: usize) *const gstanalytics.Tensor;
    pub const get = gst_tensor_meta_get;

    /// Finds the first tensor with the requsted ID in the meta
    extern fn gst_tensor_meta_get_index_from_id(p_meta: *TensorMeta, p_id: glib.Quark) c_int;
    pub const getIndexFromId = gst_tensor_meta_get_index_from_id;

    /// Sets tensors into the `gstanalytics.TensorMeta`
    extern fn gst_tensor_meta_set(p_tmeta: *TensorMeta, p_num_tensors: c_uint, p_tensors: [*]*gstanalytics.Tensor) void;
    pub const set = gst_tensor_meta_set;

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

/// Store information on results of object tracking
pub const TrackingMtd = extern struct {
    /// Instance identifier
    f_id: c_uint,
    /// Instance of `gstanalytics.RelationMeta` where the analytics-metadata
    /// identified by `id` is stored.
    f_meta: ?*gstanalytics.RelationMeta,

    extern fn gst_analytics_tracking_mtd_get_mtd_type() gstanalytics.MtdType;
    pub const getMtdType = gst_analytics_tracking_mtd_get_mtd_type;

    /// Retrieve tracking information.
    extern fn gst_analytics_tracking_mtd_get_info(p_instance: *const TrackingMtd, p_tracking_id: *u64, p_tracking_first_seen: *gst.ClockTime, p_tracking_last_seen: *gst.ClockTime, p_tracking_lost: *c_int) c_int;
    pub const getInfo = gst_analytics_tracking_mtd_get_info;

    extern fn gst_analytics_tracking_mtd_set_lost(p_instance: *TrackingMtd) c_int;
    pub const setLost = gst_analytics_tracking_mtd_set_lost;

    extern fn gst_analytics_tracking_mtd_update_last_seen(p_instance: *TrackingMtd, p_last_seen: gst.ClockTime) c_int;
    pub const updateLastSeen = gst_analytics_tracking_mtd_update_last_seen;

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

/// Enum value describing supported segmentation type
pub const SegmentationType = enum(c_int) {
    semantic = 0,
    instance = 1,
    _,

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

/// Describe the type of data contain in the tensor.
pub const TensorDataType = enum(c_int) {
    int4 = 0,
    int8 = 1,
    int16 = 2,
    int32 = 3,
    int64 = 4,
    uint4 = 5,
    uint8 = 6,
    uint16 = 7,
    uint32 = 8,
    uint64 = 9,
    float16 = 10,
    float32 = 11,
    float64 = 12,
    bfloat16 = 13,
    _,

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

/// Indicate to read tensor from memory in row-major or column-major order.
pub const TensorDimOrder = enum(c_int) {
    row_major = 0,
    col_major = 1,
    _,

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

/// Indicate tensor storage in memory.
pub const TensorLayout = enum(c_int) {
    tensor_layout_contiguous = 0,
    _,

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

pub const RelTypes = packed struct(c_uint) {
    _padding0: bool = false,
    is_part_of: bool = false,
    contain: bool = false,
    relate_to: bool = false,
    n_to_n: 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,
    _padding20: bool = false,
    _padding21: bool = false,
    _padding22: 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_none: RelTypes = @bitCast(@as(c_uint, 0));
    pub const flags_is_part_of: RelTypes = @bitCast(@as(c_uint, 2));
    pub const flags_contain: RelTypes = @bitCast(@as(c_uint, 4));
    pub const flags_relate_to: RelTypes = @bitCast(@as(c_uint, 8));
    pub const flags_n_to_n: RelTypes = @bitCast(@as(c_uint, 16));
    pub const flags_any: RelTypes = @bitCast(@as(c_uint, 2147483647));

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

/// Attach a analysis-results-meta-relation  meta (`gstanalytics.RelationMeta`)to `buffer`.
///
/// A `gstanalytics.RelationMeta` is a metadata describing relation between other
/// analysis meta. It's more efficient to use `gstanalytics.bufferAddAnalyticsRelationMetaFull`
/// and providing the maximum number of analysis meta that will attached to a buffer.
extern fn gst_buffer_add_analytics_relation_meta(p_buffer: *gst.Buffer) ?*gstanalytics.RelationMeta;
pub const bufferAddAnalyticsRelationMeta = gst_buffer_add_analytics_relation_meta;

/// Attache a analysis-results relation-meta (`gstanalytics.RelationMeta`) to `buffer`.
///
/// A `gstanalytics.RelationMeta` is a metadata describing relation between other
/// analysis meta.
extern fn gst_buffer_add_analytics_relation_meta_full(p_buffer: *gst.Buffer, p_init_params: *gstanalytics.RelationMetaInitParams) ?*gstanalytics.RelationMeta;
pub const bufferAddAnalyticsRelationMetaFull = gst_buffer_add_analytics_relation_meta_full;

/// Adds a `gstanalytics.TensorMeta` to a buffer
extern fn gst_buffer_add_tensor_meta(p_buffer: *gst.Buffer) *gstanalytics.TensorMeta;
pub const bufferAddTensorMeta = gst_buffer_add_tensor_meta;

/// Retrives the meta or `NULL` if it doesn't exist
extern fn gst_buffer_get_analytics_relation_meta(p_buffer: *gst.Buffer) ?*gstanalytics.RelationMeta;
pub const bufferGetAnalyticsRelationMeta = gst_buffer_get_analytics_relation_meta;

/// Gets the `gstanalytics.TensorMeta` from a buffer
extern fn gst_buffer_get_tensor_meta(p_buffer: *gst.Buffer) ?*gstanalytics.TensorMeta;
pub const bufferGetTensorMeta = gst_buffer_get_tensor_meta;

/// Get number of relatable meta attached to instance
extern fn gst_analytics_relation_get_length(p_instance: *const gstanalytics.RelationMeta) usize;
pub const relationGetLength = gst_analytics_relation_get_length;

extern fn gst_analytics_relation_meta_api_get_type() usize;
pub const relationMetaApiGetType = gst_analytics_relation_meta_api_get_type;

extern fn gst_tensor_meta_api_get_type() usize;
pub const tensorMetaApiGetType = gst_tensor_meta_api_get_type;

/// Passes to functions asking for a relation span when the span is
/// infinite.
pub const INF_RELATION_SPAN = -1;
/// A wildcard matching any type of analysis
pub const MTD_TYPE_ANY = 0;

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