Sunshine latest
Self-hosted game stream host for Moonlight.
video.cpp File Reference

Definitions for video. More...

#include <atomic>
#include <bitset>
#include <list>
#include <thread>
#include <boost/pointer_cast.hpp>
#include <libavutil/imgutils.h>
#include <libavutil/mastering_display_metadata.h>
#include <libavutil/opt.h>
#include <libavutil/pixdesc.h>
#include "cbs.h"
#include "config.h"
#include "display_device.h"
#include "globals.h"
#include "input.h"
#include "logging.h"
#include "nvenc/nvenc_base.h"
#include "platform/common.h"
#include "sync.h"
#include "video.h"
#include <libavutil/hwcontext_d3d11va.h>
Include dependency graph for video.cpp:

Classes

class  video::avcodec_encode_session_t
 
class  video::avcodec_software_encode_device_t
 
struct  video::capture_ctx_t
 
struct  video::capture_thread_async_ctx_t
 
struct  video::capture_thread_sync_ctx_t
 
class  video::nvenc_encode_session_t
 
struct  video::sync_session_ctx_t
 
struct  video::sync_session_t
 

Typedefs

using video::encode_e = platf::capture_e
 
using video::encode_session_ctx_queue_t = safe::queue_t<sync_session_ctx_t>
 
typedef int(* video::vaapi_init_avcodec_hardware_input_buffer_fn) (platf::avcodec_encode_device_t *encode_device, AVBufferRef **hw_device_buf)
 

Enumerations

enum  video::flag_e : uint32_t {
  video::DEFAULT = 0 , video::PARALLEL_ENCODING = 1 << 1 , video::H264_ONLY = 1 << 2 , video::LIMITED_GOP_SIZE = 1 << 3 ,
  video::SINGLE_SLICE_ONLY = 1 << 4 , video::CBR_WITH_VBR = 1 << 5 , video::RELAXED_COMPLIANCE = 1 << 6 , video::NO_RC_BUF_LIMIT = 1 << 7 ,
  video::REF_FRAMES_INVALIDATION = 1 << 8 , video::ALWAYS_REPROBE = 1 << 9 , video::YUV444_SUPPORT = 1 << 10
}
 
enum class  video::qsv::profile_av1_e : int { main = 1 , high = 2 }
 
enum class  video::nv::profile_h264_e : int { high = 2 , high_444p = 3 }
 
enum class  video::qsv::profile_h264_e : int { high = 100 , high_444p = 244 }
 
enum class  video::nv::profile_hevc_e : int { main = 0 , main_10 = 1 , rext = 2 }
 
enum class  video::qsv::profile_hevc_e : int { main = 1 , main_10 = 2 , rext = 4 }
 
enum  video::validate_flag_e { video::VUI_PARAMS = 0x01 }
 

Functions

void video::capture (safe::mail_t mail, config_t config, void *channel_data)
 
void video::capture_async (safe::mail_t mail, config_t &config, void *channel_data)
 
void video::captureThread (std::shared_ptr< safe::queue_t< capture_ctx_t > > capture_ctx_queue, sync_util::sync_t< std::weak_ptr< platf::display_t > > &display_wp, safe::signal_t &reinit_event, const encoder_t &encoder)
 
void video::captureThreadSync ()
 
util::Either< avcodec_buffer_t, int > video::cuda_init_avcodec_hardware_input_buffer (platf::avcodec_encode_device_t *)
 
void do_nothing (void *)
 
util::Either< avcodec_buffer_t, int > video::dxgi_init_avcodec_hardware_input_buffer (platf::avcodec_encode_device_t *)
 
int video::encode (int64_t frame_nr, encode_session_t &session, safe::mail_raw_t::queue_t< packet_t > &packets, void *channel_data, std::optional< std::chrono::steady_clock::time_point > frame_timestamp)
 
int video::encode_avcodec (int64_t frame_nr, avcodec_encode_session_t &session, safe::mail_raw_t::queue_t< packet_t > &packets, void *channel_data, std::optional< std::chrono::steady_clock::time_point > frame_timestamp)
 
int video::encode_nvenc (int64_t frame_nr, nvenc_encode_session_t &session, safe::mail_raw_t::queue_t< packet_t > &packets, void *channel_data, std::optional< std::chrono::steady_clock::time_point > frame_timestamp)
 
void video::encode_run (int &frame_nr, safe::mail_t mail, img_event_t images, config_t config, std::shared_ptr< platf::display_t > disp, std::unique_ptr< platf::encode_device_t > encode_device, safe::signal_t &reinit_event, const encoder_t &encoder, void *channel_data)
 
encode_e video::encode_run_sync (std::vector< std::unique_ptr< sync_session_ctx_t > > &synced_session_ctxs, encode_session_ctx_queue_t &encode_session_ctx_queue, std::vector< std::string > &display_names, int &display_p)
 
void video::end_capture_async (capture_thread_async_ctx_t &ctx)
 
void video::end_capture_sync (capture_thread_sync_ctx_t &ctx)
 
void video::free_buffer (AVBufferRef *ref)
 
void video::free_ctx (AVCodecContext *ctx)
 
void video::free_frame (AVFrame *frame)
 
std::unique_ptr< avcodec_encode_session_tvideo::make_avcodec_encode_session (platf::display_t *disp, const encoder_t &encoder, const config_t &config, int width, int height, std::unique_ptr< platf::avcodec_encode_device_t > encode_device)
 
std::unique_ptr< platf::encode_device_tvideo::make_encode_device (platf::display_t &disp, const encoder_t &encoder, const config_t &config)
 
