1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//! Builders for large params struct from autogenerated bindings.
//!
//! The bindings contain many massive structs which are used as parameters to
//! functions in the API. This module provides builders to simplify creating
//! these struct. They each have a `new()` method which has the minimum required
//! parameters for the struct. Other options

use std::ffi::c_void;

use crate::sys::nvEncodeAPI::{
    GUID,
    NV_ENC_BUFFER_FORMAT,
    NV_ENC_CONFIG,
    NV_ENC_INITIALIZE_PARAMS,
    NV_ENC_INITIALIZE_PARAMS_VER,
    NV_ENC_INPUT_RESOURCE_TYPE,
    NV_ENC_PIC_FLAGS,
    NV_ENC_PIC_PARAMS,
    NV_ENC_PIC_PARAMS_VER,
    NV_ENC_REGISTER_RESOURCE,
    NV_ENC_REGISTER_RESOURCE_VER,
};

impl NV_ENC_INITIALIZE_PARAMS {
    /// Builder for [`NV_ENC_INITIALIZE_PARAMS`].
    #[must_use]
    pub fn new(encode_guid: GUID, width: u32, height: u32) -> Self {
        NV_ENC_INITIALIZE_PARAMS {
            version: NV_ENC_INITIALIZE_PARAMS_VER,
            encodeGUID: encode_guid,
            encodeWidth: width,
            encodeHeight: height,
            ..Default::default()
        }
    }

    /// Specifies the preset for encoding. If the preset GUID is set then
    /// the preset configuration will be applied before any other parameter.
    pub fn preset_guid(&mut self, preset_guid: GUID) -> &mut Self {
        self.presetGUID = preset_guid;
        self
    }

    /// Specifies the advanced codec specific structure. If client has sent a
    /// valid codec config structure, it will override parameters set by the
    /// [`NV_ENC_INITIALIZE_PARAMS::preset_guid`].
    ///
    /// The client can query the interface for codec-specific parameters
    /// using [`Encoder::get_preset_config`](super::encoder::Encoder::get_preset_config).
    /// It can then modify (if required) some of the codec config parameters and
    /// send down a custom config structure using this method. Even in this
    /// case the client is recommended to pass the same preset GUID it has
    /// used to get the config.
    pub fn encode_config(&mut self, encode_config: &mut NV_ENC_CONFIG) -> &mut Self {
        self.encodeConfig = encode_config;
        self
    }

    /// Specifies the display aspect ratio (H264/HEVC) or the render
    /// width/height (AV1).
    pub fn display_aspect_ratio(&mut self, width: u32, height: u32) -> &mut Self {
        self.darWidth = width;
        self.darHeight = height;
        self
    }

    /// Specifies the framerate in frames per second as a fraction
    /// `numerator / denominator`.
    pub fn framerate(&mut self, numerator: u32, denominator: u32) -> &mut Self {
        self.frameRateNum = numerator;
        self.frameRateDen = denominator;
        self
    }

    /// Enable the Picture Type Decision to be taken by the
    /// `NvEncodeAPI` interface.
    pub fn enable_picture_type_decision(&mut self) -> &mut Self {
        self.enablePTD = 1;
        self
    }

    // TODO: Add other options
}

impl NV_ENC_PIC_PARAMS {
    /// Create an EOS empty frame that is used at the
    /// end of encoding to flush the encoder.
    #[must_use]
    pub fn end_of_stream() -> Self {
        NV_ENC_PIC_PARAMS {
            version: NV_ENC_PIC_PARAMS_VER,
            encodePicFlags: NV_ENC_PIC_FLAGS::NV_ENC_PIC_FLAG_EOS as u32,
            ..Default::default()
        }
    }
}

impl NV_ENC_REGISTER_RESOURCE {
    /// Builder for [`NV_ENC_REGISTER_RESOURCE`].
    ///
    /// # Arguments
    ///
    /// * `resource_type` - Specifies the type of resource to be registered.
    ///   Supported values are:
    ///   - [`NV_ENC_INPUT_RESOURCE_TYPE::NV_ENC_INPUT_RESOURCE_TYPE_DIRECTX`],
    ///   - [`NV_ENC_INPUT_RESOURCE_TYPE::NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR`],
    ///   - [`NV_ENC_INPUT_RESOURCE_TYPE::NV_ENC_INPUT_RESOURCE_TYPE_OPENGL_TEX`]
    /// * `width` - Input frame width.
    /// * `height` - Input frame height.
    /// * `resource_to_register` - Handle to the resource that is being
    ///   registered. In the case of
    ///   [`NV_ENC_INPUT_RESOURCE_TYPE::NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR`],
    ///   this should be a `CUdeviceptr` which you can get from
    ///   `cuExternalMemoryGetMappedBuffer`.
    /// * `buffer_format` - Buffer format of resource to be registered.
    #[must_use]
    pub fn new(
        resource_type: NV_ENC_INPUT_RESOURCE_TYPE,
        width: u32,
        height: u32,
        resource_to_register: *mut c_void,
        buffer_format: NV_ENC_BUFFER_FORMAT,
    ) -> Self {
        NV_ENC_REGISTER_RESOURCE {
            version: NV_ENC_REGISTER_RESOURCE_VER,
            resourceType: resource_type,
            width,
            height,
            pitch: width,
            resourceToRegister: resource_to_register,
            registeredResource: std::ptr::null_mut(),
            bufferFormat: buffer_format,
            ..Default::default()
        }
    }

    /// Set the input buffer pitch.
    ///
    /// - For [`NV_ENC_INPUT_RESOURCE_TYPE::NV_ENC_INPUT_RESOURCE_TYPE_DIRECTX`]
    /// resources, set this to 0.
    /// - For [`NV_ENC_INPUT_RESOURCE_TYPE::NV_ENC_INPUT_RESOURCE_TYPE_CUDADEVICEPTR`]
    /// resources, set this to the pitch as obtained from `cuMemAllocPitch()`,
    /// or to the width in **bytes** (if this resource was created by using
    /// `cuMemAlloc()`). This value must be a multiple of 4.
    /// - For [`NV_ENC_INPUT_RESOURCE_TYPE::NV_ENC_INPUT_RESOURCE_TYPE_OPENGL_TEX`]
    /// resources, set this to the texture width multiplied by the number of
    /// components in the texture format.
    #[must_use]
    pub fn pitch(mut self, pitch: u32) -> Self {
        self.pitch = pitch;
        self
    }

    // TODO: Add other options
}