summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorJeremy White <jwhite@codeweavers.com>2013-11-30 09:14:44 -0600
committerChristophe Fergeau <cfergeau@redhat.com>2014-01-02 12:34:34 +0100
commit4c7c0ef3a70001b1bc9011ef824d3c6fcccd9ca0 (patch)
tree22ff63f9ed6e7bc671244ece6cba72da61851740 /client
parent4fc9ba5f27dd4c04441d38c893ee962da01baf80 (diff)
downloadspice-4c7c0ef3a70001b1bc9011ef824d3c6fcccd9ca0.tar.gz
spice-4c7c0ef3a70001b1bc9011ef824d3c6fcccd9ca0.tar.xz
spice-4c7c0ef3a70001b1bc9011ef824d3c6fcccd9ca0.zip
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 <jwhite@codeweavers.com>
Diffstat (limited to 'client')
-rw-r--r--client/audio_channels.h12
-rw-r--r--client/playback_channel.cpp59
-rw-r--r--client/record_channel.cpp69
3 files changed, 58 insertions, 82 deletions
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 <celt051/celt.h>
+#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<RecordSamplesMessage *> _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<RecordChannel, SPICE_CHANNEL_RECORD> {
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;