[Spice-devel] [PATCH 2/2] Detect played silence and stop audio stream after 1 second

alexl at redhat.com alexl at redhat.com
Wed Aug 25 01:49:25 PDT 2010


From: Alexander Larsson <alexl at redhat.com>

VLC sends silence when paused (bug #28817), which causes a lot of
unnecessary network traffic. We detect such silence and shut
down the clients audio stream (even though the audio is still active
in the server), re-enabling it when we get non-silent data again.
---
 server/snd_worker.c |   60 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/server/snd_worker.c b/server/snd_worker.c
index 6c0f9d6..b5c3199 100644
--- a/server/snd_worker.c
+++ b/server/snd_worker.c
@@ -79,7 +79,9 @@ struct SndChannel {
 
     int active;
     int client_active;
+    int client_silent; /* client_active TRUE, but stopped anyway due to silence */
     int blocked;
+    int silent_count;
 
     uint32_t command;
     int migrate;
@@ -536,12 +538,19 @@ static int snd_playback_send_stop(PlaybackChannel *playback_channel)
 static int snd_playback_send_ctl(PlaybackChannel *playback_channel)
 {
     SndChannel *channel = (SndChannel *)playback_channel;
+    int was_silent;
 
     if ((channel->client_active = channel->active)) {
+        channel->client_silent = FALSE;
         return snd_playback_send_start(playback_channel);
     } else {
-        return snd_playback_send_stop(playback_channel);
+        was_silent = channel->client_silent;
+        channel->client_silent = FALSE;
+        if (!was_silent) {
+            return snd_playback_send_stop(playback_channel);
+        }
     }
+    return TRUE;
 }
 
 static int snd_record_send_start(RecordChannel *record_channel)
@@ -882,22 +891,65 @@ __visible__ void spice_server_playback_get_buffer(SpicePlaybackInstance *sin,
     *num_samples = FRAME_SIZE;
 }
 
+static int frame_is_silent(AudioFrame *frame)
+{
+    int i;
+
+    for (i = 0; i < FRAME_SIZE; i++) {
+        if (frame->samples[i] != 0) {
+            return FALSE;
+        }
+    }
+
+    return TRUE;
+}
+
 __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);
     AudioFrame *frame;
+    uint32_t mm_time;
 
     if (!channel)
         return;
     ASSERT(playback_channel->base.active);
 
+    frame = SPICE_CONTAINEROF(samples, AudioFrame, samples);
+
+    mm_time = reds_get_mm_time();
+    red_dispatcher_set_mm_time(mm_time);
+
+    if (frame_is_silent(frame)) {
+        if (channel->client_silent) {
+            snd_playback_free_frame(playback_channel, frame);
+            return;
+        }
+        channel->silent_count++;
+        if (channel->silent_count > SPICE_INTERFACE_PLAYBACK_FREQ / FRAME_SIZE) {
+            /* After 1 sec of silence we stop the audio */
+            channel->client_silent = TRUE;
+            if (playback_channel->pending_frame) {
+                snd_playback_free_frame(playback_channel, playback_channel->pending_frame);
+                playback_channel->pending_frame = NULL;
+            }
+            snd_playback_free_frame(playback_channel, frame);
+            snd_playback_send_stop(playback_channel);
+
+            return;
+        }
+    } else {
+        if (channel->client_silent) {
+            snd_playback_send_start(playback_channel);
+            channel->client_silent = FALSE;
+        }
+        channel->silent_count = 0;
+    }
+
     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);
+    frame->time = mm_time;
     playback_channel->pending_frame = frame;
     snd_set_command(&playback_channel->base, SND_PLAYBACK_PCM_MASK);
     snd_playback_send(&playback_channel->base);
-- 
1.7.2.1



More information about the Spice-devel mailing list