On Sat, Nov 30, 2013 at 09:19:21AM -0600, Jeremy White wrote: > > Signed-off-by: Jeremy White <jwhite@xxxxxxxxxxxxxxx> > --- > client/audio_channels.h | 3 +- > client/audio_devices.h | 8 --- > client/platform.h | 6 ++- > client/playback_channel.cpp | 23 ++++---- > client/record_channel.cpp | 41 ++++++++++----- > client/x11/platform.cpp | 10 ++-- > client/x11/playback.cpp | 13 ++--- > client/x11/playback.h | 5 +- > client/x11/record.cpp | 15 +++--- > client/x11/record.h | 7 ++- > server/snd_worker.c | 121 +++++++++++++++++++++++++++++++++---------- > server/spice-server.syms | 8 +++ > server/spice.h | 15 ++++-- > 13 files changed, 188 insertions(+), 87 deletions(-) > > diff --git a/client/audio_channels.h b/client/audio_channels.h > index d7b81e7..fdb4dc9 100644 > --- a/client/audio_channels.h > +++ b/client/audio_channels.h > @@ -72,7 +72,6 @@ public: > static ChannelFactory& Factory(); > > protected: > - virtual void on_connect(); > virtual void on_disconnect(); > > private: > @@ -85,6 +84,8 @@ private: > virtual void remove_event_source(EventSources::Trigger& event_source); > virtual void push_frame(uint8_t *frame); > > + void set_desired_mode(int frequency); > + void send_record_mode(); > void send_start_mark(); > void release_message(RecordSamplesMessage *message); > RecordSamplesMessage * get_message(); > diff --git a/client/audio_devices.h b/client/audio_devices.h > index a1da1f7..111c366 100644 > --- a/client/audio_devices.h > +++ b/client/audio_devices.h > @@ -27,10 +27,6 @@ public: > virtual bool abort() = 0; > virtual void stop() = 0; > virtual uint32_t get_delay_ms() = 0; > - > - enum { > - FRAME_SIZE = 256, > - }; > }; > > class WaveRecordAbstract { > @@ -42,10 +38,6 @@ public: > virtual void start() = 0; > virtual void stop() = 0; > virtual bool abort() = 0; > - > - enum { > - FRAME_SIZE = 256, > - }; > }; > > #endif > diff --git a/client/platform.h b/client/platform.h > index 913bcde..0a88f06 100644 > --- a/client/platform.h > +++ b/client/platform.h > @@ -68,10 +68,12 @@ public: > static WaveRecordAbstract* create_recorder(RecordClient& client, > uint32_t sampels_per_sec, > uint32_t bits_per_sample, > - uint32_t channels); > + uint32_t channels, > + uint32_t frame_size); > static WavePlaybackAbstract* create_player(uint32_t sampels_per_sec, > uint32_t bits_per_sample, > - uint32_t channels); > + uint32_t channels, > + uint32_t frame_size); > > enum { > SCROLL_LOCK_MODIFIER_SHIFT, > diff --git a/client/playback_channel.cpp b/client/playback_channel.cpp > index 173c94a..9f8c334 100644 > --- a/client/playback_channel.cpp > +++ b/client/playback_channel.cpp > @@ -168,8 +168,10 @@ PlaybackChannel::PlaybackChannel(RedClient& client, uint32_t id) > > handler->set_handler(SPICE_MSG_PLAYBACK_MODE, &PlaybackChannel::handle_mode); > > - if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1)) > + if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1, SND_CODEC_ANY_FREQUENCY)) > set_capability(SPICE_PLAYBACK_CAP_CELT_0_5_1); > + if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_OPUS, SND_CODEC_ANY_FREQUENCY)) > + set_capability(SPICE_PLAYBACK_CAP_OPUS); > } > > void PlaybackChannel::clear() > @@ -206,7 +208,7 @@ void PlaybackChannel::set_data_handler() > > if (_mode == SPICE_AUDIO_DATA_MODE_RAW) { > handler->set_handler(SPICE_MSG_PLAYBACK_DATA, &PlaybackChannel::handle_raw_data); > - } else if (snd_codec_is_capable(_mode)) { > + } else if (snd_codec_is_capable(_mode, SND_CODEC_ANY_FREQUENCY)) { > handler->set_handler(SPICE_MSG_PLAYBACK_DATA, &PlaybackChannel::handle_compressed_data); > } else { > THROW("invalid mode"); > @@ -218,7 +220,7 @@ void PlaybackChannel::handle_mode(RedPeer::InMessage* message) > { > SpiceMsgPlaybackMode* playback_mode = (SpiceMsgPlaybackMode*)message->data(); > if (playback_mode->mode != SPICE_AUDIO_DATA_MODE_RAW > - && !snd_codec_is_capable(playback_mode->mode) ) { > + && !snd_codec_is_capable(playback_mode->mode, SND_CODEC_ANY_FREQUENCY) ) { > THROW("invalid mode"); > } > > @@ -266,9 +268,16 @@ void PlaybackChannel::handle_start(RedPeer::InMessage* message) > } > int bits_per_sample = 16; > int frame_size = SND_CODEC_MAX_FRAME_SIZE; > + > + if (_mode != SPICE_AUDIO_DATA_MODE_RAW) { > + if (snd_codec_create(&_codec, _mode, start->frequency, SND_CODEC_DECODE) != SND_CODEC_OK) > + THROW("create decoder"); > + frame_size = snd_codec_frame_size(_codec); > + } > + > try { > _wave_player = Platform::create_player(start->frequency, bits_per_sample, > - start->channels); > + start->channels, frame_size); > } catch (...) { > LOG_WARN("create player failed"); > //todo: support disconnecting single channel > @@ -276,12 +285,6 @@ void PlaybackChannel::handle_start(RedPeer::InMessage* message) > return; > } > > - if (_mode != SPICE_AUDIO_DATA_MODE_RAW) { > - if (snd_codec_create(&_codec, _mode, start->frequency, SND_CODEC_DECODE) != SND_CODEC_OK) > - THROW("create decoder"); > - frame_size = snd_codec_frame_size(_codec); > - } > - > _frame_bytes = frame_size * start->channels * bits_per_sample / 8; > } > _playing = true; > diff --git a/client/record_channel.cpp b/client/record_channel.cpp > index 2870f62..047cdd0 100644 > --- a/client/record_channel.cpp > +++ b/client/record_channel.cpp > @@ -87,8 +87,10 @@ RecordChannel::RecordChannel(RedClient& client, uint32_t id) > > handler->set_handler(SPICE_MSG_RECORD_START, &RecordChannel::handle_start); > > - if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1)) > + if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1, SND_CODEC_ANY_FREQUENCY)) > set_capability(SPICE_RECORD_CAP_CELT_0_5_1); > + if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_OPUS, SND_CODEC_ANY_FREQUENCY)) > + set_capability(SPICE_RECORD_CAP_OPUS); > } > > RecordChannel::~RecordChannel(void) > @@ -107,16 +109,23 @@ bool RecordChannel::abort(void) > return (!_wave_recorder || _wave_recorder->abort()) && RedChannel::abort(); > } > > -void RecordChannel::on_connect() > +void RecordChannel::set_desired_mode(int frequency) > { > - Message* message = new Message(SPICE_MSGC_RECORD_MODE); > - SpiceMsgcRecordMode mode; > - mode.time = get_mm_time(); > - if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1) && > + if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_OPUS, frequency) && > + test_capability(SPICE_RECORD_CAP_OPUS)) > + _mode = SPICE_AUDIO_DATA_MODE_OPUS; > + else if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1, frequency) && > test_capability(SPICE_RECORD_CAP_CELT_0_5_1)) > _mode = SPICE_AUDIO_DATA_MODE_CELT_0_5_1; > else > _mode = SPICE_AUDIO_DATA_MODE_RAW; > +} > + > +void RecordChannel::send_record_mode() > +{ > + Message* message = new Message(SPICE_MSGC_RECORD_MODE); > + SpiceMsgcRecordMode mode; > + mode.time = get_mm_time(); > mode.mode = _mode; > _marshallers->msgc_record_mode(message->marshaller(), &mode); > post_message(message); > @@ -153,24 +162,29 @@ void RecordChannel::handle_start(RedPeer::InMessage* message) > THROW("unexpected number of channels"); > } > > + set_desired_mode(start->frequency); > + > + int frame_size = SND_CODEC_MAX_FRAME_SIZE; > + if (_mode != SPICE_AUDIO_DATA_MODE_RAW) { > + if (snd_codec_create(&_codec, _mode, start->frequency, SND_CODEC_ENCODE) != SND_CODEC_OK) > + THROW("create encoder failed"); > + frame_size = snd_codec_frame_size(_codec); > + } > + > int bits_per_sample = 16; > try { > _wave_recorder = Platform::create_recorder(*this, start->frequency, > bits_per_sample, > - start->channels); > + start->channels, > + frame_size); > } catch (...) { > LOG_WARN("create recorder failed"); > return; > } > > - int frame_size = SND_CODEC_MAX_FRAME_SIZE; > - if (_mode != SPICE_AUDIO_DATA_MODE_RAW) { > - if (snd_codec_create(&_codec, _mode, start->frequency, SND_CODEC_ENCODE) != SND_CODEC_OK) > - THROW("create encoder failed"); > - frame_size = snd_codec_frame_size(_codec); > - } > _frame_bytes = frame_size * bits_per_sample * start->channels / 8; > > + send_record_mode(); > send_start_mark(); > _wave_recorder->start(); > } > @@ -237,7 +251,6 @@ void RecordChannel::remove_event_source(EventSources::Trigger& event_source) > void RecordChannel::push_frame(uint8_t *frame) > { > RecordSamplesMessage *message; > - ASSERT(_frame_bytes == FRAME_SIZE * 4); > if (!(message = get_message())) { > DBG(0, "blocked"); > return; > diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp > index b8563b3..bb8704c 100644 > --- a/client/x11/platform.cpp > +++ b/client/x11/platform.cpp > @@ -3433,16 +3433,18 @@ void Platform::reset_cursor_pos() > WaveRecordAbstract* Platform::create_recorder(RecordClient& client, > uint32_t sampels_per_sec, > uint32_t bits_per_sample, > - uint32_t channels) > + uint32_t channels, > + uint32_t frame_size) > { > - return new WaveRecorder(client, sampels_per_sec, bits_per_sample, channels); > + return new WaveRecorder(client, sampels_per_sec, bits_per_sample, channels, frame_size); > } > > WavePlaybackAbstract* Platform::create_player(uint32_t sampels_per_sec, > uint32_t bits_per_sample, > - uint32_t channels) > + uint32_t channels, > + uint32_t frame_size) > { > - return new WavePlayer(sampels_per_sec, bits_per_sample, channels); > + return new WavePlayer(sampels_per_sec, bits_per_sample, channels, frame_size); > } > > void XPlatform::on_focus_in() > diff --git a/client/x11/playback.cpp b/client/x11/playback.cpp > index 5fa7e18..035d6de 100644 > --- a/client/x11/playback.cpp > +++ b/client/x11/playback.cpp > @@ -24,12 +24,12 @@ > > #define REING_SIZE_MS 300 > > -WavePlayer::WavePlayer(uint32_t sampels_per_sec, uint32_t bits_per_sample, uint32_t channels) > +WavePlayer::WavePlayer(uint32_t sampels_per_sec, uint32_t bits_per_sample, uint32_t channels, uint32_t frame_size) > : _pcm (NULL) > , _hw_params (NULL) > , _sw_params (NULL) > { > - if (!init(sampels_per_sec, bits_per_sample, channels)) { > + if (!init(sampels_per_sec, bits_per_sample, channels, frame_size)) { > cleanup(); > THROW("failed"); > } > @@ -57,9 +57,9 @@ WavePlayer::~WavePlayer() > > bool WavePlayer::init(uint32_t sampels_per_sec, > uint32_t bits_per_sample, > - uint32_t channels) > + uint32_t channels, > + uint32_t frame_size) > { > - const int frame_size = WavePlaybackAbstract::FRAME_SIZE; > const char* pcm_device = "default"; > snd_pcm_format_t format; > int err; > @@ -75,6 +75,7 @@ bool WavePlayer::init(uint32_t sampels_per_sec, > return false; > } > _sampels_per_ms = sampels_per_sec / 1000; > + _frame_size = frame_size; > > if ((err = snd_pcm_open(&_pcm, pcm_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) { > LOG_ERROR("cannot open audio playback device %s %s", pcm_device, snd_strerror(err)); > @@ -183,14 +184,14 @@ bool WavePlayer::init(uint32_t sampels_per_sec, > > bool WavePlayer::write(uint8_t* frame) > { > - snd_pcm_sframes_t ret = snd_pcm_writei(_pcm, frame, WavePlaybackAbstract::FRAME_SIZE); > + snd_pcm_sframes_t ret = snd_pcm_writei(_pcm, frame, _frame_size); > if (ret < 0) { > if (ret == -EAGAIN) { > return false; > } > DBG(0, "err %s", snd_strerror(-ret)); > if (snd_pcm_recover(_pcm, ret, 1) == 0) { > - snd_pcm_writei(_pcm, frame, WavePlaybackAbstract::FRAME_SIZE); > + snd_pcm_writei(_pcm, frame, _frame_size); > } > } > return true; > diff --git a/client/x11/playback.h b/client/x11/playback.h > index 27ef9ed..383f02d 100644 > --- a/client/x11/playback.h > +++ b/client/x11/playback.h > @@ -25,7 +25,7 @@ > > class WavePlayer: public WavePlaybackAbstract { > public: > - WavePlayer(uint32_t sampels_per_sec, uint32_t bits_per_sample, uint32_t channels); > + WavePlayer(uint32_t sampels_per_sec, uint32_t bits_per_sample, uint32_t channels, uint32_t frame_size); > virtual ~WavePlayer(); > > virtual bool write(uint8_t* frame); > @@ -34,7 +34,7 @@ public: > virtual uint32_t get_delay_ms(); > > private: > - bool init(uint32_t sampels_per_sec, uint32_t bits_per_sample, uint32_t channel); > + bool init(uint32_t sampels_per_sec, uint32_t bits_per_sample, uint32_t channel, uint32_t frame_size); > void cleanup(); > > private: > @@ -42,6 +42,7 @@ private: > snd_pcm_hw_params_t* _hw_params; > snd_pcm_sw_params_t* _sw_params; > uint32_t _sampels_per_ms; > + uint32_t _frame_size; > }; > > #endif > diff --git a/client/x11/record.cpp b/client/x11/record.cpp > index 535a8c9..32c0af7 100644 > --- a/client/x11/record.cpp > +++ b/client/x11/record.cpp > @@ -48,18 +48,19 @@ void WaveRecorder::EventTrigger::on_event() > WaveRecorder::WaveRecorder(Platform::RecordClient& client, > uint32_t sampels_per_sec, > uint32_t bits_per_sample, > - uint32_t channels) > + uint32_t channels, > + uint32_t frame_size) > : _client (client) > , _pcm (NULL) > , _hw_params (NULL) > , _sw_params (NULL) > , _sample_bytes (bits_per_sample * channels / 8) > - , _frame (new uint8_t[_sample_bytes * WaveRecordAbstract::FRAME_SIZE]) > + , _frame (new uint8_t[_sample_bytes * frame_size]) > , _frame_pos (_frame) > - , _frame_end (_frame + _sample_bytes * WaveRecordAbstract::FRAME_SIZE) > + , _frame_end (_frame + _sample_bytes * frame_size) > , _event_trigger (NULL) > { > - if (!init(sampels_per_sec, bits_per_sample, channels)) { > + if (!init(sampels_per_sec, bits_per_sample, channels, frame_size)) { > cleanup(); > THROW("failed"); > } > @@ -93,13 +94,15 @@ void WaveRecorder::cleanup() > > bool WaveRecorder::init(uint32_t sampels_per_sec, > uint32_t bits_per_sample, > - uint32_t channels) > + uint32_t channels, > + uint32_t frame_size) > { > - const int frame_size = WaveRecordAbstract::FRAME_SIZE; > const char* pcm_device = "default"; > snd_pcm_format_t format; > int err; > > + _frame_size = frame_size; > + > switch (bits_per_sample) { > case 8: > format = SND_PCM_FORMAT_S8; > diff --git a/client/x11/record.h b/client/x11/record.h > index 9141096..9470791 100644 > --- a/client/x11/record.h > +++ b/client/x11/record.h > @@ -29,7 +29,8 @@ public: > WaveRecorder(Platform::RecordClient& client, > uint32_t sampels_per_sec, > uint32_t bits_per_sample, > - uint32_t channels); > + uint32_t channels, > + uint32_t frame_size); > virtual ~WaveRecorder(); > > virtual void start(); > @@ -39,7 +40,8 @@ public: > private: > bool init(uint32_t sampels_per_sec, > uint32_t bits_per_sample, > - uint32_t channels); > + uint32_t channels, > + uint32_t frame_size); > void cleanup(); > void on_event(); > > @@ -49,6 +51,7 @@ private: > snd_pcm_hw_params_t* _hw_params; > snd_pcm_sw_params_t* _sw_params; > uint32_t _sample_bytes; > + uint32_t _frame_size; > uint8_t* _frame; > uint8_t* _frame_pos; > uint8_t* _frame_end; > diff --git a/server/snd_worker.c b/server/snd_worker.c > index f40fd65..240f0dd 100644 > --- a/server/snd_worker.c > +++ b/server/snd_worker.c > +SPICE_GNUC_VISIBLE uint32_t spice_server_get_best_playback_rate(SpicePlaybackInstance *sin) > +{ > + int client_can_opus = TRUE; > + if (sin && sin->st->worker.connection) { > + SndChannel *channel = sin->st->worker.connection; > + PlaybackChannel *playback_channel = SPICE_CONTAINEROF(channel, PlaybackChannel, base); > + client_can_opus = red_channel_client_test_remote_cap(playback_channel->base.channel_client, > + SPICE_PLAYBACK_CAP_OPUS); > + } > + > + if (client_can_opus && snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_OPUS, SND_CODEC_ANY_FREQUENCY)) > + return SND_CODEC_OPUS_PLAYBACK_FREQ; > + > + return SND_CODEC_CELT_PLAYBACK_FREQ; > +} > + > +SPICE_GNUC_VISIBLE void spice_server_set_playback_rate(SpicePlaybackInstance *sin, uint32_t frequency) > +{ > + RedChannel *channel = sin->st->worker.base_channel; > + sin->st->frequency = frequency; > + if (channel && snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_OPUS, frequency)) > + red_channel_set_cap(channel, SPICE_PLAYBACK_CAP_OPUS); > +} > + > +SPICE_GNUC_VISIBLE uint32_t spice_server_get_best_record_rate(SpiceRecordInstance *sin) > +{ > + int client_can_opus = TRUE; > + if (sin && sin->st->worker.connection) { > + SndChannel *channel = sin->st->worker.connection; > + RecordChannel *record_channel = SPICE_CONTAINEROF(channel, RecordChannel, base); > + client_can_opus = red_channel_client_test_remote_cap(record_channel->base.channel_client, > + SPICE_RECORD_CAP_OPUS); > + } > + > + if (client_can_opus && snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_OPUS, SND_CODEC_ANY_FREQUENCY)) > + return SND_CODEC_OPUS_PLAYBACK_FREQ; > + > + return SND_CODEC_CELT_PLAYBACK_FREQ; > +} > + > +SPICE_GNUC_VISIBLE void spice_server_set_record_rate(SpiceRecordInstance *sin, uint32_t frequency) > +{ > + RedChannel *channel = sin->st->worker.base_channel; > + sin->st->frequency = frequency; > + if (channel && snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_OPUS, frequency)) > + red_channel_set_cap(channel, SPICE_PLAYBACK_CAP_OPUS); small c&p issue here, this should be SPICE_RECORD_CAP_OPUS. I'll squash this in, and finally push the whole series! Thanks a lot for all the hardwork! Christophe
Attachment:
pgpv77dE5sJ56.pgp
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel