improved video codec informations

- added stream-created signal
- added spice_display_channel_get_supported_codecs
- increased spice version to 44
This commit is contained in:
Michael Scherle 2024-07-19 11:09:05 +02:00
parent c08de1c124
commit ed8ae0fded
9 changed files with 117 additions and 9 deletions

View File

@ -186,6 +186,8 @@ spice_display_channel_change_preferred_compression
spice_display_change_preferred_video_codec_type
spice_display_channel_change_preferred_video_codec_type
spice_display_channel_change_preferred_video_codec_types
spice_display_channel_get_supported_codecs
spice_display_get_codec_name
spice_gl_scanout_free
<SUBSECTION Standard>
SPICE_DISPLAY_CHANNEL

View File

@ -512,11 +512,12 @@ static bool try_intel_hw_pipeline(SpiceGstDecoder *decoder)
spice_warning("error finding suitable plugin for postproc");
goto err;
}
/*
g_object_set(hw_decoder,
"async-depth",G_GINT64_CONSTANT(1),
"hardware", TRUE,
"output-order",G_GINT64_CONSTANT(1),
NULL);
NULL);*/
vpp = gst_element_factory_make(vpp_name, NULL);
g_free(vpp_name);
if (!vpp) {
@ -850,7 +851,7 @@ static gboolean spice_gst_decoder_queue_frame(VideoDecoder *video_decoder,
/* SpiceGstFrame ownership is moved to the buffer */
GstBuffer *buffer = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_PHYSICALLY_CONTIGUOUS,
frame->data, frame->size, 0, frame->size,
gstframe, free_gst_frame);
gstframe,(GDestroyNotify) free_gst_frame);
GstClockTime pts = gst_clock_get_time(decoder->clock) - gst_element_get_base_time(decoder->pipeline) + ((uint64_t)MAX(0, margin)) * 1000 * 1000;
GST_BUFFER_DURATION(buffer) = GST_CLOCK_TIME_NONE;

View File

@ -188,13 +188,14 @@ static const struct {
* decoder's name anymore. */
const gchar *dec_name;
const gchar *dec_caps;
int codec;
} gst_opts[] = {
/* SpiceVideoCodecType starts at index 1 */
{ 0 },
/* SPICE_VIDEO_CODEC_TYPE_MJPEG */
{ SPICE_DISPLAY_CAP_CODEC_MJPEG, "mjpeg",
"jpegdec", "image/jpeg" },
"jpegdec", "image/jpeg", SPICE_VIDEO_CODEC_TYPE_MJPEG },
/* SPICE_VIDEO_CODEC_TYPE_VP8
*
@ -202,7 +203,7 @@ static const struct {
* See: https://bugzilla.gnome.org/show_bug.cgi?id=756457
*/
{ SPICE_DISPLAY_CAP_CODEC_VP8, "vp8",
"vp8dec", "video/x-vp8" },
"vp8dec", "video/x-vp8", SPICE_VIDEO_CODEC_TYPE_VP8},
/* SPICE_VIDEO_CODEC_TYPE_H264
* When setting video/x-h264, h264parse will complain if we don't have the
@ -210,15 +211,17 @@ static const struct {
* (hardcoded in spice-server), let's add it here to avoid the warning.
*/
{ SPICE_DISPLAY_CAP_CODEC_H264, "h264",
"h264parse ! avdec_h264", "video/x-h264,stream-format=byte-stream,alignment=au" },
"h264parse ! avdec_h264", "video/x-h264,stream-format=byte-stream,alignment=au",
SPICE_VIDEO_CODEC_TYPE_H264},
/* SPICE_VIDEO_CODEC_TYPE_VP9 */
{ SPICE_DISPLAY_CAP_CODEC_VP9, "vp9",
"vp9dec", "video/x-vp9" },
"vp9dec", "video/x-vp9",SPICE_VIDEO_CODEC_TYPE_VP9 },
/* SPICE_DISPLAY_CAP_CODEC_H265 */
{ SPICE_DISPLAY_CAP_CODEC_H265, "h265",
"h265parse ! avdec_h265", "video/x-h265,stream-format=byte-stream,alignment=au" },
"h265parse ! avdec_h265", "video/x-h265,stream-format=byte-stream,alignment=au",
SPICE_VIDEO_CODEC_TYPE_H265 },
};

View File

