[Spice-commits] 2 commits - server/snd_worker.c

Christophe Fergau teuf at kemper.freedesktop.org
Mon Oct 1 10:13:33 PDT 2012


 server/snd_worker.c |   18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

New commits:
commit d958fc100c0d14c8f55016df417c7587f670b037
Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Thu Sep 13 13:38:50 2012 -0500

    server: Access the correct SndChannel for a given AudioFrame
    
    The client of _get_buffer() holds a ref to the SndChannel, and we
    should access that SndChannel when _put_samples() is called, not the one
    that happens to currently be attached to the Interface.

diff --git a/server/snd_worker.c b/server/snd_worker.c
index 13f8c4d..6034aec 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -122,10 +122,14 @@ struct SndChannel {
     snd_channel_cleanup_channel_proc cleanup;
 };
 
+struct PlaybackChannel;
+typedef struct PlaybackChannel PlaybackChannel;
+
 typedef struct AudioFrame AudioFrame;
 struct AudioFrame {
     uint32_t time;
     uint32_t samples[FRAME_SIZE];
+    PlaybackChannel *channel;
     AudioFrame *next;
 };
 
@@ -227,6 +231,7 @@ static void snd_disconnect_channel(SndChannel *channel)
 
 static void snd_playback_free_frame(PlaybackChannel *playback_channel, AudioFrame *frame)
 {
+    frame->channel = playback_channel;
     frame->next = playback_channel->free_frames;
     playback_channel->free_frames = frame;
 }
@@ -1067,14 +1072,16 @@ SPICE_GNUC_VISIBLE void spice_server_playback_get_buffer(SpicePlaybackInstance *
 
 SPICE_GNUC_VISIBLE void spice_server_playback_put_samples(SpicePlaybackInstance *sin, uint32_t *samples)
 {
-    SndChannel *channel = sin->st->worker.connection;
-    PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base);
+    PlaybackChannel *playback_channel;
     AudioFrame *frame;
 
-    if (!channel) {
+    if (!sin->st->worker.connection) {
         return;
     }
-    if (!snd_channel_put(channel)) {
+
+    frame = SPICE_CONTAINEROF(samples, AudioFrame, samples);
+    playback_channel = frame->channel;
+    if (!snd_channel_put(&playback_channel->base) || !playback_channel->base.worker->connection) {
         /* lost last reference, channel has been destroyed previously */
         return;
     }
@@ -1083,7 +1090,6 @@ SPICE_GNUC_VISIBLE void spice_server_playback_put_samples(SpicePlaybackInstance
     if (playback_channel->pending_frame) {
         snd_playback_free_frame(playback_channel, playback_channel->pending_frame);
     }
-    frame = SPICE_CONTAINEROF(samples, AudioFrame, samples);
     frame->time = reds_get_mm_time();
     red_dispatcher_set_mm_time(frame->time);
     playback_channel->pending_frame = frame;
commit 0a62e332119abf5d21790e125f51c599a5c651dd
Author: Andrew Eikum <aeikum at codeweavers.com>
Date:   Thu Sep 13 13:21:07 2012 -0500

    server: Don't release SndChannel twice from worker reference
    
    When we release the SndChannel reference during
    snd_disconnect_channel(), we need to set the pointer to NULL so it
    doesn't get released again on client reconnect during
    snd_set_playback_peer(). This can happen when a reference is held from
    _playback_get_buffer().

diff --git a/server/snd_worker.c b/server/snd_worker.c
index 995823c..13f8c4d 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -195,7 +195,6 @@ static SndChannel *snd_channel_get(SndChannel *channel)
 static SndChannel *snd_channel_put(SndChannel *channel)
 {
     if (!--channel->refs) {
-        channel->worker->connection = NULL;
         free(channel);
         spice_printerr("sound channel freed");
         return NULL;
@@ -223,6 +222,7 @@ static void snd_disconnect_channel(SndChannel *channel)
         spice_marshaller_destroy(channel->send_data.marshaller);
     }
     snd_channel_put(channel);
+    channel->worker->connection = NULL;
 }
 
 static void snd_playback_free_frame(PlaybackChannel *playback_channel, AudioFrame *frame)


More information about the Spice-commits mailing list