[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