summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorJeremy White <jwhite@codeweavers.com>2013-11-30 09:19:21 -0600
committerChristophe Fergeau <cfergeau@redhat.com>2014-01-02 12:36:59 +0100
commitce9b714137a767b81f2d3c40b5f3ce0d5cf70fc8 (patch)
treed0d0c87004994d5d037fb63a7c1d588bafe11226 /client
parent4c7c0ef3a70001b1bc9011ef824d3c6fcccd9ca0 (diff)
downloadspice-ce9b714137a767b81f2d3c40b5f3ce0d5cf70fc8.tar.gz
spice-ce9b714137a767b81f2d3c40b5f3ce0d5cf70fc8.tar.xz
spice-ce9b714137a767b81f2d3c40b5f3ce0d5cf70fc8.zip
Add support for the Opus codec
Signed-off-by: Jeremy White <jwhite@codeweavers.com>
Diffstat (limited to 'client')
-rw-r--r--client/audio_channels.h3
-rw-r--r--client/audio_devices.h8
-rw-r--r--client/platform.h6
-rw-r--r--client/playback_channel.cpp23
-rw-r--r--client/record_channel.cpp41
-rw-r--r--client/x11/platform.cpp10
-rw-r--r--client/x11/playback.cpp13
-rw-r--r--client/x11/playback.h5
-rw-r--r--client/x11/record.cpp15
-rw-r--r--client/x11/record.h7
10 files changed, 76 insertions, 55 deletions
diff --git a/client/audio_channels.h b/client/audio_channels.h
index d7b81e75..fdb4dc93 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 a1da1f72..111c3667 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 913bcde4..0a88f06b 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 173c94a6..9f8c334c 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 2870f62f..047cdd0b 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 b8563b3f..bb8704c4 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 5fa7e182..035d6de8 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 27ef9ed7..383f02d3 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 535a8c9e..32c0af7f 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 91410962..9470791f 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;