From 4c7c0ef3a70001b1bc9011ef824d3c6fcccd9ca0 Mon Sep 17 00:00:00 2001 From: Jeremy White Date: Sat, 30 Nov 2013 09:14:44 -0600 Subject: Revise the spice client and server to use the new snd_codec functions in spice-common. This makes celt optional, and paves the way to readily add additional codecs. Signed-off-by: Jeremy White --- client/audio_channels.h | 12 ++++---- client/playback_channel.cpp | 59 ++++++++++++++++---------------------- client/record_channel.cpp | 69 ++++++++++++++++++--------------------------- 3 files changed, 58 insertions(+), 82 deletions(-) (limited to 'client') diff --git a/client/audio_channels.h b/client/audio_channels.h index d38a79eb..d7b81e75 100644 --- a/client/audio_channels.h +++ b/client/audio_channels.h @@ -18,7 +18,7 @@ #ifndef _H_AUDIO_CHANNELS #define _H_AUDIO_CHANNELS -#include +#include "common/snd_codec.h" #include "red_channel.h" #include "debug.h" @@ -45,7 +45,7 @@ private: void handle_start(RedPeer::InMessage* message); void handle_stop(RedPeer::InMessage* message); void handle_raw_data(RedPeer::InMessage* message); - void handle_celt_data(RedPeer::InMessage* message); + void handle_compressed_data(RedPeer::InMessage* message); void null_handler(RedPeer::InMessage* message); void disable(); @@ -57,8 +57,7 @@ private: WavePlaybackAbstract* _wave_player; uint32_t _mode; uint32_t _frame_bytes; - CELTMode *_celt_mode; - CELTDecoder *_celt_decoder; + SndCodec _codec; bool _playing; uint32_t _frame_count; }; @@ -96,11 +95,10 @@ private: Mutex _messages_lock; std::list _messages; int _mode; - CELTMode *_celt_mode; - CELTEncoder *_celt_encoder; + SndCodec _codec; uint32_t _frame_bytes; - static int data_mode; + uint8_t compressed_buf[SND_CODEC_MAX_COMPRESSED_BYTES]; friend class RecordSamplesMessage; }; diff --git a/client/playback_channel.cpp b/client/playback_channel.cpp index 802a4d3b..173c94a6 100644 --- a/client/playback_channel.cpp +++ b/client/playback_channel.cpp @@ -151,8 +151,7 @@ PlaybackChannel::PlaybackChannel(RedClient& client, uint32_t id) Platform::PRIORITY_HIGH) , _wave_player (NULL) , _mode (SPICE_AUDIO_DATA_MODE_INVALID) - , _celt_mode (NULL) - , _celt_decoder (NULL) + , _codec(NULL) , _playing (false) { #ifdef WAVE_CAPTURE @@ -169,7 +168,8 @@ PlaybackChannel::PlaybackChannel(RedClient& client, uint32_t id) handler->set_handler(SPICE_MSG_PLAYBACK_MODE, &PlaybackChannel::handle_mode); - set_capability(SPICE_PLAYBACK_CAP_CELT_0_5_1); + if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1)) + set_capability(SPICE_PLAYBACK_CAP_CELT_0_5_1); } void PlaybackChannel::clear() @@ -182,15 +182,7 @@ void PlaybackChannel::clear() } _mode = SPICE_AUDIO_DATA_MODE_INVALID; - if (_celt_decoder) { - celt051_decoder_destroy(_celt_decoder); - _celt_decoder = NULL; - } - - if (_celt_mode) { - celt051_mode_destroy(_celt_mode); - _celt_mode = NULL; - } + snd_codec_destroy(&_codec); } void PlaybackChannel::on_disconnect() @@ -214,22 +206,23 @@ 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 (_mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) { - handler->set_handler(SPICE_MSG_PLAYBACK_DATA, &PlaybackChannel::handle_celt_data); + } else if (snd_codec_is_capable(_mode)) { + handler->set_handler(SPICE_MSG_PLAYBACK_DATA, &PlaybackChannel::handle_compressed_data); } else { THROW("invalid mode"); } + } void PlaybackChannel::handle_mode(RedPeer::InMessage* message) { - SpiceMsgPlaybackMode* playbacke_mode = (SpiceMsgPlaybackMode*)message->data(); - if (playbacke_mode->mode != SPICE_AUDIO_DATA_MODE_RAW && - playbacke_mode->mode != SPICE_AUDIO_DATA_MODE_CELT_0_5_1) { + SpiceMsgPlaybackMode* playback_mode = (SpiceMsgPlaybackMode*)message->data(); + if (playback_mode->mode != SPICE_AUDIO_DATA_MODE_RAW + && !snd_codec_is_capable(playback_mode->mode) ) { THROW("invalid mode"); } - _mode = playbacke_mode->mode; + _mode = playback_mode->mode; if (_playing) { set_data_handler(); return; @@ -265,15 +258,14 @@ void PlaybackChannel::handle_start(RedPeer::InMessage* message) start_wave(); #endif if (!_wave_player) { - // for now support only one setting - int celt_mode_err; - if (start->format != SPICE_AUDIO_FMT_S16) { THROW("unexpected format"); } + if (start->channels != 2) { + THROW("unexpected number of channels"); + } int bits_per_sample = 16; - int frame_size = 256; - _frame_bytes = frame_size * start->channels * bits_per_sample / 8; + int frame_size = SND_CODEC_MAX_FRAME_SIZE; try { _wave_player = Platform::create_player(start->frequency, bits_per_sample, start->channels); @@ -284,14 +276,13 @@ void PlaybackChannel::handle_start(RedPeer::InMessage* message) return; } - if (!(_celt_mode = celt051_mode_create(start->frequency, start->channels, - frame_size, &celt_mode_err))) { - THROW("create celt mode failed %d", celt_mode_err); + 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); } - if (!(_celt_decoder = celt051_decoder_create(_celt_mode))) { - THROW("create celt decoder"); - } + _frame_bytes = frame_size * start->channels * bits_per_sample / 8; } _playing = true; _frame_count = 0; @@ -333,16 +324,16 @@ void PlaybackChannel::handle_raw_data(RedPeer::InMessage* message) _wave_player->write(data); } -void PlaybackChannel::handle_celt_data(RedPeer::InMessage* message) +void PlaybackChannel::handle_compressed_data(RedPeer::InMessage* message) { SpiceMsgPlaybackPacket* packet = (SpiceMsgPlaybackPacket*)message->data(); uint8_t* data = packet->data; uint32_t size = packet->data_size; - celt_int16_t pcm[256 * 2]; + int pcm_size = _frame_bytes; + uint8_t pcm[_frame_bytes]; - if (celt051_decode(_celt_decoder, data, size, pcm) != CELT_OK) { - THROW("celt decode failed"); - } + if (snd_codec_decode(_codec, data, size, pcm, &pcm_size) != SND_CODEC_OK) + THROW("decode failed"); #ifdef WAVE_CAPTURE put_wave_data(pcm, _frame_bytes); return; diff --git a/client/record_channel.cpp b/client/record_channel.cpp index d9332c6b..2870f62f 100644 --- a/client/record_channel.cpp +++ b/client/record_channel.cpp @@ -60,8 +60,6 @@ void RecordSamplesMessage::release() _channel.release_message(this); } -int RecordChannel::data_mode = SPICE_AUDIO_DATA_MODE_CELT_0_5_1; - class RecordHandler: public MessageHandlerImp { public: RecordHandler(RecordChannel& channel) @@ -72,8 +70,7 @@ RecordChannel::RecordChannel(RedClient& client, uint32_t id) : RedChannel(client, SPICE_CHANNEL_RECORD, id, new RecordHandler(*this)) , _wave_recorder (NULL) , _mode (SPICE_AUDIO_DATA_MODE_INVALID) - , _celt_mode (NULL) - , _celt_encoder (NULL) + , _codec(NULL) { for (int i = 0; i < NUM_SAMPLES_MESSAGES; i++) { _messages.push_front(new RecordSamplesMessage(*this)); @@ -90,7 +87,8 @@ RecordChannel::RecordChannel(RedClient& client, uint32_t id) handler->set_handler(SPICE_MSG_RECORD_START, &RecordChannel::handle_start); - set_capability(SPICE_RECORD_CAP_CELT_0_5_1); + if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1)) + set_capability(SPICE_RECORD_CAP_CELT_0_5_1); } RecordChannel::~RecordChannel(void) @@ -114,9 +112,12 @@ void RecordChannel::on_connect() Message* message = new Message(SPICE_MSGC_RECORD_MODE); SpiceMsgcRecordMode mode; mode.time = get_mm_time(); - mode.mode = _mode = - test_capability(SPICE_RECORD_CAP_CELT_0_5_1) ? RecordChannel::data_mode : - SPICE_AUDIO_DATA_MODE_RAW; + if (snd_codec_is_capable(SPICE_AUDIO_DATA_MODE_CELT_0_5_1) && + 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; + mode.mode = _mode; _marshallers->msgc_record_mode(message->marshaller(), &mode); post_message(message); } @@ -142,12 +143,15 @@ void RecordChannel::handle_start(RedPeer::InMessage* message) handler->set_handler(SPICE_MSG_RECORD_START, NULL); handler->set_handler(SPICE_MSG_RECORD_STOP, &RecordChannel::handle_stop); - ASSERT(!_wave_recorder && !_celt_mode && !_celt_encoder); + ASSERT(!_wave_recorder); // for now support only one setting if (start->format != SPICE_AUDIO_FMT_S16) { THROW("unexpected format"); } + if (start->channels != 2) { + THROW("unexpected number of channels"); + } int bits_per_sample = 16; try { @@ -159,17 +163,13 @@ void RecordChannel::handle_start(RedPeer::InMessage* message) return; } - int frame_size = 256; - int celt_mode_err; - _frame_bytes = frame_size * bits_per_sample * start->channels / 8; - if (!(_celt_mode = celt051_mode_create(start->frequency, start->channels, frame_size, - &celt_mode_err))) { - THROW("create celt mode failed %d", celt_mode_err); - } - - if (!(_celt_encoder = celt051_encoder_create(_celt_mode))) { - THROW("create celt encoder failed"); + 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_start_mark(); _wave_recorder->start(); @@ -182,14 +182,7 @@ void RecordChannel::clear() delete _wave_recorder; _wave_recorder = NULL; } - if (_celt_encoder) { - celt051_encoder_destroy(_celt_encoder); - _celt_encoder = NULL; - } - if (_celt_mode) { - celt051_mode_destroy(_celt_mode); - _celt_mode = NULL; - } + snd_codec_destroy(&_codec); } void RecordChannel::handle_stop(RedPeer::InMessage* message) @@ -200,7 +193,6 @@ void RecordChannel::handle_stop(RedPeer::InMessage* message) if (!_wave_recorder) { return; } - ASSERT(_celt_mode && _celt_encoder); clear(); } @@ -242,10 +234,6 @@ void RecordChannel::remove_event_source(EventSources::Trigger& event_source) get_process_loop().remove_trigger(event_source); } -#define FRAME_SIZE 256 -#define CELT_BIT_RATE (64 * 1024) -#define CELT_COMPRESSED_FRAME_BYTES (FRAME_SIZE * CELT_BIT_RATE / 44100 / 8) - void RecordChannel::push_frame(uint8_t *frame) { RecordSamplesMessage *message; @@ -254,19 +242,18 @@ void RecordChannel::push_frame(uint8_t *frame) DBG(0, "blocked"); return; } - uint8_t celt_buf[CELT_COMPRESSED_FRAME_BYTES]; int n; - if (_mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) { - n = celt051_encode(_celt_encoder, (celt_int16_t *)frame, NULL, celt_buf, - CELT_COMPRESSED_FRAME_BYTES); - if (n < 0) { - THROW("celt encode failed"); - } - frame = celt_buf; - } else { + + if (_mode == SPICE_AUDIO_DATA_MODE_RAW) { n = _frame_bytes; + } else { + n = sizeof(compressed_buf); + if (snd_codec_encode(_codec, frame, _frame_bytes, compressed_buf, &n) != SND_CODEC_OK) + THROW("encode failed"); + frame = compressed_buf; } + RedPeer::OutMessage& peer_message = message->peer_message(); peer_message.reset(SPICE_MSGC_RECORD_DATA); SpiceMsgcRecordPacket packet; -- cgit