On 06.05.2012 08:21, Serge E. Hallyn wrote: > Just saw http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=671627 (someone > forwarded it to me). Glad it seems to have worked out :) If you want > more help pls let me know, but if you're comfortable as is that's great.
Well, it hasn't worked out yet, as I wrote in #671627 I had no good conditions to do the work before since spice didn't work in 32bits, and while I had a patch for some time I had no idea if it works or not. Yesterday I did some testing, but again I've no idea if it works or not -- I don't know how to test sound transmitted using spice! The current version of the patch is attached, for anyone to experiment. I'll try to do my best afer a short vacation we all russians have these days due to the Victory Day (World Wide War II), I'll be back in May-10. Thank you! /mjt
diff --git a/client/audio_channels.h b/client/audio_channels.h index d38a79e..8f8a186 100644 --- a/client/audio_channels.h +++ b/client/audio_channels.h @@ -18,7 +18,9 @@ #ifndef _H_AUDIO_CHANNELS #define _H_AUDIO_CHANNELS +#if HAVE_CELT051 #include <celt051/celt.h> +#endif #include "red_channel.h" #include "debug.h" @@ -45,7 +47,9 @@ private: void handle_start(RedPeer::InMessage* message); void handle_stop(RedPeer::InMessage* message); void handle_raw_data(RedPeer::InMessage* message); +#if HAVE_CELT051 void handle_celt_data(RedPeer::InMessage* message); +#endif void null_handler(RedPeer::InMessage* message); void disable(); @@ -57,8 +61,10 @@ private: WavePlaybackAbstract* _wave_player; uint32_t _mode; uint32_t _frame_bytes; +#if HAVE_CELT051 CELTMode *_celt_mode; CELTDecoder *_celt_decoder; +#endif bool _playing; uint32_t _frame_count; }; @@ -96,8 +102,10 @@ private: Mutex _messages_lock; std::list<RecordSamplesMessage *> _messages; int _mode; +#if HAVE_CELT051 CELTMode *_celt_mode; CELTEncoder *_celt_encoder; +#endif uint32_t _frame_bytes; static int data_mode; diff --git a/client/playback_channel.cpp b/client/playback_channel.cpp index 802a4d3..caf6424 100644 --- a/client/playback_channel.cpp +++ b/client/playback_channel.cpp @@ -151,8 +151,10 @@ PlaybackChannel::PlaybackChannel(RedClient& client, uint32_t id) Platform::PRIORITY_HIGH) , _wave_player (NULL) , _mode (SPICE_AUDIO_DATA_MODE_INVALID) +#if HAVE_CELT051 , _celt_mode (NULL) , _celt_decoder (NULL) +#endif , _playing (false) { #ifdef WAVE_CAPTURE @@ -169,7 +171,9 @@ PlaybackChannel::PlaybackChannel(RedClient& client, uint32_t id) handler->set_handler(SPICE_MSG_PLAYBACK_MODE, &PlaybackChannel::handle_mode); +#if HAVE_CELT051 set_capability(SPICE_PLAYBACK_CAP_CELT_0_5_1); +#endif } void PlaybackChannel::clear() @@ -182,6 +186,7 @@ void PlaybackChannel::clear() } _mode = SPICE_AUDIO_DATA_MODE_INVALID; +#if HAVE_CELT051 if (_celt_decoder) { celt051_decoder_destroy(_celt_decoder); _celt_decoder = NULL; @@ -191,6 +196,7 @@ void PlaybackChannel::clear() celt051_mode_destroy(_celt_mode); _celt_mode = NULL; } +#endif } void PlaybackChannel::on_disconnect() @@ -214,8 +220,10 @@ void PlaybackChannel::set_data_handler() if (_mode == SPICE_AUDIO_DATA_MODE_RAW) { handler->set_handler(SPICE_MSG_PLAYBACK_DATA, &PlaybackChannel::handle_raw_data); +#if HAVE_CELT051 } else if (_mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) { handler->set_handler(SPICE_MSG_PLAYBACK_DATA, &PlaybackChannel::handle_celt_data); +#endif } else { THROW("invalid mode"); } @@ -224,8 +232,11 @@ void PlaybackChannel::set_data_handler() 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) { + if (playbacke_mode->mode != SPICE_AUDIO_DATA_MODE_RAW +#if HAVE_CELT051 + && playbacke_mode->mode != SPICE_AUDIO_DATA_MODE_CELT_0_5_1 +#endif + ) { THROW("invalid mode"); } @@ -265,9 +276,6 @@ 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"); } @@ -284,6 +292,10 @@ void PlaybackChannel::handle_start(RedPeer::InMessage* message) return; } +#if HAVE_CELT051 + // for now support only one setting + int celt_mode_err; + if (!(_celt_mode = celt051_mode_create(start->frequency, start->channels, frame_size, &celt_mode_err))) { THROW("create celt mode failed %d", celt_mode_err); @@ -292,6 +304,7 @@ void PlaybackChannel::handle_start(RedPeer::InMessage* message) if (!(_celt_decoder = celt051_decoder_create(_celt_mode))) { THROW("create celt decoder"); } +#endif } _playing = true; _frame_count = 0; @@ -333,6 +346,7 @@ void PlaybackChannel::handle_raw_data(RedPeer::InMessage* message) _wave_player->write(data); } +#if HAVE_CELT051 void PlaybackChannel::handle_celt_data(RedPeer::InMessage* message) { SpiceMsgPlaybackPacket* packet = (SpiceMsgPlaybackPacket*)message->data(); @@ -352,6 +366,7 @@ void PlaybackChannel::handle_celt_data(RedPeer::InMessage* message) } _wave_player->write((uint8_t *)pcm); } +#endif class PlaybackFactory: public ChannelFactory { public: diff --git a/client/record_channel.cpp b/client/record_channel.cpp index d9332c6..dbf8344 100644 --- a/client/record_channel.cpp +++ b/client/record_channel.cpp @@ -72,8 +72,10 @@ 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) +#if HAVE_CELT051 , _celt_mode (NULL) , _celt_encoder (NULL) +#endif { for (int i = 0; i < NUM_SAMPLES_MESSAGES; i++) { _messages.push_front(new RecordSamplesMessage(*this)); @@ -142,7 +144,11 @@ 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); +#if HAVE_CELT051 ASSERT(!_wave_recorder && !_celt_mode && !_celt_encoder); +#else + ASSERT(!_wave_recorder); +#endif // for now support only one setting if (start->format != SPICE_AUDIO_FMT_S16) { @@ -160,8 +166,9 @@ void RecordChannel::handle_start(RedPeer::InMessage* message) } int frame_size = 256; - int celt_mode_err; _frame_bytes = frame_size * bits_per_sample * start->channels / 8; +#if HAVE_CELT051 + int celt_mode_err; if (!(_celt_mode = celt051_mode_create(start->frequency, start->channels, frame_size, &celt_mode_err))) { THROW("create celt mode failed %d", celt_mode_err); @@ -170,6 +177,7 @@ void RecordChannel::handle_start(RedPeer::InMessage* message) if (!(_celt_encoder = celt051_encoder_create(_celt_mode))) { THROW("create celt encoder failed"); } +#endif send_start_mark(); _wave_recorder->start(); @@ -182,6 +190,7 @@ void RecordChannel::clear() delete _wave_recorder; _wave_recorder = NULL; } +#if HAVE_CELT051 if (_celt_encoder) { celt051_encoder_destroy(_celt_encoder); _celt_encoder = NULL; @@ -190,6 +199,7 @@ void RecordChannel::clear() celt051_mode_destroy(_celt_mode); _celt_mode = NULL; } +#endif } void RecordChannel::handle_stop(RedPeer::InMessage* message) @@ -200,7 +210,9 @@ void RecordChannel::handle_stop(RedPeer::InMessage* message) if (!_wave_recorder) { return; } +#if HAVE_CELT051 ASSERT(_celt_mode && _celt_encoder); +#endif clear(); } @@ -254,8 +266,9 @@ void RecordChannel::push_frame(uint8_t *frame) DBG(0, "blocked"); return; } - uint8_t celt_buf[CELT_COMPRESSED_FRAME_BYTES]; int n; +#if HAVE_CELT051 + uint8_t celt_buf[CELT_COMPRESSED_FRAME_BYTES]; if (_mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) { n = celt051_encode(_celt_encoder, (celt_int16_t *)frame, NULL, celt_buf, @@ -264,7 +277,9 @@ void RecordChannel::push_frame(uint8_t *frame) THROW("celt encode failed"); } frame = celt_buf; - } else { + } else +#endif + { n = _frame_bytes; } RedPeer::OutMessage& peer_message = message->peer_message(); diff --git a/configure.ac b/configure.ac index 66f9d12..21bd326 100644 --- a/configure.ac +++ b/configure.ac @@ -125,6 +125,9 @@ AM_CONDITIONAL(SUPPORT_SMARTCARD, test "x$enable_smartcard" != "xno") if test "x$enable_smartcard" = "xyes"; then AC_DEFINE([USE_SMARTCARD], [1], [Define if supporting smartcard proxying]) fi +AC_ARG_ENABLE(celt051, +[ --disable-celt051 Disable celt051 audio codec (enabled by default)],, +[enable_celt051="yes"]) AC_ARG_ENABLE(client, [ --enable-client Enable spice client],, @@ -220,11 +223,14 @@ AC_SUBST(PIXMAN_CFLAGS) AC_SUBST(PIXMAN_LIBS) SPICE_REQUIRES+=" pixman-1 >= 0.17.7" -PKG_CHECK_MODULES(CELT051, celt051 >= 0.5.1.1) -AC_SUBST(CELT051_CFLAGS) -AC_SUBST(CELT051_LIBS) -AC_SUBST(CELT051_LIBDIR) -SPICE_REQUIRES+=" celt051 >= 0.5.1.1" +if test "x$enable_celt051" = "xyes"; then + PKG_CHECK_MODULES(CELT051, celt051 >= 0.5.1.1) + SPICE_REQUIRES+=" celt051 >= 0.5.1.1" + AC_DEFINE([HAVE_CELT051], 1, [Define if we have celt051 codec]) + AC_SUBST(CELT051_CFLAGS) + AC_SUBST(CELT051_LIBS) + AC_SUBST(CELT051_LIBDIR) +fi if test ! -e client/generated_marshallers.cpp; then AC_MSG_CHECKING([for pyparsing python module]) diff --git a/server/snd_worker.c b/server/snd_worker.c index caffe67..a72aece 100644 --- a/server/snd_worker.c +++ b/server/snd_worker.c @@ -25,7 +25,9 @@ #include <sys/socket.h> #include <netinet/ip.h> #include <netinet/tcp.h> +#if HAVE_CELT051 #include <celt051/celt.h> +#endif #include "common/marshaller.h" #include "common/generated_server_marshallers.h" @@ -136,12 +138,14 @@ typedef struct PlaybackChannel { AudioFrame *free_frames; AudioFrame *in_progress; AudioFrame *pending_frame; + uint32_t mode; +#if HAVE_CELT051 CELTMode *celt_mode; CELTEncoder *celt_encoder; - uint32_t mode; struct { uint8_t celt_buf[CELT_COMPRESSED_FRAME_BYTES]; } send_data; +#endif } PlaybackChannel; struct SndWorker { @@ -187,13 +191,21 @@ typedef struct RecordChannel { uint32_t mode; uint32_t mode_time; uint32_t start_time; +#if HAVE_CELT051 CELTDecoder *celt_decoder; CELTMode *celt_mode; uint32_t celt_buf[FRAME_SIZE]; +#endif } RecordChannel; static SndWorker *workers; -static uint32_t playback_compression = SPICE_AUDIO_DATA_MODE_CELT_0_5_1; +static uint32_t playback_compression = +#if HAVE_CELT051 + SPICE_AUDIO_DATA_MODE_CELT_0_5_1 +#else + SPICE_AUDIO_DATA_MODE_RAW +#endif + ; static void snd_receive(void* data); @@ -322,6 +334,7 @@ static int snd_record_handle_write(RecordChannel *record_channel, size_t size, v packet = (SpiceMsgcRecordPacket *)message; size = packet->data_size; +#if HAVE_CELT051 if (record_channel->mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) { int celt_err = celt051_decode(record_channel->celt_decoder, packet->data, size, (celt_int16_t *)record_channel->celt_buf); @@ -331,7 +344,9 @@ static int snd_record_handle_write(RecordChannel *record_channel, size_t size, v } data = record_channel->celt_buf; size = FRAME_SIZE; - } else if (record_channel->mode == SPICE_AUDIO_DATA_MODE_RAW) { + } else +#endif + if (record_channel->mode == SPICE_AUDIO_DATA_MODE_RAW) { data = (uint32_t *)packet->data; size = size >> 2; size = MIN(size, RECORD_SAMPLES_SIZE); @@ -386,8 +401,11 @@ static int snd_record_handle_message(SndChannel *channel, size_t size, uint32_t SpiceMsgcRecordMode *mode = (SpiceMsgcRecordMode *)message; record_channel->mode = mode->mode; record_channel->mode_time = mode->time; - if (record_channel->mode != SPICE_AUDIO_DATA_MODE_CELT_0_5_1 && - record_channel->mode != SPICE_AUDIO_DATA_MODE_RAW) { + if (record_channel->mode != SPICE_AUDIO_DATA_MODE_RAW +#if HAVE_CELT051 + && record_channel->mode != SPICE_AUDIO_DATA_MODE_CELT_0_5_1 +#endif + ) { spice_printerr("unsupported mode"); } break; @@ -779,6 +797,7 @@ static int snd_playback_send_write(PlaybackChannel *playback_channel) spice_marshall_msg_playback_data(channel->send_data.marshaller, &msg); +#if HAVE_CELT051 if (playback_channel->mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) { int n = celt051_encode(playback_channel->celt_encoder, (celt_int16_t *)frame->samples, NULL, playback_channel->send_data.celt_buf, CELT_COMPRESSED_FRAME_BYTES); @@ -789,7 +808,9 @@ static int snd_playback_send_write(PlaybackChannel *playback_channel) } spice_marshaller_add_ref(channel->send_data.marshaller, playback_channel->send_data.celt_buf, n); - } else { + } else +#endif + { spice_marshaller_add_ref(channel->send_data.marshaller, (uint8_t *)frame->samples, sizeof(frame->samples)); } @@ -1154,8 +1175,10 @@ static void snd_playback_cleanup(SndChannel *channel) reds_enable_mm_timer(); } +#if HAVE_CELT051 celt051_encoder_destroy(playback_channel->celt_encoder); celt051_mode_destroy(playback_channel->celt_mode); +#endif } static void snd_set_playback_peer(RedChannel *channel, RedClient *client, RedsStream *stream, @@ -1165,13 +1188,13 @@ static void snd_set_playback_peer(RedChannel *channel, RedClient *client, RedsSt SndWorker *worker = channel->data; PlaybackChannel *playback_channel; SpicePlaybackState *st = SPICE_CONTAINEROF(worker, SpicePlaybackState, worker); - CELTEncoder *celt_encoder; - CELTMode *celt_mode; - int celt_error; - RedChannelClient *rcc; snd_disconnect_channel(worker->connection); +#if HAVE_CELT051 + CELTEncoder *celt_encoder; + CELTMode *celt_mode; + int celt_error; if (!(celt_mode = celt051_mode_create(SPICE_INTERFACE_PLAYBACK_FREQ, SPICE_INTERFACE_PLAYBACK_CHAN, FRAME_SIZE, &celt_error))) { @@ -1183,6 +1206,7 @@ static void snd_set_playback_peer(RedChannel *channel, RedClient *client, RedsSt spice_printerr("create celt encoder failed"); goto error_1; } +#endif if (!(playback_channel = (PlaybackChannel *)__new_channel(worker, sizeof(*playback_channel), @@ -1199,16 +1223,20 @@ static void snd_set_playback_peer(RedChannel *channel, RedClient *client, RedsSt goto error_2; } worker->connection = &playback_channel->base; - rcc = playback_channel->base.channel_client; snd_playback_free_frame(playback_channel, &playback_channel->frames[0]); snd_playback_free_frame(playback_channel, &playback_channel->frames[1]); snd_playback_free_frame(playback_channel, &playback_channel->frames[2]); +#if HAVE_CELT051 playback_channel->celt_mode = celt_mode; playback_channel->celt_encoder = celt_encoder; - playback_channel->mode = red_channel_client_test_remote_cap(rcc, - SPICE_PLAYBACK_CAP_CELT_0_5_1) ? + playback_channel->mode = + red_channel_client_test_remote_cap(playback_channel->base.channel_client, + SPICE_PLAYBACK_CAP_CELT_0_5_1) ? playback_compression : SPICE_AUDIO_DATA_MODE_RAW; +#else + playback_channel->mode = SPICE_AUDIO_DATA_MODE_RAW; +#endif on_new_playback_channel(worker); if (worker->active) { @@ -1218,10 +1246,13 @@ static void snd_set_playback_peer(RedChannel *channel, RedClient *client, RedsSt return; error_2: +#if HAVE_CELT051 celt051_encoder_destroy(celt_encoder); error_1: celt051_mode_destroy(celt_mode); +#endif + return; } static void snd_record_migrate_channel_client(RedChannelClient *rcc) @@ -1362,10 +1393,12 @@ static void on_new_record_channel(SndWorker *worker) static void snd_record_cleanup(SndChannel *channel) { +#if HAVE_CELT051 RecordChannel *record_channel = SPICE_CONTAINEROF(channel, RecordChannel, base); celt051_decoder_destroy(record_channel->celt_decoder); celt051_mode_destroy(record_channel->celt_mode); +#endif } static void snd_set_record_peer(RedChannel *channel, RedClient *client, RedsStream *stream, @@ -1375,12 +1408,13 @@ static void snd_set_record_peer(RedChannel *channel, RedClient *client, RedsStre SndWorker *worker = channel->data; RecordChannel *record_channel; SpiceRecordState *st = SPICE_CONTAINEROF(worker, SpiceRecordState, worker); - CELTDecoder *celt_decoder; - CELTMode *celt_mode; - int celt_error; snd_disconnect_channel(worker->connection); +#if HAVE_CELT051 + CELTDecoder *celt_decoder; + CELTMode *celt_mode; + int celt_error; if (!(celt_mode = celt051_mode_create(SPICE_INTERFACE_RECORD_FREQ, SPICE_INTERFACE_RECORD_CHAN, FRAME_SIZE, &celt_error))) { @@ -1392,6 +1426,7 @@ static void snd_set_record_peer(RedChannel *channel, RedClient *client, RedsStre spice_printerr("create celt decoder failed"); goto error_1; } +#endif if (!(record_channel = (RecordChannel *)__new_channel(worker, sizeof(*record_channel), @@ -1410,8 +1445,10 @@ static void snd_set_record_peer(RedChannel *channel, RedClient *client, RedsStre worker->connection = &record_channel->base; +#if HAVE_CELT051 record_channel->celt_mode = celt_mode; record_channel->celt_decoder = celt_decoder; +#endif on_new_record_channel(worker); if (worker->active) { @@ -1421,10 +1458,13 @@ static void snd_set_record_peer(RedChannel *channel, RedClient *client, RedsStre return; error_2: +#if HAVE_CELT051 celt051_decoder_destroy(celt_decoder); error_1: celt051_mode_destroy(celt_mode); +#endif + return; } static void snd_playback_migrate_channel_client(RedChannelClient *rcc) @@ -1480,7 +1520,9 @@ void snd_attach_playback(SpicePlaybackInstance *sin) client_cbs.migrate = snd_playback_migrate_channel_client; red_channel_register_client_cbs(channel, &client_cbs); red_channel_set_data(channel, playback_worker); +#if HAVE_CELT051 red_channel_set_cap(channel, SPICE_PLAYBACK_CAP_CELT_0_5_1); +#endif red_channel_set_cap(channel, SPICE_PLAYBACK_CAP_VOLUME); playback_worker->base_channel = channel; @@ -1507,7 +1549,9 @@ void snd_attach_record(SpiceRecordInstance *sin) client_cbs.migrate = snd_record_migrate_channel_client; red_channel_register_client_cbs(channel, &client_cbs); red_channel_set_data(channel, record_worker); +#if HAVE_CELT051 red_channel_set_cap(channel, SPICE_RECORD_CAP_CELT_0_5_1); +#endif red_channel_set_cap(channel, SPICE_RECORD_CAP_VOLUME); record_worker->base_channel = channel; @@ -1554,7 +1598,11 @@ void snd_set_playback_compression(int on) { SndWorker *now = workers; - playback_compression = on ? SPICE_AUDIO_DATA_MODE_CELT_0_5_1 : SPICE_AUDIO_DATA_MODE_RAW; + playback_compression = +#if HAVE_CELT051 + on ? SPICE_AUDIO_DATA_MODE_CELT_0_5_1 : +#endif + SPICE_AUDIO_DATA_MODE_RAW; for (; now; now = now->next) { if (now->base_channel->type == SPICE_CHANNEL_PLAYBACK && now->connection) { SndChannel* sndchannel = now->connection;