@ -90,6 +90,7 @@ enum {
SPICE_DISPLAY_GL_DRAW,
SPICE_DISPLAY_STREAMING_MODE,
SPICE_DISPLAY_OVERLAY,
SPICE_DISPLAY_STREAM_CREATED,
SPICE_DISPLAY_LAST_SIGNAL,
};
@ -503,6 +504,32 @@ static void spice_display_channel_class_init(SpiceDisplayChannelClass *klass)
GST_TYPE_PIPELINE);
channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
/**
* SpiceDisplayChannel:latest-codec:
* @display: the #SpiceDisplayChannel that emitted the signal
* @id: the display_stream id
* @codec: SpiceVideoCodecType
*
* The #SpiceDisplayChannel::stream-created signal is emitted when
* a new display_stream is created
*
*
* Since: 0.44
**/
signals[SPICE_DISPLAY_STREAM_CREATED] =
g_signal_new("stream-created",
G_OBJECT_CLASS_TYPE(gobject_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(SpiceDisplayChannelClass,
stream_created),
NULL, NULL,
g_cclosure_user_marshal_VOID__INT_INT,
G_TYPE_NONE,
2,
G_TYPE_INT, G_TYPE_INT);
channel_set_handlers(SPICE_CHANNEL_CLASS(klass));
}
/**
@ -774,6 +801,50 @@ spice_display_channel_get_gl_scanout(SpiceDisplayChannel *channel)
return channel->priv->scanout.fd != -1 ? &channel->priv->scanout : NULL;
}
/**
* spice_display_channel_get_supported_codecs:
* @channel: a #SpiceDisplayChannel
*
* Returns: Supported Video Codecs by the client and server
*
* Since: 0.44
**/
GArray * spice_display_channel_get_supported_codecs(SpiceDisplayChannel * channel) {
g_return_val_if_fail(SPICE_IS_DISPLAY_CHANNEL(channel), NULL);
GArray *codecs = g_array_new(FALSE,TRUE,sizeof(gint));
#ifdef HAVE_BUILTIN_MJPEG
// g_array_index(codecs, gint, 0 ) = SPICE_VIDEO_CODEC_TYPE_MJPEG;
#endif
for (int i = 1; i < G_N_ELEMENTS(gst_opts); i++) {
if(i >= SPICE_VIDEO_CODEC_TYPE_ENUM_END) {
break;
}
if( spice_channel_test_capability(channel, gst_opts[i].cap)
&& spice_channel_test_local_capability(channel, gst_opts[i].cap)) {
g_array_append_val(codecs,gst_opts[i].codec);
}
}
return codecs;
}
/**
* spice_display_get_codec_name:
* @codec_type: a #SpiceVideoCodecType
*
* Returns: Returns the codec name as string
*
* Since: 0.44
**/
char * spice_display_get_codec_name(gint codec_type) {
for (int i = 0; i < G_N_ELEMENTS(gst_opts) ; i++){
if(gst_opts[i].codec == codec_type) {
return gst_opts[i].name;
}
}
return NULL;
}
/* ------------------------------------------------------------------ */
static void image_put(SpiceImageCache *cache, uint64_t id, pixman_image_t *image)
@ -1359,6 +1430,9 @@ static display_stream *display_stream_create(SpiceChannel *channel,
g_warning("could not create a video decoder for codec %u", codec_type);
g_clear_pointer(&st, display_stream_destroy);
}
g_signal_emit(st->channel, signals[SPICE_DISPLAY_STREAM_CREATED], 0,
id, codec_type);
return st;
}

View File

@ -139,6 +139,7 @@ struct _SpiceDisplayChannelClass {
gint x, gint y, gint w, gint h);
void (*display_mark)(SpiceChannel *channel,
gboolean mark);
void (*stream_created)(SpiceChannel *channel, gint id, gint codec_type );
/*< private >*/
};
@ -166,6 +167,10 @@ SPICE_GTK_AVAILABLE_IN_0_35
const SpiceGlScanout* spice_display_channel_get_gl_scanout(SpiceDisplayChannel *channel);
SPICE_GTK_AVAILABLE_IN_0_35
void spice_display_channel_gl_draw_done(SpiceDisplayChannel *channel);
SPICE_GTK_AVAILABLE_IN_0_44
GArray * spice_display_channel_get_supported_codecs(SpiceDisplayChannel * channel);
SPICE_GTK_AVAILABLE_IN_0_44
char * spice_display_get_codec_name(gint codec_type);
#ifndef SPICE_DISABLE_DEPRECATED
SPICE_GTK_DEPRECATED_IN_0_35_FOR(spice_display_channel_change_preferred_compression)

View File

@ -30,6 +30,8 @@ spice_display_channel_get_gl_scanout;
spice_display_channel_get_primary;
spice_display_channel_get_type;
spice_display_channel_gl_draw_done;
spice_display_channel_get_supported_codecs;
spice_display_get_codec_name;
spice_display_get_gl_scanout;
spice_display_get_primary;
spice_display_gl_draw_done;

View File

@ -21,7 +21,7 @@ endif
script = ''
# versions, [major, minimum_minor, maximum_minor]
versions = [[ 0, 1, 43 ]]
versions = [[ 0, 1, 44 ]]
# build a long string to use for loops
x = 'aaaaaaaaaa'
x = x.replace('a', 'bbbbbbbbbb')
@ -43,7 +43,7 @@ foreach version : versions
endforeach
versions = '''2 3 4 5 6 7 8 9 10 11 13 14 15 17 19
20 24 27 30 31 32 33 34 35 36 38 39 40 43'''.split()
20 24 27 30 31 32 33 34 35 36 38 39 40 43 44'''.split()
foreach version: versions
script = '''@2@
#if SPICE_GTK_VERSION_MAX_ALLOWED < SPICE_GTK_VERSION_@0@_@1@

View File

@ -3001,6 +3001,25 @@ gboolean spice_channel_test_capability(SpiceChannel *self, guint32 cap)
return test_capability(c->remote_caps, cap);
}
/**
* spice_channel_test_local_capability:
* @channel: a #SpiceChannel
* @cap: a capability
*
* Test availability of local "channel kind capability".
*
* Returns: %TRUE if @cap (channel kind capability) is available.
**/
gboolean spice_channel_test_local_capability(SpiceChannel *self, guint32 cap)
{
SpiceChannelPrivate *c;
g_return_val_if_fail(SPICE_IS_CHANNEL(self), FALSE);
c = self->priv;
return test_capability(c->caps, cap);
}
/**
* spice_channel_test_common_capability:
* @channel: a #SpiceChannel

View File

@ -158,6 +158,8 @@ gint spice_channel_string_to_type(const gchar *str);
SPICE_GTK_AVAILABLE_IN_0_24
const GError* spice_channel_get_error(SpiceChannel *channel);
SPICE_GTK_AVAILABLE_IN_0_44
gboolean spice_channel_test_local_capability(SpiceChannel *channel, guint32 cap);
G_END_DECLS
#endif /* __SPICE_CLIENT_CHANNEL_H__ */