std::unique_ptr< encode_session_tvideo::make_encode_session (platf::display_t *disp, const encoder_t &encoder, const config_t &config, int width, int height, std::unique_ptr< platf::encode_device_t > encode_device)
 
std::unique_ptr< nvenc_encode_session_tvideo::make_nvenc_encode_session (const config_t &client_config, std::unique_ptr< platf::nvenc_encode_device_t > encode_device)
 
input::touch_port_t video::make_port (platf::display_t *display, const config_t &config)
 
std::optional< sync_session_tvideo::make_synced_session (platf::display_t *disp, const encoder_t &encoder, platf::img_t &img, sync_session_ctx_t &ctx)
 
platf::mem_type_e video::map_base_dev_type (AVHWDeviceType type)
 
platf::pix_fmt_e video::map_pix_fmt (AVPixelFormat fmt)
 
int video::probe_encoders ()
 Probe encoders and select the preferred encoder. This is called once at startup and each time a stream is launched to ensure the best encoder is selected. Encoder availability can change at runtime due to all sorts of things from driver updates to eGPUs.
 
void video::refresh_displays (platf::mem_type_e dev_type, std::vector< std::string > &display_names, int &current_display_index)
 Update the list of display names before or during a stream.
 
void video::reset_display (std::shared_ptr< platf::display_t > &disp, const platf::mem_type_e &type, const std::string &display_name, const config_t &config)
 
int video::start_capture_async (capture_thread_async_ctx_t &ctx)
 
int video::start_capture_sync (capture_thread_sync_ctx_t &ctx)
 
util::Either< avcodec_buffer_t, int > video::vaapi_init_avcodec_hardware_input_buffer (platf::avcodec_encode_device_t *)
 
int video::validate_config (std::shared_ptr< platf::display_t > disp, const encoder_t &encoder, const config_t &config)
 
bool video::validate_encoder (encoder_t &encoder, bool expect_failure)
 
util::Either< avcodec_buffer_t, int > video::vt_init_avcodec_hardware_input_buffer (platf::avcodec_encode_device_t *)
 

Variables

int video::active_av1_mode
 
int video::active_hevc_mode
 
encoder_t video::amdvce
 
auto video::capture_thread_async = safe::make_shared<capture_thread_async_ctx_t>(start_capture_async, end_capture_async)
 
auto video::capture_thread_sync = safe::make_shared<capture_thread_sync_ctx_t>(start_capture_sync, end_capture_sync)
 
bool video::last_encoder_probe_supported_ref_frames_invalidation = false
 
std::array< bool, 3 > video::last_encoder_probe_supported_yuv444_for_codec = {}
 
encoder_t video::nvenc
 
encoder_t video::quicksync
 
encoder_t video::software
 
encoder_t video::vaapi
 
encoder_t video::videotoolbox
 

Detailed Description

Definitions for video.

Enumeration Type Documentation

◆ flag_e

enum video::flag_e : uint32_t
Enumerator
DEFAULT 

Default flags.

PARALLEL_ENCODING 

Capture and encoding can run concurrently on separate threads.

H264_ONLY 

When HEVC is too heavy.

LIMITED_GOP_SIZE 

Some encoders don't like it when you have an infinite GOP_SIZE. e.g. VAAPI.

SINGLE_SLICE_ONLY 

Never use multiple slices. Older intel iGPU's ruin it for everyone else.

CBR_WITH_VBR 

Use a VBR rate control mode to simulate CBR.

RELAXED_COMPLIANCE 

Use FF_COMPLIANCE_UNOFFICIAL compliance mode.

NO_RC_BUF_LIMIT 

Don't set rc_buffer_size.

REF_FRAMES_INVALIDATION 

Support reference frames invalidation.

ALWAYS_REPROBE 

This is an encoder of last resort and we want to aggressively probe for a better one.

YUV444_SUPPORT 

Encoder may support 4:4:4 chroma sampling depending on hardware.

◆ profile_av1_e

enum class video::qsv::profile_av1_e : int
strong
Enumerator
main 

Main profile.

high 

High profile.

◆ profile_h264_e [1/2]

enum class video::nv::profile_h264_e : int
strong
Enumerator
high 

High profile.

high_444p 

High 4:4:4 Predictive profile.

◆ profile_h264_e [2/2]

enum class video::qsv::profile_h264_e : int
strong
Enumerator
high 

High profile.

high_444p 

High 4:4:4 Predictive profile.

◆ profile_hevc_e [1/2]

enum class video::nv::profile_hevc_e : int
strong
Enumerator
main 

Main profile.

main_10 

Main 10 profile.

rext 

Rext profile.

◆ profile_hevc_e [2/2]

enum class video::qsv::profile_hevc_e : int
strong
Enumerator
main 

Main profile.

main_10 

Main 10 profile.

rext 

RExt profile.

◆ validate_flag_e

Enumerator
VUI_PARAMS 

VUI parameters.

Function Documentation

◆ probe_encoders()

int video::probe_encoders ( )

Probe encoders and select the preferred encoder. This is called once at startup and each time a stream is launched to ensure the best encoder is selected. Encoder availability can change at runtime due to all sorts of things from driver updates to eGPUs.

Warning
This is only safe to call when there is no client actively streaming.

◆ refresh_displays()

void video::refresh_displays ( platf::mem_type_e dev_type,
std::vector< std::string > & display_names,
int & current_display_index )

Update the list of display names before or during a stream.

This will attempt to keep current_display_index pointing at the same display.

Parameters
dev_typeThe encoder device type used for display lookup.
display_namesThe list of display names to repopulate.
current_display_indexThe current display index or -1 if not yet known.