[Spice-devel] [PATCH spice-server 2/7] VideoStream: store channel in stream
Jonathon Jongsma
jjongsma at redhat.com
Thu Nov 30 20:19:12 UTC 2017
On Thu, 2017-11-30 at 13:40 -0500, Frediano Ziglio wrote:
> >
> > This allows us to unref the stream directly rather than needing to
> > pass
> > the associated DisplayChannel to stream_unref(). The same is also
> > true
> > for stream_agent_unref, since the only reason that
> > stream_agent_unref()
> > required a DisplayChannel parameter was to pass it to
> > stream_unref().
> > This also resulted in some additional minor redesign due to the
> > fact
> > that streams are pre-allocated in a pool in the display channel,
> > and
> > freeing a stream simply means moving it to a different ring to be
> > re-used.
> >
> > Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
> > ---
> > server/display-channel.c | 27 ++++++++++++++++++++++++++-
> > server/display-channel.h | 1 +
> > server/video-stream.c | 44 ++++++++++++----------------------
> > ----------
> > server/video-stream.h | 8 ++++----
> > 4 files changed, 43 insertions(+), 37 deletions(-)
> >
> > diff --git a/server/display-channel.c b/server/display-channel.c
> > index 2caaa6433..d3db1e0db 100644
> > --- a/server/display-channel.c
> > +++ b/server/display-channel.c
> > @@ -272,7 +272,7 @@ static void stop_streams(DisplayChannel
> > *display)
> > VideoStream *stream = SPICE_CONTAINEROF(item, VideoStream,
> > link);
> > item = ring_next(ring, item);
> > if (!stream->current) {
> > - video_stream_stop(display, stream);
> > + video_stream_stop(stream);
> > } else {
> > spice_debug("attached stream");
> > }
> > @@ -2279,6 +2279,31 @@ display_channel_init(DisplayChannel *self)
> > self->priv->image_surfaces.ops = &image_surfaces_ops;
> > }
> >
> > +static void display_channel_mark_stream_unused(DisplayChannel
> > *display,
> > VideoStream *stream)
> > +{
> > + stream->next = display->priv->free_streams;
> > + display->priv->free_streams = stream;
> > +}
> > +
> > +static void display_channel_init_video_streams(DisplayChannel
> > *display)
> > +{
> > + int i;
> > +
> > + ring_init(&display->priv->streams);
> > + display->priv->free_streams = NULL;
> > + for (i = 0; i < NUM_STREAMS; i++) {
> > + VideoStream *stream =
> > display_channel_get_nth_video_stream(display,
> > i);
> > + ring_item_init(&stream->link);
> > + display_channel_mark_stream_unused(display, stream);
> > + }
> > +}
> > +
> > +void display_channel_free_video_stream(DisplayChannel *display,
> > VideoStream
> > *stream)
> > +{
> > + display_channel_mark_stream_unused(stream->display, stream);
> > + display->priv->stream_count--;
> > +}
> > +
> > static void
> > display_channel_constructed(GObject *object)
> > {
> > diff --git a/server/display-channel.h b/server/display-channel.h
> > index 4f7def216..a0470ec67 100644
> > --- a/server/display-channel.h
> > +++ b/server/display-channel.h
> > @@ -168,6 +168,7 @@ gboolean
> > display_channel_surface_has_canvas(DisplayChannel *display,
> > uint32_t su
> > void display_channel_reset_image_cache(DisplayChannel *self);
> >
> > void display_channel_debug_oom(DisplayChannel *display, const char
> > *msg);
> > +void display_channel_free_video_stream(DisplayChannel *display,
> > VideoStream
> > *stream);
> >
> > G_END_DECLS
> >
> > diff --git a/server/video-stream.c b/server/video-stream.c
> > index 65da3f8a0..a24c787ef 100644
> > --- a/server/video-stream.c
> > +++ b/server/video-stream.c
> > @@ -66,8 +66,7 @@ static void
> > video_stream_agent_stats_print(VideoStreamAgent
> > *agent)
> > static void video_stream_create_destroy_item_release(RedPipeItem
> > *base)
> > {
> > StreamCreateDestroyItem *item =
> > SPICE_UPCAST(StreamCreateDestroyItem,
> > base);
> > - DisplayChannel *display = DCC_TO_DC(item->agent->dcc);
> > - video_stream_agent_unref(display, item->agent);
> > + video_stream_agent_unref(item->agent);
> > g_free(item);
> > }
> >
> > @@ -94,8 +93,9 @@ static RedPipeItem
> > *video_stream_destroy_item_new(VideoStreamAgent *agent)
> > }
> >
> >
> > -void video_stream_stop(DisplayChannel *display, VideoStream
> > *stream)
> > +void video_stream_stop(VideoStream *stream)
> > {
> > + DisplayChannel *display = stream->display;
> > DisplayChannelClient *dcc;
> > int stream_id = display_channel_get_video_stream_id(display,
> > stream);
> >
> > @@ -125,53 +125,32 @@ void video_stream_stop(DisplayChannel
> > *display,
> > VideoStream *stream)
> > }
> > display->priv->streams_size_total -= stream->width * stream-
> > >height;
> > ring_remove(&stream->link);
> > - video_stream_unref(display, stream);
> > + video_stream_unref(stream);
> > }
> >
> > -static void video_stream_free(DisplayChannel *display, VideoStream
> > *stream)
> > -{
> > - stream->next = display->priv->free_streams;
> > - display->priv->free_streams = stream;
> > -}
> > -
> > -void display_channel_init_video_streams(DisplayChannel *display)
> > -{
> > - int i;
> > -
> > - ring_init(&display->priv->streams);
> > - display->priv->free_streams = NULL;
> > - for (i = 0; i < NUM_STREAMS; i++) {
> > - VideoStream *stream =
> > display_channel_get_nth_video_stream(display,
> > i);
> > - ring_item_init(&stream->link);
> > - video_stream_free(display, stream);
> > - }
> > -}
> > -
> > -void video_stream_unref(DisplayChannel *display, VideoStream
> > *stream)
> > +void video_stream_unref(VideoStream *stream)
> > {
> > if (--stream->refs != 0)
> > return;
> >
> > spice_warn_if_fail(!ring_item_is_linked(&stream->link));
> >
> > - video_stream_free(display, stream);
> > - display->priv->stream_count--;
> > + display_channel_free_video_stream(stream->display, stream);
> > }
> >
> > -void video_stream_agent_unref(DisplayChannel *display,
> > VideoStreamAgent
> > *agent)
> > +void video_stream_agent_unref(VideoStreamAgent *agent)
> > {
> > - video_stream_unref(display, agent->stream);
> > + video_stream_unref(agent->stream);
> > }
> >
> > static void video_stream_clip_item_free(RedPipeItem *base)
> > {
> > g_return_if_fail(base != NULL);
> > VideoStreamClipItem *item = SPICE_UPCAST(VideoStreamClipItem,
> > base);
> > - DisplayChannel *display = DCC_TO_DC(item->stream_agent->dcc);
> >
> > g_return_if_fail(item->base.refcount == 0);
> >
> > - video_stream_agent_unref(display, item->stream_agent);
> > + video_stream_agent_unref(item->stream_agent);
> > g_free(item->rects);
> > g_free(item);
> > }
> > @@ -375,6 +354,7 @@ static VideoStream
> > *display_channel_stream_try_new(DisplayChannel *display)
> > }
> > stream = display->priv->free_streams;
> > display->priv->free_streams = display->priv->free_streams-
> > >next;
> > + stream->display = display;
> > return stream;
> > }
> >
> > @@ -923,7 +903,7 @@ void
> > video_stream_detach_and_stop(DisplayChannel
> > *display)
> > VideoStream *stream = SPICE_CONTAINEROF(stream_item,
> > VideoStream,
> > link);
> >
> > detach_video_stream_gracefully(display, stream, NULL);
> > - video_stream_stop(display, stream);
> > + video_stream_stop(stream);
> > }
> > }
> >
> > @@ -939,7 +919,7 @@ void video_stream_timeout(DisplayChannel
> > *display)
> > item = ring_next(ring, item);
> > if (now >= (stream->last_time + RED_STREAM_TIMEOUT)) {
> > detach_video_stream_gracefully(display, stream, NULL);
> > - video_stream_stop(display, stream);
> > + video_stream_stop(stream);
> > }
> > }
> > }
> > diff --git a/server/video-stream.h b/server/video-stream.h
> > index a4d149816..88d59c848 100644
> > --- a/server/video-stream.h
> > +++ b/server/video-stream.h
> > @@ -125,11 +125,11 @@ struct VideoStream {
> > uint32_t num_input_frames;
> > uint64_t input_fps_start_time;
> > uint32_t input_fps;
> > + DisplayChannel *display;
> > };
> >
> > -void display_channel_init_video_streams(DisplayChannel *display);
> > -void video_stream_stop(DisplayChannel *display, VideoStream
> > *stream);
> > -void video_stream_unref(DisplayChannel *display, VideoStream
> > *stream);
> > +void video_stream_stop(VideoStream *stream);
> > +void video_stream_unref(VideoStream *stream);
> > void video_stream_trace_update(DisplayChannel *display, Drawable
> > *drawable);
> > void video_stream_maintenance(DisplayChannel *display, Drawable
> > *candidate,
> > Drawable *prev);
> > @@ -139,7 +139,7 @@ void
> > video_stream_trace_add_drawable(DisplayChannel
> > *display, Drawable *item);
> > void video_stream_detach_behind(DisplayChannel *display, QRegion
> > *region,
> > Drawable *drawable);
> >
> > -void video_stream_agent_unref(DisplayChannel *display,
> > VideoStreamAgent
> > *agent);
> > +void video_stream_agent_unref(VideoStreamAgent *agent);
> > void video_stream_agent_stop(VideoStreamAgent *agent);
> >
> > void video_stream_detach_drawable(VideoStream *stream);
>
> Looks like this patch is trying to do multiple stuff.
> Yes, having display directly in the VideoStream helps but for
> instance
> there are different functions (like display_channel_get_stream_id)
> that
> would benefit from this change.
> On the other side there's no much rationale on some function move.
> This for this patch but also 3/7.
Yes, it does look a bit like it's doing more than it should. But this
is a bit of a complicated situation. These VideoStream/VideoStreamAgent
items are all preallocated in an array within the
DisplayChannel/DisplayChannelClient objects. So "freeing" a VideoStream
object is not as simple as de-allocating the memory. Instead we need to
tell the DisplayChannel (who owns the memory) that this VideoStream is
no longer used. This is done by video_stream_free(display, stream). But
this function really acts like a DisplayChannel member function (for
example: display->free_video_stream(stream)) and requires access to the
internals of DisplayChannel. So I moved this function to display-
channel.[ch] and renamed it to display_channel_free_video_stream().
(I just noticed that video_stream_stop() also modifies the internals of
DisplayChannel, so
> What should the rule why a given function should be in video-stream.c
> and not on display-channel.c/dcc.c/dcc-send.c?
Well, my long-term goal was to have video-stream.[ch] only contain the
types and functions directly related to VideoStream (and potentially
VideoStreamAgent). In other words: member functions. It should not need
to access the internals of any other types (for example: DisplayChannel
or DisplayChannelClient). I agree that after this patch series, it's
nowhere near that goal, but I think it's a step in the right direction.
You may disagree though.
> Not that I have a precise
> idea myself but these functions had been moved around multiple time
> and I think the main reason is that we don't have an agreed reasoning
> of this split. Said that streaming handling is part of the display
> channel
> where should be the code that detect new streams reside? For instance
> looks like the code that initialize a VideoStream is in display-
> channel.c
> but all the *_new functions are usually in the same file that should
> handle the structure, in this case video-stream.c.
Well, since DisplayChannel maintains a pool of pre-allocated
VideoStream objects, this object is different than most in that we
don't have a *_new() function that allocates and initializes the
object. Nevertheless, I agree that the initialization of VideoStream
does not really belong in display-channel.c. I could have perhaps added
a video_stream_init(...) function that is called from
display_channel_create_stream().
> If the VideoStreamAgent is specifically related to the client (so
> DisplayChannelClient) should the code reside in dcc.c or video-
> stream.c?
> Why the definition is in video-stream.h and some code in dcc.c?
> I tried to do some split like what I did for image encoding but
> got not really far, the code is too much mingled.
Yes, I didn't try to untangle too much of the streamagent/dcc stuff yet
since it is much more entangled. As I said, this wasn't meant to be a
full solution, just a partial move in the right direction, I hope.
>
> Frediano
More information about the Spice-devel
mailing list