~ubuntu-branches/debian/sid/spice/sid

« back to all changes in this revision

Viewing changes to .pc/make-celt-to-be-optional.patch/client/record_channel.cpp

  • Committer: Package Import Robot
  • Author(s): Michael Tokarev
  • Date: 2014-05-23 19:26:44 UTC
  • mfrom: (0.5.4)
  • Revision ID: package-import@ubuntu.com-20140523192644-svo3epmsv5i1ioql
Tags: 0.12.5-1
* new upstream release.  Can now build without celt!
* Dropped patches:
  - make-celt-to-be-optional.patch
  - link-server-test-with-libm-libpthread.patch
  - enable_subdir-objects.patch
  - fix-buffer-overflow-when-decrypting-client-spice-ticket.patch
* build-depend on libopus-dev, which enables opus support
  (no --enable-opus configure flag for now)
* do not remove .version in clean anymore (it is part of the tarball)
* do not use dh_autoreconf, since we aren't changing autoconf anymore
* update libspice-server1.symbols with new symbols
* introduce libspice-server1-dbg package (Closes: #743850)
* fix the vcs-browse url (Closes: #722241)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
   Copyright (C) 2009 Red Hat, Inc.
3
 
 
4
 
   This library is free software; you can redistribute it and/or
5
 
   modify it under the terms of the GNU Lesser General Public
6
 
   License as published by the Free Software Foundation; either
7
 
   version 2.1 of the License, or (at your option) any later version.
8
 
 
9
 
   This library is distributed in the hope that it will be useful,
10
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
   Lesser General Public License for more details.
13
 
 
14
 
   You should have received a copy of the GNU Lesser General Public
15
 
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
16
 
*/
17
 
#ifdef HAVE_CONFIG_H
18
 
#include <config.h>
19
 
#endif
20
 
 
21
 
#include "common.h"
22
 
#include "red_client.h"
23
 
#include "audio_channels.h"
24
 
#include "audio_devices.h"
25
 
 
26
 
#define NUM_SAMPLES_MESSAGES 4
27
 
 
28
 
 
29
 
static uint32_t get_mm_time()
30
 
{
31
 
    return uint32_t(Platform::get_monolithic_time() / (1000 * 1000));
32
 
}
33
 
 
34
 
class RecordSamplesMessage: public RedChannel::OutMessage {
35
 
public:
36
 
    RecordSamplesMessage(RecordChannel& channel);
37
 
    virtual ~RecordSamplesMessage();
38
 
 
39
 
    virtual RedPeer::OutMessage& peer_message() { return *_message;}
40
 
    virtual void release();
41
 
 
42
 
private:
43
 
    RecordChannel& _channel;
44
 
    RedPeer::OutMessage *_message;
45
 
};
46
 
 
47
 
RecordSamplesMessage::RecordSamplesMessage(RecordChannel& channel)
48
 
    : _channel (channel)
49
 
    , _message (new Message(SPICE_MSGC_RECORD_DATA))
50
 
{
51
 
}
52
 
 
53
 
RecordSamplesMessage::~RecordSamplesMessage()
54
 
{
55
 
    delete _message;
56
 
}
57
 
 
58
 
void RecordSamplesMessage::release()
59
 
{
60
 
    _channel.release_message(this);
61
 
}
62
 
 
63
 
int RecordChannel::data_mode = SPICE_AUDIO_DATA_MODE_CELT_0_5_1;
64
 
 
65
 
class RecordHandler: public MessageHandlerImp<RecordChannel, SPICE_CHANNEL_RECORD> {
66
 
public:
67
 
    RecordHandler(RecordChannel& channel)
68
 
        : MessageHandlerImp<RecordChannel, SPICE_CHANNEL_RECORD>(channel) {}
69
 
};
70
 
 
71
 
RecordChannel::RecordChannel(RedClient& client, uint32_t id)
72
 
    : RedChannel(client, SPICE_CHANNEL_RECORD, id, new RecordHandler(*this))
73
 
    , _wave_recorder (NULL)
74
 
    , _mode (SPICE_AUDIO_DATA_MODE_INVALID)
75
 
    , _celt_mode (NULL)
76
 
    , _celt_encoder (NULL)
77
 
{
78
 
    for (int i = 0; i < NUM_SAMPLES_MESSAGES; i++) {
79
 
        _messages.push_front(new RecordSamplesMessage(*this));
80
 
    }
81
 
 
82
 
    RecordHandler* handler = static_cast<RecordHandler*>(get_message_handler());
83
 
 
84
 
    handler->set_handler(SPICE_MSG_MIGRATE, &RecordChannel::handle_migrate);
85
 
    handler->set_handler(SPICE_MSG_SET_ACK, &RecordChannel::handle_set_ack);
86
 
    handler->set_handler(SPICE_MSG_PING, &RecordChannel::handle_ping);
87
 
    handler->set_handler(SPICE_MSG_WAIT_FOR_CHANNELS, &RecordChannel::handle_wait_for_channels);
88
 
    handler->set_handler(SPICE_MSG_DISCONNECTING, &RecordChannel::handle_disconnect);
89
 
    handler->set_handler(SPICE_MSG_NOTIFY, &RecordChannel::handle_notify);
90
 
 
91
 
    handler->set_handler(SPICE_MSG_RECORD_START, &RecordChannel::handle_start);
92
 
 
93
 
    set_capability(SPICE_RECORD_CAP_CELT_0_5_1);
94
 
}
95
 
 
96
 
RecordChannel::~RecordChannel(void)
97
 
{
98
 
    while (!_messages.empty()) {
99
 
        RecordSamplesMessage *mes;
100
 
        mes = *_messages.begin();
101
 
        _messages.pop_front();
102
 
        delete mes;
103
 
    }
104
 
    clear();
105
 
}
106
 
 
107
 
bool RecordChannel::abort(void)
108
 
{
109
 
    return (!_wave_recorder || _wave_recorder->abort()) && RedChannel::abort();
110
 
}
111
 
 
112
 
void RecordChannel::on_connect()
113
 
{
114
 
    Message* message = new Message(SPICE_MSGC_RECORD_MODE);
115
 
    SpiceMsgcRecordMode mode;
116
 
    mode.time = get_mm_time();
117
 
    mode.mode = _mode =
118
 
      test_capability(SPICE_RECORD_CAP_CELT_0_5_1) ? RecordChannel::data_mode :
119
 
                                                                      SPICE_AUDIO_DATA_MODE_RAW;
120
 
    _marshallers->msgc_record_mode(message->marshaller(), &mode);
121
 
    post_message(message);
122
 
}
123
 
 
124
 
void RecordChannel::on_disconnect()
125
 
{
126
 
    clear();
127
 
}
128
 
 
129
 
void RecordChannel::send_start_mark()
130
 
{
131
 
    Message* message = new Message(SPICE_MSGC_RECORD_START_MARK);
132
 
    SpiceMsgcRecordStartMark start_mark;
133
 
    start_mark.time = get_mm_time();
134
 
    _marshallers->msgc_record_start_mark(message->marshaller(), &start_mark);
135
 
    post_message(message);
136
 
}
137
 
 
138
 
void RecordChannel::handle_start(RedPeer::InMessage* message)
139
 
{
140
 
    RecordHandler* handler = static_cast<RecordHandler*>(get_message_handler());
141
 
    SpiceMsgRecordStart* start = (SpiceMsgRecordStart*)message->data();
142
 
 
143
 
    handler->set_handler(SPICE_MSG_RECORD_START, NULL);
144
 
    handler->set_handler(SPICE_MSG_RECORD_STOP, &RecordChannel::handle_stop);
145
 
    ASSERT(!_wave_recorder && !_celt_mode && !_celt_encoder);
146
 
 
147
 
    // for now support only one setting
148
 
    if (start->format != SPICE_AUDIO_FMT_S16) {
149
 
        THROW("unexpected format");
150
 
    }
151
 
 
152
 
    int bits_per_sample = 16;
153
 
    try {
154
 
        _wave_recorder = Platform::create_recorder(*this, start->frequency,
155
 
                                                   bits_per_sample,
156
 
                                                   start->channels);
157
 
    } catch (...) {
158
 
        LOG_WARN("create recorder failed");
159
 
        return;
160
 
    }
161
 
 
162
 
    int frame_size = 256;
163
 
    int celt_mode_err;
164
 
    _frame_bytes = frame_size * bits_per_sample * start->channels / 8;
165
 
    if (!(_celt_mode = celt051_mode_create(start->frequency, start->channels, frame_size,
166
 
                                           &celt_mode_err))) {
167
 
        THROW("create celt mode failed %d", celt_mode_err);
168
 
    }
169
 
 
170
 
    if (!(_celt_encoder = celt051_encoder_create(_celt_mode))) {
171
 
        THROW("create celt encoder failed");
172
 
    }
173
 
 
174
 
    send_start_mark();
175
 
    _wave_recorder->start();
176
 
}
177
 
 
178
 
void RecordChannel::clear()
179
 
{
180
 
    if (_wave_recorder) {
181
 
        _wave_recorder->stop();
182
 
        delete _wave_recorder;
183
 
        _wave_recorder = NULL;
184
 
    }
185
 
    if (_celt_encoder) {
186
 
        celt051_encoder_destroy(_celt_encoder);
187
 
        _celt_encoder = NULL;
188
 
    }
189
 
    if (_celt_mode) {
190
 
        celt051_mode_destroy(_celt_mode);
191
 
        _celt_mode = NULL;
192
 
    }
193
 
}
194
 
 
195
 
void RecordChannel::handle_stop(RedPeer::InMessage* message)
196
 
{
197
 
    RecordHandler* handler = static_cast<RecordHandler*>(get_message_handler());
198
 
    handler->set_handler(SPICE_MSG_RECORD_START, &RecordChannel::handle_start);
199
 
    handler->set_handler(SPICE_MSG_RECORD_STOP, NULL);
200
 
    if (!_wave_recorder) {
201
 
        return;
202
 
    }
203
 
    ASSERT(_celt_mode && _celt_encoder);
204
 
    clear();
205
 
}
206
 
 
207
 
RecordSamplesMessage* RecordChannel::get_message()
208
 
{
209
 
    Lock lock(_messages_lock);
210
 
    if (_messages.empty()) {
211
 
        return NULL;
212
 
    }
213
 
 
214
 
    RecordSamplesMessage* ret = *_messages.begin();
215
 
    _messages.pop_front();
216
 
    return ret;
217
 
}
218
 
 
219
 
void RecordChannel::release_message(RecordSamplesMessage *message)
220
 
{
221
 
    Lock lock(_messages_lock);
222
 
    _messages.push_front(message);
223
 
}
224
 
 
225
 
void RecordChannel::add_event_source(EventSources::File& event_source)
226
 
{
227
 
    get_process_loop().add_file(event_source);
228
 
}
229
 
 
230
 
void RecordChannel::remove_event_source(EventSources::File& event_source)
231
 
{
232
 
    get_process_loop().remove_file(event_source);
233
 
}
234
 
 
235
 
void RecordChannel::add_event_source(EventSources::Trigger& event_source)
236
 
{
237
 
    get_process_loop().add_trigger(event_source);
238
 
}
239
 
 
240
 
void RecordChannel::remove_event_source(EventSources::Trigger& event_source)
241
 
{
242
 
    get_process_loop().remove_trigger(event_source);
243
 
}
244
 
 
245
 
#define FRAME_SIZE 256
246
 
#define CELT_BIT_RATE (64 * 1024)
247
 
#define CELT_COMPRESSED_FRAME_BYTES (FRAME_SIZE * CELT_BIT_RATE / 44100 / 8)
248
 
 
249
 
void RecordChannel::push_frame(uint8_t *frame)
250
 
{
251
 
    RecordSamplesMessage *message;
252
 
    ASSERT(_frame_bytes == FRAME_SIZE * 4);
253
 
    if (!(message = get_message())) {
254
 
        DBG(0, "blocked");
255
 
        return;
256
 
    }
257
 
    uint8_t celt_buf[CELT_COMPRESSED_FRAME_BYTES];
258
 
    int n;
259
 
 
260
 
    if (_mode == SPICE_AUDIO_DATA_MODE_CELT_0_5_1) {
261
 
        n = celt051_encode(_celt_encoder, (celt_int16_t *)frame, NULL, celt_buf,
262
 
                           CELT_COMPRESSED_FRAME_BYTES);
263
 
        if (n < 0) {
264
 
            THROW("celt encode failed");
265
 
        }
266
 
        frame = celt_buf;
267
 
    } else {
268
 
        n = _frame_bytes;
269
 
    }
270
 
    RedPeer::OutMessage& peer_message = message->peer_message();
271
 
    peer_message.reset(SPICE_MSGC_RECORD_DATA);
272
 
    SpiceMsgcRecordPacket packet;
273
 
    packet.time = get_mm_time();
274
 
    _marshallers->msgc_record_data(peer_message.marshaller(), &packet);
275
 
    spice_marshaller_add(peer_message.marshaller(), frame, n);
276
 
    post_message(message);
277
 
}
278
 
 
279
 
class RecordFactory: public ChannelFactory {
280
 
public:
281
 
    RecordFactory() : ChannelFactory(SPICE_CHANNEL_RECORD) {}
282
 
    virtual RedChannel* construct(RedClient& client, uint32_t id)
283
 
    {
284
 
        return new RecordChannel(client, id);
285
 
    }
286
 
};
287
 
 
288
 
static RecordFactory factory;
289
 
 
290
 
ChannelFactory& RecordChannel::Factory()
291
 
{
292
 
    return factory;
293
 
}