mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-06 15:34:29 +00:00
feat: add spice_server_set_rendernode which sets the gpu to encode for va
This commit is contained in:
parent
e330e7cafc
commit
d298bb2f14
@ -1004,6 +1004,11 @@ GArray *dcc_get_preferred_video_codecs_for_encoding(DisplayChannelClient *dcc)
|
||||
return display_channel_get_video_codecs(DCC_TO_DC(dcc));
|
||||
}
|
||||
|
||||
const char * dcc_get_renderNode(DisplayChannelClient *dcc)
|
||||
{
|
||||
return DCC_TO_DC(dcc)->priv->rendernode;
|
||||
}
|
||||
|
||||
bool dcc_handle_gl_draw_done(DisplayChannelClient *dcc)
|
||||
{
|
||||
DisplayChannel *display = DCC_TO_DC(dcc);
|
||||
|
||||
@ -163,6 +163,7 @@ uint64_t dcc_get_max_stream_bit_rate(DisplayChannelClient *dcc);
|
||||
void dcc_set_max_stream_bit_rate(DisplayChannelClient *dcc, uint64_t rate);
|
||||
gboolean dcc_is_low_bandwidth(DisplayChannelClient *dcc);
|
||||
GArray *dcc_get_preferred_video_codecs_for_encoding(DisplayChannelClient *dcc);
|
||||
const char * dcc_get_renderNode(DisplayChannelClient *dcc);
|
||||
void dcc_video_codecs_update(DisplayChannelClient *dcc);
|
||||
|
||||
#include "pop-visibility.h"
|
||||
|
||||
@ -106,6 +106,7 @@ struct DisplayChannelPrivate
|
||||
_Drawable *free_drawables;
|
||||
|
||||
int stream_video;
|
||||
const char *rendernode;
|
||||
GArray *video_codecs;
|
||||
uint32_t stream_count;
|
||||
std::array<VideoStream, NUM_STREAMS> streams_buf;
|
||||
|
||||
@ -2163,13 +2163,14 @@ display_channel_new(RedsState *reds, QXLInstance *qxl,
|
||||
SpiceCoreInterfaceInternal *core, Dispatcher *dispatcher,
|
||||
int migrate, int stream_video,
|
||||
GArray *video_codecs,
|
||||
const char* rendernode,
|
||||
uint32_t n_surfaces)
|
||||
{
|
||||
/* FIXME: migrate is not used...? */
|
||||
spice_debug("create display channel");
|
||||
auto display =
|
||||
red::make_shared<DisplayChannel>(reds, qxl, core, dispatcher, migrate, stream_video,
|
||||
video_codecs, n_surfaces);
|
||||
video_codecs, rendernode, n_surfaces);
|
||||
if (display) {
|
||||
display_channel_set_stream_video(display.get(), stream_video);
|
||||
display->priv->gl_draw_stream = nullptr;
|
||||
@ -2183,6 +2184,7 @@ DisplayChannel::DisplayChannel(RedsState *reds,
|
||||
Dispatcher *dispatcher,
|
||||
int migrate, int stream_video,
|
||||
GArray *video_codecs,
|
||||
const char *rendernode,
|
||||
uint32_t n_surfaces):
|
||||
CommonGraphicsChannel(reds, SPICE_CHANNEL_DISPLAY, qxl->id,
|
||||
RedChannel::MigrateAll|RedChannel::HandleAcks, core, dispatcher)
|
||||
@ -2238,6 +2240,7 @@ DisplayChannel::DisplayChannel(RedsState *reds,
|
||||
set_cap(SPICE_DISPLAY_CAP_CODEC_VP9_444);
|
||||
set_cap(SPICE_DISPLAY_CAP_CODEC_H265_444);
|
||||
// set_cap(SPICE_DISPLAY_CAP_CODEC_VP9_U);
|
||||
priv->rendernode = rendernode;
|
||||
|
||||
reds_register_channel(reds, this);
|
||||
}
|
||||
|
||||
@ -47,6 +47,7 @@ struct DisplayChannel final: public CommonGraphicsChannel
|
||||
Dispatcher *dispatcher,
|
||||
int migrate, int stream_video,
|
||||
GArray *video_codecs,
|
||||
const char *rendernode,
|
||||
uint32_t n_surfaces);
|
||||
~DisplayChannel();
|
||||
void on_connect(RedClient *client, RedStream *stream, int migration,
|
||||
@ -93,6 +94,7 @@ display_channel_new(RedsState *reds, QXLInstance *qxl,
|
||||
SpiceCoreInterfaceInternal *core, Dispatcher *dispatcher,
|
||||
int migrate, int stream_video,
|
||||
GArray *video_codecs,
|
||||
const char* rendernode,
|
||||
uint32_t n_surfaces);
|
||||
void display_channel_surface_id_unref(DisplayChannel *display, uint32_t surface_id);
|
||||
RedSurface *display_channel_create_surface(DisplayChannel *display, uint32_t surface_id,
|
||||
|
||||
@ -304,6 +304,7 @@ typedef struct SpiceGstEncoder {
|
||||
/* How many frames were dropped by the server since the last encoded frame. */
|
||||
uint32_t server_drops;
|
||||
GstAllocator *allocator;
|
||||
const char * rendernode;
|
||||
} SpiceGstEncoder;
|
||||
|
||||
|
||||
@ -975,43 +976,38 @@ static bool gst_features_lookup(const gchar *feature_name)
|
||||
return true;
|
||||
}
|
||||
|
||||
static const gchar *get_encode_gpu(){
|
||||
|
||||
const gchar* env_encode_gpu_str = g_getenv("SPICE_ENCODE_GPU");
|
||||
if ((!env_encode_gpu_str) || (strcmp(env_encode_gpu_str, "renderD128") == 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_autoptr(GRegex) regex = g_regex_new("renderD1[[:digit:]]{2}", 0, 0, NULL);
|
||||
if (g_regex_match(regex, env_encode_gpu_str, 0, NULL)) {
|
||||
return env_encode_gpu_str;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar *find_best_hw_plugin(const gchar *codec_name)
|
||||
static gchar *find_best_hw_plugin(const gchar *codec_name, const char *rendernode)
|
||||
{
|
||||
char plugins[][20] = {"va","msdk", "vaapi"};
|
||||
char plugins[][8] = {"va","msdk", "vaapi"};
|
||||
char postproc[][10] ={"postproc","vpp","postproc"};
|
||||
gchar *feature_name;
|
||||
int i;
|
||||
const gchar *encode_gpu = get_encode_gpu();
|
||||
if (encode_gpu) {
|
||||
g_strlcat(plugins[1], encode_gpu, sizeof(plugins[1]));
|
||||
}
|
||||
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS(plugins); i++) {
|
||||
feature_name = !codec_name ? g_strconcat(plugins[i], "postproc", NULL) :
|
||||
g_strconcat(plugins[i], codec_name, "enc", NULL);
|
||||
if (gst_features_lookup(feature_name)) {
|
||||
return feature_name;
|
||||
}
|
||||
g_free(feature_name);
|
||||
if(codec_name){
|
||||
feature_name = g_strconcat(plugins[i], codec_name, "lpenc", NULL);
|
||||
if (gst_features_lookup(feature_name)) {
|
||||
return feature_name;
|
||||
if (codec_name == NULL){
|
||||
feature_name = g_strdup_printf("%s%s", plugins[i], postproc[i]);
|
||||
if (!gst_features_lookup(feature_name)) {
|
||||
g_free(feature_name);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
feature_name = g_strconcat(plugins[i], codec_name, "enc", NULL);
|
||||
if (!gst_features_lookup(feature_name)) {
|
||||
g_free(feature_name);
|
||||
feature_name = g_strconcat(plugins[i], codec_name, "lpenc", NULL);
|
||||
if (!gst_features_lookup(feature_name)) {
|
||||
g_free(feature_name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(i == 0 && rendernode){
|
||||
gchar * feature_name_with_render = g_strdup_printf("%s device-path=%s",feature_name, rendernode);
|
||||
g_free(feature_name);
|
||||
return feature_name_with_render;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@ -1058,11 +1054,11 @@ static void try_intel_hw_plugins(SpiceGstEncoder* spice_encoder, gchar **convert
|
||||
return;
|
||||
}
|
||||
|
||||
encoder = find_best_hw_plugin(codec_name);
|
||||
encoder = find_best_hw_plugin(codec_name, spice_encoder->rendernode);
|
||||
if (!encoder) {
|
||||
return;
|
||||
}
|
||||
vpp = find_best_hw_plugin(NULL);
|
||||
vpp = find_best_hw_plugin(NULL,spice_encoder->rendernode);
|
||||
if (!vpp) {
|
||||
g_free(encoder);
|
||||
return;
|
||||
@ -2077,7 +2073,8 @@ VideoEncoder *gstreamer_encoder_new(SpiceVideoCodecType codec_type,
|
||||
uint64_t starting_bit_rate,
|
||||
VideoEncoderRateControlCbs *cbs,
|
||||
bitmap_ref_t bitmap_ref,
|
||||
bitmap_unref_t bitmap_unref)
|
||||
bitmap_unref_t bitmap_unref,
|
||||
const char * rendernode)
|
||||
{
|
||||
SPICE_VERIFY(SPICE_GST_FRAME_STATISTICS_COUNT <= SPICE_GST_HISTORY_SIZE);
|
||||
spice_return_val_if_fail(codec_type == SPICE_VIDEO_CODEC_TYPE_MJPEG ||
|
||||
@ -2122,6 +2119,7 @@ VideoEncoder *gstreamer_encoder_new(SpiceVideoCodecType codec_type,
|
||||
encoder->bitmap_ref = bitmap_ref;
|
||||
encoder->bitmap_unref = bitmap_unref;
|
||||
encoder->format = GSTREAMER_FORMAT_INVALID;
|
||||
encoder->rendernode = rendernode;
|
||||
pthread_mutex_init(&encoder->outbuf_mutex, NULL);
|
||||
pthread_cond_init(&encoder->outbuf_cond, NULL);
|
||||
|
||||
|
||||
@ -1364,7 +1364,8 @@ VideoEncoder *mjpeg_encoder_new(SpiceVideoCodecType codec_type,
|
||||
uint64_t starting_bit_rate,
|
||||
VideoEncoderRateControlCbs *cbs,
|
||||
bitmap_ref_t bitmap_ref,
|
||||
bitmap_unref_t bitmap_unref)
|
||||
bitmap_unref_t bitmap_unref,
|
||||
const char *rendernode)
|
||||
{
|
||||
MJpegEncoder *encoder;
|
||||
|
||||
|
||||
@ -990,7 +990,9 @@ RedWorker* red_worker_new(QXLInstance *qxl)
|
||||
FALSE,
|
||||
reds_get_streaming_video(reds),
|
||||
reds_get_video_codecs(reds),
|
||||
init_info.n_surfaces).get(); // XXX
|
||||
reds_get_rendernode(reds),
|
||||
init_info.n_surfaces
|
||||
).get(); // XXX
|
||||
channel = worker->display_channel;
|
||||
channel->init_stat_node(&worker->stat, "display_channel");
|
||||
display_channel_set_image_compression(worker->display_channel,
|
||||
|
||||
@ -121,6 +121,7 @@ struct RedServerConfig {
|
||||
char *sasl_appname;
|
||||
#endif
|
||||
char *spice_name;
|
||||
char *rendernode;
|
||||
|
||||
bool spice_uuid_is_set;
|
||||
uint8_t spice_uuid[16];
|
||||
@ -4093,6 +4094,16 @@ SPICE_GNUC_VISIBLE int spice_server_set_video_codecs(SpiceServer *reds, const ch
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPICE_GNUC_VISIBLE int spice_server_set_rendernode(SpiceServer *s, const char *rendernode) {
|
||||
g_free(s->config->rendernode);
|
||||
s->config->rendernode = g_strdup(rendernode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* reds_get_rendernode(const RedsState *reds){
|
||||
return reds->config->rendernode;
|
||||
}
|
||||
|
||||
SPICE_GNUC_VISIBLE const char *spice_server_get_video_codecs(SpiceServer *reds)
|
||||
{
|
||||
return video_codecs_to_string(reds_get_video_codecs(reds), ";");
|
||||
|
||||
@ -97,6 +97,7 @@ void reds_on_main_channel_migrate(RedsState *reds, MainChannelClient *mcc);
|
||||
|
||||
uint32_t reds_get_streaming_video(const RedsState *reds);
|
||||
GArray* reds_get_video_codecs(const RedsState *reds);
|
||||
const char* reds_get_rendernode(const RedsState *reds);
|
||||
spice_wan_compression_t reds_get_jpeg_state(const RedsState *reds);
|
||||
spice_wan_compression_t reds_get_zlib_glz_state(const RedsState *reds);
|
||||
SpiceCoreInterfaceInternal* reds_get_core_interface(RedsState *reds);
|
||||
|
||||
@ -139,6 +139,8 @@ enum {
|
||||
|
||||
int spice_server_set_video_codecs(SpiceServer *s, const char* video_codecs);
|
||||
|
||||
int spice_server_set_rendernode(SpiceServer *s, const char *rendernode);
|
||||
|
||||
/**
|
||||
* Returns a newly allocated string describing video encoders/codecs
|
||||
* currently allowed in @s Spice server. The string returned by
|
||||
|
||||
@ -187,4 +187,5 @@ global:
|
||||
SPICE_SERVER_0.16 {
|
||||
global:
|
||||
spice_qxl_gl_scanout2;
|
||||
spice_server_set_rendernode;
|
||||
} SPICE_SERVER_0.14.3;
|
||||
|
||||
@ -806,7 +806,7 @@ static QXLInterface display_sif = {
|
||||
.major_version = SPICE_INTERFACE_QXL_MAJOR,
|
||||
.minor_version = SPICE_INTERFACE_QXL_MINOR
|
||||
},
|
||||
{ .attached_worker = attached_worker },
|
||||
.attached_worker = attached_worker ,
|
||||
.set_compression_level = set_compression_level,
|
||||
.set_mm_time = nullptr,
|
||||
.get_init_info = get_init_info,
|
||||
|
||||
@ -692,7 +692,7 @@ create_video_encoder(const EncoderInfo *encoder)
|
||||
spice_assert(encoder);
|
||||
|
||||
video_encoder = encoder->new_encoder(encoder->coded_type, starting_bit_rate, &rate_control_cbs,
|
||||
(bitmap_ref_t) frame_ref, (bitmap_unref_t) frame_unref);
|
||||
(bitmap_ref_t) frame_ref, (bitmap_unref_t) frame_unref, NULL);
|
||||
if (video_encoder == NULL) {
|
||||
exit(123);
|
||||
}
|
||||
|
||||
@ -208,19 +208,22 @@ typedef VideoEncoder* (*new_video_encoder_t)(SpiceVideoCodecType codec_type,
|
||||
uint64_t starting_bit_rate,
|
||||
VideoEncoderRateControlCbs *cbs,
|
||||
bitmap_ref_t bitmap_ref,
|
||||
bitmap_unref_t bitmap_unref);
|
||||
bitmap_unref_t bitmap_unref,
|
||||
const char * rendernode);
|
||||
|
||||
VideoEncoder* mjpeg_encoder_new(SpiceVideoCodecType codec_type,
|
||||
uint64_t starting_bit_rate,
|
||||
VideoEncoderRateControlCbs *cbs,
|
||||
bitmap_ref_t bitmap_ref,
|
||||
bitmap_unref_t bitmap_unref);
|
||||
bitmap_unref_t bitmap_unref,
|
||||
const char * rendernode);
|
||||
#if defined(HAVE_GSTREAMER_1_0)
|
||||
VideoEncoder* gstreamer_encoder_new(SpiceVideoCodecType codec_type,
|
||||
uint64_t starting_bit_rate,
|
||||
VideoEncoderRateControlCbs *cbs,
|
||||
bitmap_ref_t bitmap_ref,
|
||||
bitmap_unref_t bitmap_unref);
|
||||
bitmap_unref_t bitmap_unref,
|
||||
const char * rendernode);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -820,7 +820,7 @@ static VideoEncoder* dcc_create_video_encoder(DisplayChannelClient *dcc,
|
||||
continue;
|
||||
}
|
||||
|
||||
VideoEncoder* video_encoder = video_codec->create(video_codec->type, starting_bit_rate, cbs, bitmap_ref, bitmap_unref);
|
||||
VideoEncoder* video_encoder = video_codec->create(video_codec->type, starting_bit_rate, cbs, bitmap_ref, bitmap_unref, dcc_get_renderNode(dcc));
|
||||
if (video_encoder) {
|
||||
return video_encoder;
|
||||
}
|
||||
@ -828,7 +828,7 @@ static VideoEncoder* dcc_create_video_encoder(DisplayChannelClient *dcc,
|
||||
|
||||
/* Try to use the builtin MJPEG video encoder as a fallback */
|
||||
if (!client_has_multi_codec || dcc->test_remote_cap(SPICE_DISPLAY_CAP_CODEC_MJPEG)) {
|
||||
return mjpeg_encoder_new(SPICE_VIDEO_CODEC_TYPE_MJPEG, starting_bit_rate, cbs, bitmap_ref, bitmap_unref);
|
||||
return mjpeg_encoder_new(SPICE_VIDEO_CODEC_TYPE_MJPEG, starting_bit_rate, cbs, bitmap_ref, bitmap_unref, dcc_get_renderNode(dcc));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user