Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 70 additions & 7 deletions docs/source/about/advanced_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -739,13 +739,14 @@ encoder
.. table::
:widths: auto

======== ===========
Value Description
======== ===========
nvenc For Nvidia graphics cards
amdvce For AMD graphics cards
software Encoding occurs on the CPU
======== ===========
========= ===========
Value Description
========= ===========
nvenc For NVIDIA graphics cards
quicksync For Intel graphics cards
amdvce For AMD graphics cards
software Encoding occurs on the CPU
========= ===========

**Default**
Sunshine will use the first encoder that is available.
Expand Down Expand Up @@ -958,6 +959,68 @@ nv_coder

nv_coder = auto

qsv_preset
^^^^^^^^^^

**Description**
The encoder preset to use.

.. Note:: This option only applies when using quicksync `encoder`_.

**Choices**

.. table::
:widths: auto

========== ===========
Value Description
========== ===========
veryfast fastest (lowest quality)
faster faster (lower quality)
fast fast (low quality)
medium medium (default)
slow slow (good quality)
slower slower (better quality)
veryslow slowest (best quality)
========== ===========

**Default**
``medium``

**Example**
.. code-block:: text

qsv_preset = medium

qsv_coder
^^^^^^^^^

**Description**
The entropy encoding to use.

.. Note:: This option only applies when using H264 with quicksync `encoder`_.

**Choices**

.. table::
:widths: auto

========== ===========
Value Description
========== ===========
auto let ffmpeg decide
cabac context adaptive binary arithmetic coding - higher quality
cavlc context adaptive variable-length coding - faster decode
========== ===========

**Default**
``auto``

**Example**
.. code-block:: text

qsv_coder = auto

amd_quality
^^^^^^^^^^^

Expand Down
52 changes: 51 additions & 1 deletion src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,46 @@ int coder_from_view(const std::string_view &coder) {
}
} // namespace amd

namespace qsv {
enum preset_e : int {
veryslow = 1,
slower = 2,
slow = 3,
medium = 4,
fast = 5,
faster = 6,
veryfast = 7
};

enum cavlc_e : int {
_auto = false,
enabled = true,
disabled = false
};

std::optional<int> preset_from_view(const std::string_view &preset) {
#define _CONVERT_(x) \
if(preset == #x##sv) return x
_CONVERT_(veryslow);
_CONVERT_(slower);
_CONVERT_(slow);
_CONVERT_(medium);
_CONVERT_(fast);
_CONVERT_(faster);
_CONVERT_(veryfast);
#undef _CONVERT_
return std::nullopt;
}

std::optional<int> coder_from_view(const std::string_view &coder) {
if(coder == "auto"sv) return _auto;
if(coder == "cabac"sv || coder == "ac"sv) return disabled;
if(coder == "cavlc"sv || coder == "vlc"sv) return enabled;
return std::nullopt;
}

} // namespace qsv

namespace vt {

enum coder_e : int {
Expand Down Expand Up @@ -254,18 +294,25 @@ video_t video {
nv::_auto // coder
}, // nv

{
qsv::medium, // preset
qsv::_auto, // cavlc
}, // qsv

{
(int)amd::quality_h264_e::balanced, // quality (h264)
(int)amd::quality_hevc_e::balanced, // quality (hevc)
(int)amd::rc_h264_e::vbr_latency, // rate control (h264)
(int)amd::rc_hevc_e::vbr_latency, // rate control (hevc)
(int)amd::coder_e::_auto, // coder
}, // amd

{
0,
0,
1,
-1 }, // vt
-1,
}, // vt

{}, // encoder
{}, // adapter_name
Expand Down Expand Up @@ -761,6 +808,9 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
int_f(vars, "nv_rc", video.nv.rc, nv::rc_from_view);
int_f(vars, "nv_coder", video.nv.coder, nv::coder_from_view);

int_f(vars, "qsv_preset", video.qsv.preset, qsv::preset_from_view);
int_f(vars, "qsv_coder", video.qsv.cavlc, qsv::coder_from_view);

std::string quality;
string_f(vars, "amd_quality", quality);
if(!quality.empty()) {
Expand Down
5 changes: 5 additions & 0 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ struct video_t {
int coder;
} nv;

struct {
std::optional<int> preset;
std::optional<int> cavlc;
} qsv;

struct {
std::optional<int> quality_h264;
std::optional<int> quality_hevc;
Expand Down
7 changes: 7 additions & 0 deletions src/platform/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,13 @@ struct hwdevice_t {
*/
virtual void init_hwframes(AVHWFramesContext *frames) {};

/**
* Implementations may make modifications required before context derivation
*/
virtual int prepare_to_derive_context(int hw_device_type) {
return 0;
};

virtual ~hwdevice_t() = default;
};

Expand Down
17 changes: 17 additions & 0 deletions src/platform/windows/display_vram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,23 @@ class hwdevice_t : public platf::hwdevice_t {
frames->initial_pool_size = 1;
}

int prepare_to_derive_context(int hw_device_type) override {
// QuickSync requires our device to be multithread-protected
if(hw_device_type == AV_HWDEVICE_TYPE_QSV) {
multithread_t mt;

auto status = device->QueryInterface(IID_ID3D11Multithread, (void **)&mt);
if(FAILED(status)) {
BOOST_LOG(warning) << "Failed to query ID3D11Multithread interface from device [0x"sv << util::hex(status).to_string_view() << ']';
return -1;
}

mt->SetMultithreadProtected(TRUE);
}

return 0;
}

int set_frame(AVFrame *frame, AVBufferRef *hw_frames_ctx) override {
this->hwframe.reset(frame);
this->frame = frame;
Expand Down
Loading