feat(win/video): support native YUV 4:4:4 encoding (#2533)

This commit is contained in:
ns6089
2024-08-16 20:41:27 +03:00
committed by GitHub
parent e8c837f412
commit bfdfcebc80
35 changed files with 1454 additions and 330 deletions
+74 -9
View File
@@ -1,6 +1,6 @@
/**
* @file src/nvenc/nvenc_base.h
* @brief Declarations for base NVENC encoder.
* @brief Declarations for abstract platform-agnostic base of standalone NVENC encoder.
*/
#pragma once
@@ -13,36 +13,98 @@
#include <ffnvcodec/nvEncodeAPI.h>
/**
* @brief Standalone NVENC encoder
*/
namespace nvenc {
/**
* @brief Abstract platform-agnostic base of standalone NVENC encoder.
* Derived classes perform platform-specific operations.
*/
class nvenc_base {
public:
nvenc_base(NV_ENC_DEVICE_TYPE device_type, void *device);
/**
* @param device_type Underlying device type used by derived class.
*/
explicit nvenc_base(NV_ENC_DEVICE_TYPE device_type);
virtual ~nvenc_base();
nvenc_base(const nvenc_base &) = delete;
nvenc_base &
operator=(const nvenc_base &) = delete;
/**
* @brief Create the encoder.
* @param config NVENC encoder configuration.
* @param client_config Stream configuration requested by the client.
* @param colorspace YUV colorspace.
* @param buffer_format Platform-agnostic input surface format.
* @return `true` on success, `false` on error
*/
bool
create_encoder(const nvenc_config &config, const video::config_t &client_config, const nvenc_colorspace_t &colorspace, NV_ENC_BUFFER_FORMAT buffer_format);
/**
* @brief Destroy the encoder.
* Derived classes classes call it in the destructor.
*/
void
destroy_encoder();
/**
* @brief Encode the next frame using platform-specific input surface.
* @param frame_index Frame index that uniquely identifies the frame.
* Afterwards serves as parameter for `invalidate_ref_frames()`.
* No restrictions on the first frame index, but later frame indexes must be subsequent.
* @param force_idr Whether to encode frame as forced IDR.
* @return Encoded frame.
*/
nvenc_encoded_frame
encode_frame(uint64_t frame_index, bool force_idr);
/**
* @brief Perform reference frame invalidation (RFI) procedure.
* @param first_frame First frame index of the invalidation range.
* @param last_frame Last frame index of the invalidation range.
* @return `true` on success, `false` on error.
* After error next frame must be encoded with `force_idr = true`.
*/
bool
invalidate_ref_frames(uint64_t first_frame, uint64_t last_frame);
protected:
/**
* @brief Required. Used for loading NvEnc library and setting `nvenc` variable with `NvEncodeAPICreateInstance()`.
* Called during `create_encoder()` if `nvenc` variable is not initialized.
* @return `true` on success, `false` on error
*/
virtual bool
init_library() = 0;
/**
* @brief Required. Used for creating outside-facing input surface,
* registering this surface with `nvenc->nvEncRegisterResource()` and setting `registered_input_buffer` variable.
* Called during `create_encoder()`.
* @return `true` on success, `false` on error
*/
virtual bool
create_and_register_input_buffer() = 0;
/**
* @brief Optional. Override if you must perform additional operations on the registered input surface in the beginning of `encode_frame()`.
* Typically used for interop copy.
* @return `true` on success, `false` on error
*/
virtual bool
synchronize_input_buffer() { return true; }
/**
* @brief Optional. Override if you want to create encoder in async mode.
* In this case must also set `async_event_handle` variable.
* @param timeout_ms Wait timeout in milliseconds
* @return `true` on success, `false` on timeout or error
*/
virtual bool
wait_for_async_event(uint32_t timeout_ms) { return false; }
@@ -61,9 +123,6 @@ namespace nvenc {
min_struct_version(uint32_t version, uint32_t v11_struct_version = 0, uint32_t v12_struct_version = 0);
const NV_ENC_DEVICE_TYPE device_type;
void *const device;
std::unique_ptr<NV_ENCODE_API_FUNCTION_LIST> nvenc;
void *encoder = nullptr;
@@ -75,11 +134,17 @@ namespace nvenc {
bool rfi = false;
} encoder_params;
// Derived classes set these variables
NV_ENC_REGISTERED_PTR registered_input_buffer = nullptr;
void *async_event_handle = nullptr;
std::string last_nvenc_error_string;
std::string last_error_string;
// Derived classes set these variables
void *device = nullptr; ///< Platform-specific handle of encoding device.
///< Should be set in constructor or `init_library()`.
std::shared_ptr<NV_ENCODE_API_FUNCTION_LIST> nvenc; ///< Function pointers list produced by `NvEncodeAPICreateInstance()`.
///< Should be set in `init_library()`.
NV_ENC_REGISTERED_PTR registered_input_buffer = nullptr; ///< Platform-specific input surface registered with `NvEncRegisterResource()`.
///< Should be set in `create_and_register_input_buffer()`.
void *async_event_handle = nullptr; ///< (optional) Platform-specific handle of event object event.
///< Can be set in constructor or `init_library()`, must override `wait_for_async_event()`.
private:
NV_ENC_OUTPUT_PTR output_bitstream = nullptr;