audiortp.cpp 17.3 KB
Newer Older
jpbl's avatar
jpbl committed
1
/*
2
 *
3
 *  Copyright (C) 2004-2007 Savoir-Faire Linux inc.
4
 *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
5
 *  Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com>
jpbl's avatar
jpbl committed
6
7
8
9
10
 *  Author: Yan Morin <yan.morin@savoirfairelinux.com>
 *  Author: Laurielle Lea <laurielle.lea@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 3 of the License, or
jpbl's avatar
jpbl committed
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <cstdio>
#include <cstdlib>
#include <ccrtp/rtp.h>
#include <assert.h>
#include <string>
29
#include <cstring>
30
#include <math.h>
31
32
#include <dlfcn.h>
#include <iostream>
jpbl's avatar
jpbl committed
33
34
35
36
37
38
39
40
41

#include "../global.h"
#include "../manager.h"
#include "codecDescriptor.h"
#include "audiortp.h"
#include "audiolayer.h"
#include "ringbuffer.h"
#include "../user_cfg.h"
#include "../sipcall.h"
42
#include <samplerate.h>
jpbl's avatar
jpbl committed
43
44
45
46
47
48

////////////////////////////////////////////////////////////////////////////////
// AudioRtp                                                          
////////////////////////////////////////////////////////////////////////////////
AudioRtp::AudioRtp ()
{
49
	_RTXThread = 0;
jpbl's avatar
jpbl committed
50
51
52
}

AudioRtp::~AudioRtp (void) {
53
	delete _RTXThread; _RTXThread = 0;
jpbl's avatar
jpbl committed
54
55
56
}

int 
yanmorin's avatar
   
yanmorin committed
57
AudioRtp::createNewSession (SIPCall *ca) {
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
	ost::MutexLock m(_threadMutex);

	// something should stop the thread before...
	if ( _RTXThread != 0 ) { 
		_debug("! ARTP Failure: Thread already exists..., stopping it\n");
		delete _RTXThread; _RTXThread = 0;
		//return -1; 
	}

	// Start RTP Send/Receive threads
	_symmetric = Manager::instance().getConfigInt(SIGNALISATION,SYMMETRIC) ? true : false;
	_RTXThread = new AudioRtpRTX (ca, _symmetric);
	try {
		if (_RTXThread->start() != 0) {
			_debug("! ARTP Failure: unable to start RTX Thread\n");
			return -1;
		}
	} catch(...) {
		_debugException("! ARTP Failure: when trying to start a thread");
		throw;
	}
	return 0;
jpbl's avatar
jpbl committed
80
81
}

82

jpbl's avatar
jpbl committed
83
84
void
AudioRtp::closeRtpSession () {
85
86
87
88
89
90
91
92
93
	ost::MutexLock m(_threadMutex);
	// This will make RTP threads finish.
	// _debug("Stopping AudioRTP\n");
	try {
		delete _RTXThread; _RTXThread = 0;
	} catch(...) {
		_debugException("! ARTP Exception: when stopping audiortp\n");
		throw;
	}
jpbl's avatar
jpbl committed
94
95
96
97
98
}

////////////////////////////////////////////////////////////////////////////////
// AudioRtpRTX Class                                                          //
////////////////////////////////////////////////////////////////////////////////
99
AudioRtpRTX::AudioRtpRTX (SIPCall *sipcall, bool sym)
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
100
	 : _fstream("/tmp/audio.gsm", std::ofstream::binary|std::ios::out|std::ios::app)
101
102
103
104
105
106
107
{
	setCancel(cancelDeferred);
	time = new ost::Time();
	_ca = sipcall;
	_sym = sym;
	// AudioRtpRTX should be close if we change sample rate

108
109
	//_codecSampleRate = _ca->getAudioCodec()->getClockRate();

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
	// TODO: Change bind address according to user settings.
	// TODO: this should be the local ip not the external (router) IP
	std::string localipConfig = _ca->getLocalIp(); // _ca->getLocalIp();
	ost::InetHostAddress local_ip(localipConfig.c_str());
	if (!_sym) {
		_sessionRecv = new ost::RTPSession(local_ip, _ca->getLocalAudioPort());
		_sessionSend = new ost::RTPSession(local_ip, _ca->getLocalAudioPort());
		_session = NULL;
	} else {
		_session = new ost::SymmetricRTPSession (local_ip, _ca->getLocalAudioPort());
		_sessionRecv = NULL;
		_sessionSend = NULL;
	}

	// libsamplerate-related
	// Set the converter type for the upsampling and the downsampling
	// interpolator SRC_SINC_BEST_QUALITY
	_src_state_mic  = src_new(SRC_SINC_BEST_QUALITY, 1, &_src_err);
	_src_state_spkr = src_new(SRC_SINC_BEST_QUALITY, 1, &_src_err);

jpbl's avatar
jpbl committed
130
131
132
}

AudioRtpRTX::~AudioRtpRTX () {
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
	_start.wait();

	try {
		this->terminate();
	} catch(...) {
		_debugException("! ARTP: Thread destructor didn't terminate correctly");
		throw;
	}
	//_debug("terminate audiortprtx ended...\n");
	_ca = 0;
	if (!_sym) {
		delete _sessionRecv; _sessionRecv = NULL;
		delete _sessionSend; _sessionSend = NULL;
	} else {
		delete _session;     _session = NULL;
	}

	delete [] _intBufferDown; _intBufferDown = NULL;
	delete [] _floatBufferUp; _floatBufferUp = NULL;
	delete [] _floatBufferDown; _floatBufferDown = NULL;
	delete [] _dataAudioLayer; _dataAudioLayer = NULL;

	delete [] _sendDataEncoded; _sendDataEncoded = NULL;
	delete [] _receiveDataDecoded; _receiveDataDecoded = NULL;

	delete time; time = NULL;

	// libsamplerate-related
	_src_state_mic  = src_delete(_src_state_mic);
	_src_state_spkr = src_delete(_src_state_spkr);
jpbl's avatar
jpbl committed
163
164
}

165
166
	void
AudioRtpRTX::initBuffers()
jpbl's avatar
jpbl committed
167
{
168
169
170
171
172
173
174
	int nbSamplesMax = (int) (_layerSampleRate * _layerFrameSize /1000);
	_dataAudioLayer = new SFLDataFormat[nbSamplesMax];
	_receiveDataDecoded = new int16[nbSamplesMax];
	_floatBufferDown  = new float32[nbSamplesMax];
	_floatBufferUp = new float32[nbSamplesMax];
	_sendDataEncoded = new unsigned char[nbSamplesMax];
	_intBufferDown = new int16[nbSamplesMax];
jpbl's avatar
jpbl committed
175
176
}

177
178
179
	void
AudioRtpRTX::initAudioRtpSession (void) 
{
180
181
182



183
184
	try {
		if (_ca == 0) { return; }
185
		_codecSampleRate = _audiocodec->getClockRate();	
186
	
Emmanuel Milou's avatar
Bug fix    
Emmanuel Milou committed
187
		_debug("Init audio RTP session\n");
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
		ost::InetHostAddress remote_ip(_ca->getRemoteIp().c_str());
		if (!remote_ip) {
			_debug("! ARTP Thread Error: Target IP address [%s] is not correct!\n", _ca->getRemoteIp().data());
			return;
		}

		// Initialization
		if (!_sym) {
			_sessionRecv->setSchedulingTimeout (10000);
			_sessionRecv->setExpireTimeout(1000000);

			_sessionSend->setSchedulingTimeout(10000);
			_sessionSend->setExpireTimeout(1000000);
		} else {
			_session->setSchedulingTimeout(10000);
			_session->setExpireTimeout(1000000);
		}

		if (!_sym) {
			if ( !_sessionRecv->addDestination(remote_ip, (unsigned short) _ca->getRemoteAudioPort()) ) {
				_debug("AudioRTP Thread Error: could not connect to port %d\n",  _ca->getRemoteAudioPort());
				return;
			}
			if (!_sessionSend->addDestination (remote_ip, (unsigned short) _ca->getRemoteAudioPort())) {
				_debug("! ARTP Thread Error: could not connect to port %d\n",  _ca->getRemoteAudioPort());
				return;
			}

			bool payloadIsSet = false;
217
218
219
			if (_audiocodec) {
				if (_audiocodec->hasDynamicPayload()) {
					payloadIsSet = _sessionRecv->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate()));
220
				} else {
221
222
					payloadIsSet= _sessionRecv->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) _audiocodec->getPayload()));
					payloadIsSet = _sessionSend->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) _audiocodec->getPayload()));
223
				}
224
225
226
227
			}
			_sessionSend->setMark(true);
		} else {

Emmanuel Milou's avatar
Bug fix    
Emmanuel Milou committed
228
			//_debug("AudioRTP Thread: Added session destination %s\n", remote_ip.getHostname() );
229
230
231
232
233
234

			if (!_session->addDestination (remote_ip, (unsigned short) _ca->getRemoteAudioPort())) {
				return;
			}

			bool payloadIsSet = false;
235
236
237
			if (_audiocodec) {
				if (_audiocodec->hasDynamicPayload()) {
					payloadIsSet = _session->setPayloadFormat(ost::DynamicPayloadFormat((ost::PayloadType) _audiocodec->getPayload(), _audiocodec->getClockRate()));
238
				} else {
239
					payloadIsSet = _session->setPayloadFormat(ost::StaticPayloadFormat((ost::StaticPayloadType) _audiocodec->getPayload()));
240
				}
241
242
243
244
245
246
247
			}
		}
	} catch(...) {
		_debugException("! ARTP Failure: initialisation failed");
		throw;
	}
}
248

249
void
250
AudioRtpRTX::loadCodec(int payload)
jpbl's avatar
jpbl committed
251
{
252
        using std::cerr;
253

254
255
	switch(payload){
	  case 0:
256
            handle_codec = dlopen( CODECS_DIR "/libcodec_ulaw.so", RTLD_LAZY);
257
258
	    break;
	  case 3:
259
	    handle_codec = dlopen(CODECS_DIR "/libcodec_gsm.so", RTLD_LAZY);
260
261
	    break;
	  case 8:
262
	    handle_codec = dlopen(CODECS_DIR "/libcodec_alaw.so", RTLD_LAZY);
263
	    break;
264
	  case 97:
265
            handle_codec = dlopen(CODECS_DIR "/libcodec_ilbc.so", RTLD_LAZY);
266
	    break;
267
268
269
	  case 110:
	    handle_codec = dlopen(CODECS_DIR "/libcodec_speex.so", RTLD_LAZY);
	    break;
270
271
	}

272
        if(!handle_codec){
273
274
275
                cerr<<"cannot load library: "<< dlerror() <<'\n';
        }
        dlerror();
276
        create_t* create_codec = (create_t*)dlsym(handle_codec, "create");
277
278
279
280
        const char* dlsym_error = dlerror();
        if(dlsym_error){
                cerr << "Cannot load symbol create: " << dlsym_error << '\n';
        }
281
282

        _audiocodec = create_codec();
283
}
284

285
void
286
AudioRtpRTX::unloadCodec()
287
288
289
290
291
292
293
{
	using std::cerr;
        destroy_t* destroy_codec = (destroy_t*)dlsym(handle_codec, "destroy");
	const char* dlsym_error = dlerror();
	if(dlsym_error){
                cerr << "Cannot load symbol destroy" << dlsym_error << '\n';
        }
294
	destroy_codec(_audiocodec);
295
	dlclose(handle_codec);
Emmanuel Milou's avatar
Emmanuel Milou committed
296
297
}

298
299
300
301
	
void
AudioRtpRTX::sendSessionFromMic(int timestamp)
{
Emmanuel Milou's avatar
Emmanuel Milou committed
302
303
304
305
306
307
308
309
310
311
312
313
314
// STEP:
//   1. get data from mic
//   2. convert it to int16 - good sample, good rate
//   3. encode it
//   4. send it
try {
	int16* toSIP = NULL;

	timestamp += time->getSecond();
	if (_ca==0) { _debug(" !ARTP: No call associated (mic)\n"); return; } // no call, so we do nothing
	AudioLayer* audiolayer = Manager::instance().getAudioDriver();
	if (!audiolayer) { _debug(" !ARTP: No audiolayer available for mic\n"); return; }

315
	if (!_audiocodec) { _debug(" !ARTP: No audiocodec available for mic\n"); return; }
Emmanuel Milou's avatar
Emmanuel Milou committed
316
317
318
319
320
321
322
323
324
325
326

	// we have to get 20ms of data from the mic *20/1000 = /50
	int maxBytesToGet = _layerSampleRate * _layerFrameSize * sizeof(SFLDataFormat) / 1000;
	// available bytes inside ringbuffer
	int availBytesFromMic = audiolayer->canGetMic();

	// take the lowest
	int bytesAvail = (availBytesFromMic < maxBytesToGet) ? availBytesFromMic : maxBytesToGet;
	// Get bytes from micRingBuffer to data_from_mic
	int nbSample = audiolayer->getMic(_dataAudioLayer, bytesAvail) / sizeof(SFLDataFormat);
	int nb_sample_up = nbSample;
327
	int nbSamplesMax = _layerFrameSize * _audiocodec->getClockRate() / 1000;
328
	
329
	nbSample = reSampleData(_audiocodec->getClockRate(), nb_sample_up, DOWN_SAMPLING);	
330
	
Emmanuel Milou's avatar
Emmanuel Milou committed
331
332
333
334
335
336
337
338
	toSIP = _intBufferDown;
	
	if ( nbSample < nbSamplesMax - 10 ) { // if only 10 is missing, it's ok
		// fill end with 0...
		//_debug("begin: %p, nbSample: %d\n", toSIP, nbSample);
		memset(toSIP + nbSample, 0, (nbSamplesMax-nbSample)*sizeof(int16));
		nbSample = nbSamplesMax;
	}
339
340
	// debug - dump sound in a file
//_debug("AR: Nb sample: %d int, [0]=%d [1]=%d [2]=%d\n", nbSample, toSIP[0], toSIP[1], toSIP[2]);
Emmanuel Milou's avatar
Emmanuel Milou committed
341
342
	// for the mono: range = 0 to RTP_FRAME2SEND * sizeof(int16)
	// codecEncode(char *dest, int16* src, size in bytes of the src)
343
	int compSize = _audiocodec->codecEncode(_sendDataEncoded, toSIP, nbSample*sizeof(int16));
344
	//printf("jusqu'ici tout vas bien\n");
345

Emmanuel Milou's avatar
Emmanuel Milou committed
346
347
348
349
350
351
352
	// encode divise by two
	// Send encoded audio sample over the network
	if (compSize > nbSamplesMax) { _debug("! ARTP: %d should be %d\n", compSize, nbSamplesMax);}
	if (!_sym) {
		_sessionSend->putData(timestamp, _sendDataEncoded, compSize);
	} else {
		_session->putData(timestamp, _sendDataEncoded, compSize);
353
	}
Emmanuel Milou's avatar
Emmanuel Milou committed
354
355
356
357
358
	toSIP = NULL;
} catch(...) {
	_debugException("! ARTP: sending failed");
	throw;
}
jpbl's avatar
jpbl committed
359
360
}

361
362


Emmanuel Milou's avatar
Emmanuel Milou committed
363
void
364
AudioRtpRTX::receiveSessionForSpkr (int& countTime)
jpbl's avatar
jpbl committed
365
{
366
367


Emmanuel Milou's avatar
Emmanuel Milou committed
368
369
370
371
if (_ca == 0) { return; }
try {
	AudioLayer* audiolayer = Manager::instance().getAudioDriver();
	if (!audiolayer) { return; }
372

Emmanuel Milou's avatar
Emmanuel Milou committed
373
374
	const ost::AppDataUnit* adu = NULL;
	// Get audio data stream
375

Emmanuel Milou's avatar
Emmanuel Milou committed
376
377
378
379
380
381
382
383
	if (!_sym) {
		adu = _sessionRecv->getData(_sessionRecv->getFirstTimestamp());
	} else {
		adu = _session->getData(_session->getFirstTimestamp());
	}
	if (adu == NULL) {
		//_debug("No RTP audio stream\n");
		return;
384
385
	}

Emmanuel Milou's avatar
Emmanuel Milou committed
386
387
	int payload = adu->getType(); // codec type
	unsigned char* data  = (unsigned char*)adu->getData(); // data in char
388
	unsigned int size = adu->getSize(); // size in char
389

Emmanuel Milou's avatar
Emmanuel Milou committed
390
	
391
	//_fstream.write((char*) data, size);
Emmanuel Milou's avatar
Emmanuel Milou committed
392
	// Decode data with relevant codec
393
	_codecSampleRate = _audiocodec->getClockRate();
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
394
	int max = (int)(_codecSampleRate * _layerFrameSize / 1000);
Emmanuel Milou's avatar
Emmanuel Milou committed
395
396
397
398
399

	if ( size > max ) {
		_debug("We have received from RTP a packet larger than expected: %s VS %s\n", size, max);
		_debug("The packet size has been cropped\n");
		size=max;
400
	}
401
402
	
	//printf("size = %i\n", size);
Emmanuel Milou's avatar
Emmanuel Milou committed
403

404
405
406
407
	if (_audiocodec != NULL) {
		
		int expandedSize = _audiocodec->codecDecode(_receiveDataDecoded, data, size);
	        //_fstream.write((char*) _receiveDataDecoded, );
Emmanuel Milou's avatar
Emmanuel Milou committed
408
409
410
411
412
413
414
		//buffer _receiveDataDecoded ----> short int or int16, coded on 2 bytes
		int nbInt16 = expandedSize / sizeof(int16);
		//nbInt16 represents the number of samples we just decoded
		if (nbInt16 > max) {
			_debug("We have decoded an RTP packet larger than expected: %s VS %s. Cropping.\n", nbInt16, max);
			nbInt16=max;
		}
415
	
Emmanuel Milou's avatar
Emmanuel Milou committed
416
417
		SFLDataFormat* toAudioLayer;
		int nbSample = nbInt16;
418

Emmanuel Milou's avatar
Emmanuel Milou committed
419
420
421
		// Do sample rate conversion
		int nb_sample_down = nbSample;
		nbSample = reSampleData(_codecSampleRate , nb_sample_down, UP_SAMPLING);
422
#ifdef DATAFORMAT_IS_FLOAT
Emmanuel Milou's avatar
Emmanuel Milou committed
423
		toAudioLayer = _floatBufferUp;
424
#else
Emmanuel Milou's avatar
Emmanuel Milou committed
425
		toAudioLayer = _dataAudioLayer;
426
427
428
#endif


Emmanuel Milou's avatar
Emmanuel Milou committed
429
		audiolayer->putMain(toAudioLayer, nbSample * sizeof(SFLDataFormat));
430

Emmanuel Milou's avatar
Emmanuel Milou committed
431
432
433
434
435
436
		// Notify (with a beep) an incoming call when there is already a call 
		countTime += time->getSecond();
		if (Manager::instance().incomingCallWaiting() > 0) {
			countTime = countTime % 500; // more often...
			if (countTime == 0) {
				Manager::instance().notificationIncomingCall();
437
438
439
			}
		}

Emmanuel Milou's avatar
Emmanuel Milou committed
440
441
	} else {
		countTime += time->getSecond();
442
	}
443

Emmanuel Milou's avatar
Emmanuel Milou committed
444
445
446
447
448
449
	delete adu; adu = NULL;
} catch(...) {
	_debugException("! ARTP: receiving failed");
	throw;
}

450

451
}
452

453
454
455
int 
AudioRtpRTX::reSampleData(int sampleRate_codec, int nbSamples, int status)
{
Emmanuel Milou's avatar
Emmanuel Milou committed
456
457
458
459
460
461
if(status==UP_SAMPLING)
	return upSampleData(sampleRate_codec, nbSamples);
else if(status==DOWN_SAMPLING)
	return downSampleData(sampleRate_codec, nbSamples);
else
	return 0;
jpbl's avatar
jpbl committed
462
463
}

464
465
466
467
////////////////////////////////////////////////////////////////////
//////////// RESAMPLING FUNCTIONS /////////////////////////////////
//////////////////////////////////////////////////////////////////

Emmanuel Milou's avatar
Emmanuel Milou committed
468
int
469
470
AudioRtpRTX::upSampleData(int sampleRate_codec, int nbSamples)
{
Emmanuel Milou's avatar
Emmanuel Milou committed
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
double upsampleFactor = (double) _layerSampleRate / sampleRate_codec;
int nbSamplesMax = (int) (_layerSampleRate * _layerFrameSize /1000);
if( upsampleFactor != 1 )
{
	SRC_DATA src_data;
	src_data.data_in = _floatBufferDown;
	src_data.data_out = _floatBufferUp;
	src_data.input_frames = nbSamples;
	src_data.output_frames = (int) floor(upsampleFactor * nbSamples);
	src_data.src_ratio = upsampleFactor;
	src_data.end_of_input = 0; // More data will come
	src_short_to_float_array(_receiveDataDecoded, _floatBufferDown, nbSamples);
	src_process(_src_state_spkr, &src_data);
	nbSamples  = ( src_data.output_frames_gen > nbSamplesMax) ? nbSamplesMax : src_data.output_frames_gen;		
	src_float_to_short_array(_floatBufferUp, _dataAudioLayer, nbSamples);
}
487

Emmanuel Milou's avatar
Emmanuel Milou committed
488
return nbSamples;
489
490
}	

Emmanuel Milou's avatar
Emmanuel Milou committed
491
int
492
493
AudioRtpRTX::downSampleData(int sampleRate_codec, int nbSamples)
{
Emmanuel Milou's avatar
Emmanuel Milou committed
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
double downsampleFactor = (double) sampleRate_codec / _layerSampleRate;
int nbSamplesMax = (int) (sampleRate_codec * _layerFrameSize / 1000);
if ( downsampleFactor != 1)
{
	SRC_DATA src_data;	
	src_data.data_in = _floatBufferUp;
	src_data.data_out = _floatBufferDown;
	src_data.input_frames = nbSamples;
	src_data.output_frames = (int) floor(downsampleFactor * nbSamples);
	src_data.src_ratio = downsampleFactor;
	src_data.end_of_input = 0; // More data will come
	src_short_to_float_array(_dataAudioLayer, _floatBufferUp, nbSamples);
	src_process(_src_state_mic, &src_data);
	nbSamples  = ( src_data.output_frames_gen > nbSamplesMax) ? nbSamplesMax : src_data.output_frames_gen;
	src_float_to_short_array(_floatBufferDown, _intBufferDown, nbSamples);
}
return nbSamples;
511
512
513
514
515

}

//////////////////////// END RESAMPLING //////////////////////////////////////////////////////

jpbl's avatar
jpbl committed
516
517
void
AudioRtpRTX::run () {
Emmanuel Milou's avatar
Emmanuel Milou committed
518
519
520
//mic, we receive from soundcard in stereo, and we send encoded
//encoding before sending
AudioLayer *audiolayer = Manager::instance().getAudioDriver();
521

Emmanuel Milou's avatar
Emmanuel Milou committed
522
523
524
_layerFrameSize = audiolayer->getFrameSize(); // en ms
_layerSampleRate = audiolayer->getSampleRate();	
initBuffers();
525
int step; 
526
loadCodec(_ca->getAudioCodec());
527

Emmanuel Milou's avatar
Emmanuel Milou committed
528
529
530
try {
	// Init the session
	initAudioRtpSession();
531
	step = (int) (_layerFrameSize * _codecSampleRate / 1000);
Emmanuel Milou's avatar
Emmanuel Milou committed
532
533
534
535
536
537
538
539
540
	// start running the packet queue scheduler.
	//_debug("AudioRTP Thread started\n");
	if (!_sym) {
		_sessionRecv->startRunning();
		_sessionSend->startRunning();
	} else {
		_session->startRunning();
		//_debug("Session is now: %d active\n", _session->isActive());
	}
541

Emmanuel Milou's avatar
Emmanuel Milou committed
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
	int timestamp = 0; // for mic
	int countTime = 0; // for receive
	TimerPort::setTimer(_layerFrameSize);

	audiolayer->flushMic();
	audiolayer->startStream();
	_start.post();
	_debug("- ARTP Action: Start\n");
	while (!testCancel()) {
		////////////////////////////
		// Send session
		////////////////////////////
		sendSessionFromMic(timestamp);
		timestamp += step;
		////////////////////////////
		// Recv session
		////////////////////////////
		receiveSessionForSpkr(countTime);
		// Let's wait for the next transmit cycle
		Thread::sleep(TimerPort::getTimer());
		TimerPort::incTimer(_layerFrameSize); // 'frameSize' ms
563
	}
Emmanuel Milou's avatar
nothing    
Emmanuel Milou committed
564
	_fstream.close();
565
 	unloadCodec();
Emmanuel Milou's avatar
Emmanuel Milou committed
566
567
568
569
570
571
572
573
574
575
576
	//_debug("stop stream for audiortp loop\n");
	audiolayer->stopStream();
} catch(std::exception &e) {
	_start.post();
	_debug("! ARTP: Stop %s\n", e.what());
	throw;
} catch(...) {
	_start.post();
	_debugException("* ARTP Action: Stop");
	throw;
}
jpbl's avatar
jpbl committed
577
578
579
580
}


// EOF