@babblevoice/projectrtp 2.4.8 → 2.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -75,7 +75,7 @@ void projectchannelmux::mixall( void ) {
|
|
|
75
75
|
this->postrtpdata( chan, dtmfchan, src );
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
-
|
|
78
|
+
/* remove the DTMF packet */
|
|
79
79
|
AQUIRESPINLOCK( chan->rtpbufferlock );
|
|
80
80
|
chan->inbuff->poppeeked();
|
|
81
81
|
RELEASESPINLOCK( chan->rtpbufferlock );
|
|
@@ -94,7 +94,7 @@ void projectchannelmux::mixall( void ) {
|
|
|
94
94
|
|
|
95
95
|
rtppacket *dst = chan->gettempoutbuf();
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
/* start with a direct copy */
|
|
98
98
|
this->subtracted.copy( this->added );
|
|
99
99
|
|
|
100
100
|
if( chan->recv ) {
|
package/src/projectrtpcodecx.cpp
CHANGED
|
@@ -141,8 +141,7 @@ void codecx::reset()
|
|
|
141
141
|
## restart
|
|
142
142
|
Do enough to manage missing packets.
|
|
143
143
|
*/
|
|
144
|
-
void codecx::restart( void )
|
|
145
|
-
{
|
|
144
|
+
void codecx::restart( void ) {
|
|
146
145
|
this->lpfilter.reset();
|
|
147
146
|
this->dcpowerfilter.reset();
|
|
148
147
|
this->resamplelastsample = 0;
|
|
@@ -154,8 +153,7 @@ void codecx::restart( void )
|
|
|
154
153
|
|
|
155
154
|
From whichever PCM encoding (u or a) encode to the other without having to do intermediate l16.
|
|
156
155
|
*/
|
|
157
|
-
bool codecx::alaw2ulaw( void )
|
|
158
|
-
{
|
|
156
|
+
bool codecx::alaw2ulaw( void ) {
|
|
159
157
|
if( 0 == this->pcmaref.size() ) return false;
|
|
160
158
|
if( this->pcmaref.isdirty() ) return false;
|
|
161
159
|
|
|
@@ -167,23 +165,22 @@ bool codecx::alaw2ulaw( void )
|
|
|
167
165
|
outbufptr = this->pcmuref.c_str();
|
|
168
166
|
this->pcmuref.size( insize );
|
|
169
167
|
|
|
170
|
-
if( nullptr == outbufptr || nullptr == inbufptr )
|
|
171
|
-
{
|
|
168
|
+
if( nullptr == outbufptr || nullptr == inbufptr ) {
|
|
172
169
|
std::cerr << "PCMA NULLPTR shouldn't happen (" << (void*)outbufptr << ", " << (void*)inbufptr << ")" << std::endl;
|
|
173
170
|
return false;
|
|
174
171
|
}
|
|
175
172
|
|
|
176
|
-
for( size_t i = 0; i < insize; i++ )
|
|
177
|
-
|
|
178
|
-
|
|
173
|
+
for( size_t i = 0; i < insize; i++ ) {
|
|
174
|
+
*outbufptr = alaw_to_ulaw_table[ *inbufptr ];
|
|
175
|
+
inbufptr++;
|
|
176
|
+
outbufptr++;
|
|
179
177
|
}
|
|
180
178
|
|
|
181
179
|
this->pcmuref.dirty( false );
|
|
182
180
|
return true;
|
|
183
181
|
}
|
|
184
182
|
|
|
185
|
-
bool codecx::ulaw2alaw( void )
|
|
186
|
-
{
|
|
183
|
+
bool codecx::ulaw2alaw( void ) {
|
|
187
184
|
if( 0 == this->pcmuref.size() ) return false;
|
|
188
185
|
if( this->pcmuref.isdirty() ) return false;
|
|
189
186
|
|
|
@@ -195,15 +192,15 @@ bool codecx::ulaw2alaw( void )
|
|
|
195
192
|
outbufptr = this->pcmaref.c_str();
|
|
196
193
|
this->pcmaref.size( insize );
|
|
197
194
|
|
|
198
|
-
if( nullptr == outbufptr || nullptr == inbufptr )
|
|
199
|
-
{
|
|
195
|
+
if( nullptr == outbufptr || nullptr == inbufptr ) {
|
|
200
196
|
std::cerr << "PCMU NULLPTR shouldn't happen(" << (void*)outbufptr << ", " << (void*)inbufptr << ")" << std::endl;
|
|
201
197
|
return false;
|
|
202
198
|
}
|
|
203
199
|
|
|
204
|
-
for( size_t i = 0; i < insize; i++ )
|
|
205
|
-
|
|
206
|
-
|
|
200
|
+
for( size_t i = 0; i < insize; i++ ) {
|
|
201
|
+
*outbufptr = ulaw_to_alaw_table[ *inbufptr ];
|
|
202
|
+
inbufptr++;
|
|
203
|
+
outbufptr++;
|
|
207
204
|
}
|
|
208
205
|
|
|
209
206
|
this->pcmaref.dirty( false );
|
|
@@ -220,20 +217,15 @@ bool codecx::g711tol16( void )
|
|
|
220
217
|
int16_t *convert;
|
|
221
218
|
size_t insize;
|
|
222
219
|
|
|
223
|
-
if( this->pcmaref.size() > 0 && !this->pcmaref.isdirty() )
|
|
224
|
-
{
|
|
220
|
+
if( this->pcmaref.size() > 0 && !this->pcmaref.isdirty() ) {
|
|
225
221
|
in = this->pcmaref.c_str();
|
|
226
222
|
convert = _pcmatol16;
|
|
227
223
|
insize = this->pcmaref.size();
|
|
228
|
-
}
|
|
229
|
-
else if ( this->pcmuref.size() > 0 && !this->pcmuref.isdirty() )
|
|
230
|
-
{
|
|
224
|
+
} else if ( this->pcmuref.size() > 0 && !this->pcmuref.isdirty() ) {
|
|
231
225
|
in = this->pcmuref.c_str();
|
|
232
226
|
convert = _pcmutol16;
|
|
233
227
|
insize = this->pcmuref.size();
|
|
234
|
-
}
|
|
235
|
-
else
|
|
236
|
-
{
|
|
228
|
+
} else {
|
|
237
229
|
return false;
|
|
238
230
|
}
|
|
239
231
|
|
|
@@ -241,9 +233,10 @@ bool codecx::g711tol16( void )
|
|
|
241
233
|
|
|
242
234
|
int16_t *out = ( int16_t * ) this->l168kref.c_str();
|
|
243
235
|
|
|
244
|
-
for( size_t i = 0; i < insize; i++ )
|
|
245
|
-
|
|
246
|
-
|
|
236
|
+
for( size_t i = 0; i < insize; i++ ) {
|
|
237
|
+
*out = convert[ *in ];
|
|
238
|
+
in++;
|
|
239
|
+
out++;
|
|
247
240
|
}
|
|
248
241
|
|
|
249
242
|
this->l168kref.dirty( false );
|
|
@@ -265,9 +258,12 @@ bool codecx::l16topcma( void )
|
|
|
265
258
|
size_t l168klength = this->l168kref.size();
|
|
266
259
|
in = ( int16_t * ) this->l168kref.c_str();
|
|
267
260
|
|
|
268
|
-
|
|
269
|
-
{
|
|
270
|
-
|
|
261
|
+
uint16_t index;
|
|
262
|
+
for( size_t i = 0; i < l168klength; i++ ) {
|
|
263
|
+
index = *in + 32768;
|
|
264
|
+
*out = _l16topcma[ index ];
|
|
265
|
+
in++;
|
|
266
|
+
out++;
|
|
271
267
|
}
|
|
272
268
|
this->pcmaref.dirty( false );
|
|
273
269
|
return true;
|
|
@@ -276,8 +272,7 @@ bool codecx::l16topcma( void )
|
|
|
276
272
|
/*!md
|
|
277
273
|
## l16topcmu
|
|
278
274
|
*/
|
|
279
|
-
bool codecx::l16topcmu( void )
|
|
280
|
-
{
|
|
275
|
+
bool codecx::l16topcmu( void ) {
|
|
281
276
|
if( 0 == this->l168kref.size() ) return false;
|
|
282
277
|
if( this->l168kref.isdirty() ) return false;
|
|
283
278
|
|
|
@@ -287,9 +282,12 @@ bool codecx::l16topcmu( void )
|
|
|
287
282
|
size_t l168klength = this->l168kref.size();
|
|
288
283
|
in = ( int16_t * ) this->l168kref.c_str();
|
|
289
284
|
|
|
290
|
-
|
|
291
|
-
{
|
|
292
|
-
|
|
285
|
+
uint16_t index;
|
|
286
|
+
for( size_t i = 0; i < l168klength; i++ ) {
|
|
287
|
+
index = *in + 32768;
|
|
288
|
+
*out = _l16topcmu[ index ];
|
|
289
|
+
in++;
|
|
290
|
+
out++;
|
|
293
291
|
}
|
|
294
292
|
this->pcmuref.dirty( false );
|
|
295
293
|
return true;
|
|
@@ -299,8 +297,7 @@ bool codecx::l16topcmu( void )
|
|
|
299
297
|
## ilbctol16
|
|
300
298
|
As it says.
|
|
301
299
|
*/
|
|
302
|
-
bool codecx::ilbctol16( void )
|
|
303
|
-
{
|
|
300
|
+
bool codecx::ilbctol16( void ) {
|
|
304
301
|
if( 0 == this->ilbcref.size() ) return false;
|
|
305
302
|
if( this->ilbcref.isdirty() ) return false;
|
|
306
303
|
|
|
@@ -335,25 +332,20 @@ bool codecx::ilbctol16( void )
|
|
|
335
332
|
## l16tog722
|
|
336
333
|
As it says.
|
|
337
334
|
*/
|
|
338
|
-
bool codecx::l16tog722( void )
|
|
339
|
-
{
|
|
335
|
+
bool codecx::l16tog722( void ) {
|
|
340
336
|
if( 0 == this->l1616kref.size() ) return false;
|
|
341
337
|
if( this->l1616kref.isdirty() ) return false;
|
|
342
338
|
|
|
343
|
-
if( nullptr == this->g722encoder )
|
|
344
|
-
{
|
|
339
|
+
if( nullptr == this->g722encoder ) {
|
|
345
340
|
this->g722encoder = g722_encode_init( NULL, 64000, G722_PACKED );
|
|
346
341
|
}
|
|
347
342
|
|
|
348
343
|
int len = g722_encode( this->g722encoder, this->g722ref.c_str(), ( int16_t * ) this->l1616kref.c_str(), this->g722ref.size() * 2 );
|
|
349
344
|
|
|
350
|
-
if( len > 0 )
|
|
351
|
-
{
|
|
345
|
+
if( len > 0 ) {
|
|
352
346
|
this->g722ref.size( len );
|
|
353
347
|
this->g722ref.dirty( false );
|
|
354
|
-
}
|
|
355
|
-
else
|
|
356
|
-
{
|
|
348
|
+
} else {
|
|
357
349
|
std::cerr << "g722_encode didn't encode any data" << std::endl;
|
|
358
350
|
this->g722ref.size( 0 );
|
|
359
351
|
}
|
|
@@ -400,19 +392,16 @@ bool codecx::l16toilbc( void ) {
|
|
|
400
392
|
## g722tol16
|
|
401
393
|
As it says.
|
|
402
394
|
*/
|
|
403
|
-
bool codecx::g722tol16( void )
|
|
404
|
-
{
|
|
395
|
+
bool codecx::g722tol16( void ) {
|
|
405
396
|
if( 0 == this->g722ref.size() ) return false;
|
|
406
397
|
if( this->g722ref.isdirty() ) return false;
|
|
407
398
|
|
|
408
399
|
/* x 2 for 16 bit instead of 8 and then x 2 sample rate */
|
|
409
400
|
this->l1616kref.malloc( this->g722ref.size(), sizeof( int16_t ), L1616KPAYLOADTYPE );
|
|
410
401
|
|
|
411
|
-
if( nullptr == this->g722decoder )
|
|
412
|
-
{
|
|
402
|
+
if( nullptr == this->g722decoder ) {
|
|
413
403
|
this->g722decoder = g722_decode_init( NULL, 64000, G722_PACKED );
|
|
414
|
-
if( nullptr == this->g722decoder )
|
|
415
|
-
{
|
|
404
|
+
if( nullptr == this->g722decoder ) {
|
|
416
405
|
std::cerr << "Failed to init G722 decoder" << std::endl;
|
|
417
406
|
}
|
|
418
407
|
}
|
|
@@ -431,8 +420,7 @@ bool codecx::g722tol16( void )
|
|
|
431
420
|
## l16lowtowideband
|
|
432
421
|
Upsample from narrow to wideband. Take each point and interpolate between them. We require the final sample from the last packet to continue the interpolating.
|
|
433
422
|
*/
|
|
434
|
-
bool codecx::l16lowtowideband( void )
|
|
435
|
-
{
|
|
423
|
+
bool codecx::l16lowtowideband( void ) {
|
|
436
424
|
size_t l168klength = this->l168kref.size();
|
|
437
425
|
|
|
438
426
|
if( 0 == l168klength ) return false;
|
|
@@ -443,8 +431,7 @@ bool codecx::l16lowtowideband( void )
|
|
|
443
431
|
int16_t *in = ( int16_t * ) this->l168kref.c_str();
|
|
444
432
|
int16_t *out = ( int16_t * ) this->l1616kref.c_str();
|
|
445
433
|
|
|
446
|
-
for( size_t i = 0; i < l168klength; i++ )
|
|
447
|
-
{
|
|
434
|
+
for( size_t i = 0; i < l168klength; i++ ) {
|
|
448
435
|
*out = ( ( *in - this->resamplelastsample ) / 2 ) + this->resamplelastsample;
|
|
449
436
|
this->resamplelastsample = *in;
|
|
450
437
|
out++;
|
|
@@ -463,8 +450,7 @@ bool codecx::l16lowtowideband( void )
|
|
|
463
450
|
## requirewideband
|
|
464
451
|
Search for the relevent data and convert as necessary.
|
|
465
452
|
*/
|
|
466
|
-
bool codecx::requirewideband( void )
|
|
467
|
-
{
|
|
453
|
+
bool codecx::requirewideband( void ) {
|
|
468
454
|
if( 0 != this->l1616kref.size() && !this->l1616kref.isdirty() ) return true;
|
|
469
455
|
if( this->g722tol16() ) return true;
|
|
470
456
|
if( !this->g711tol16() )
|
|
@@ -491,10 +477,12 @@ bool codecx::l16widetonarrowband( void )
|
|
|
491
477
|
int16_t *out = ( int16_t * ) this->l168kref.c_str();
|
|
492
478
|
int16_t *in = ( int16_t * ) this->l1616kref.c_str();
|
|
493
479
|
|
|
494
|
-
for( size_t i = 0; i < l1616klength / 2; i++ )
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
*out
|
|
480
|
+
for( size_t i = 0; i < l1616klength / 2; i++ ) {
|
|
481
|
+
lpfilter.execute( *in );
|
|
482
|
+
in++;
|
|
483
|
+
*out = lpfilter.execute( *in );
|
|
484
|
+
in++;
|
|
485
|
+
out++;
|
|
498
486
|
}
|
|
499
487
|
|
|
500
488
|
this->l168kref.dirty( false );
|
|
@@ -820,6 +808,18 @@ void codectests( void )
|
|
|
820
808
|
|
|
821
809
|
#ifdef NODE_MODULE
|
|
822
810
|
|
|
811
|
+
static napi_value codectest( napi_env env, napi_callback_info info ) {
|
|
812
|
+
napi_value result;
|
|
813
|
+
if( napi_ok != napi_create_object( env, &result ) ) return NULL;
|
|
814
|
+
|
|
815
|
+
codectests();
|
|
816
|
+
|
|
817
|
+
napi_create_uint32( env, 1, &result );
|
|
818
|
+
napi_coerce_to_bool( env, result, &result );
|
|
819
|
+
|
|
820
|
+
return result;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
823
|
/*
|
|
824
824
|
Support single number just for now - but TODO detect Buffer input to convert whole bufffer.
|
|
825
825
|
*/
|
|
@@ -929,6 +929,9 @@ void initrtpcodecx( napi_env env, napi_value &result ) {
|
|
|
929
929
|
|
|
930
930
|
if( napi_ok != napi_create_function( env, "exports", NAPI_AUTO_LENGTH, pcmu2linear, nullptr, &funct ) ) return;
|
|
931
931
|
if( napi_ok != napi_set_named_property( env, codecx, "pcmu2linear16", funct ) ) return;
|
|
932
|
+
|
|
933
|
+
if( napi_ok != napi_create_function( env, "exports", NAPI_AUTO_LENGTH, codectest, nullptr, &funct ) ) return;
|
|
934
|
+
if( napi_ok != napi_set_named_property( env, codecx, "codectests", funct ) ) return;
|
|
932
935
|
}
|
|
933
936
|
|
|
934
937
|
#endif /* NODE_MODULE */
|
|
@@ -298,36 +298,24 @@ describe( "dtls", function() {
|
|
|
298
298
|
it( "Connect then remote to another session", async function() {
|
|
299
299
|
|
|
300
300
|
/*
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
301
|
+
Play, then encrypt at one end, then unencrypt in projectrtp and send onto d
|
|
302
|
+
Create an e channel so that we mix 3
|
|
303
|
+
|
|
304
|
+
| internal |
|
|
305
|
+
channel channel channel channel
|
|
306
|
+
a RTP over DTLS -----------b c RTP d
|
|
307
|
+
play b mix c echo
|
|
308
|
+
mix e f
|
|
309
|
+
echo
|
|
310
310
|
|
|
311
311
|
*/
|
|
312
312
|
|
|
313
313
|
this.timeout( 6000 )
|
|
314
314
|
this.slow( 2500 )
|
|
315
315
|
|
|
316
|
-
projectrtp.tone.generate( "400+450*0.
|
|
316
|
+
projectrtp.tone.generate( "400+450*0.25/0/400+450*0.25/0:400/200/400/2000", "/tmp/ukringing.wav" )
|
|
317
317
|
|
|
318
|
-
const
|
|
319
|
-
"address": "localhost",
|
|
320
|
-
"port": 0,
|
|
321
|
-
"codec": 0,
|
|
322
|
-
"dtls": {
|
|
323
|
-
"fingerprint": {
|
|
324
|
-
"hash": ""
|
|
325
|
-
},
|
|
326
|
-
"mode": "active" // - is this in the right place and the right way round!
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
const channeltargetc = {
|
|
318
|
+
const targeta = {
|
|
331
319
|
"address": "localhost",
|
|
332
320
|
"port": 0,
|
|
333
321
|
"codec": 0,
|
|
@@ -335,36 +323,23 @@ describe( "dtls", function() {
|
|
|
335
323
|
"fingerprint": {
|
|
336
324
|
"hash": ""
|
|
337
325
|
},
|
|
338
|
-
"mode": "active"
|
|
326
|
+
"mode": "active"
|
|
339
327
|
}
|
|
340
328
|
}
|
|
341
329
|
|
|
342
|
-
const
|
|
343
|
-
"address": "localhost",
|
|
344
|
-
"port": 12008,
|
|
345
|
-
"codec": 0,
|
|
346
|
-
"dtls": {
|
|
347
|
-
"fingerprint": {
|
|
348
|
-
"hash": ""
|
|
349
|
-
},
|
|
350
|
-
"mode": "passive"
|
|
351
|
-
}
|
|
352
|
-
}
|
|
330
|
+
const targetb = JSON.parse( JSON.stringify( targeta ) )
|
|
353
331
|
|
|
354
|
-
const
|
|
332
|
+
const targetc = {
|
|
355
333
|
"address": "localhost",
|
|
356
334
|
"port": 0,
|
|
357
335
|
"codec": 0
|
|
358
336
|
}
|
|
359
|
-
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
"port": 12010,
|
|
363
|
-
"codec": 0
|
|
364
|
-
}
|
|
337
|
+
const targetd = JSON.parse( JSON.stringify( targetc ) )
|
|
338
|
+
const targete = JSON.parse( JSON.stringify( targetc ) )
|
|
339
|
+
const targetf = JSON.parse( JSON.stringify( targetc ) )
|
|
365
340
|
|
|
366
341
|
let done
|
|
367
|
-
const finished = new Promise( (
|
|
342
|
+
const finished = new Promise( ( resolve ) => { done = resolve } )
|
|
368
343
|
|
|
369
344
|
const channela = await projectrtp.openchannel( {}, function( d ) {
|
|
370
345
|
if( "close" === d.action ) {
|
|
@@ -372,57 +347,66 @@ describe( "dtls", function() {
|
|
|
372
347
|
}
|
|
373
348
|
} )
|
|
374
349
|
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
clienttargeta.port = channela.local.port
|
|
381
|
-
clienttargeta.dtls.fingerprint.hash = channela.local.dtls.fingerprint
|
|
382
|
-
expect( clienta.remote( clienttargeta ) ).to.be.true
|
|
383
|
-
|
|
384
|
-
clienta.play( { "loop": true, "files": [
|
|
385
|
-
{ "wav": "/tmp/ukringing.wav" } ] } )
|
|
350
|
+
const channelb = await projectrtp.openchannel( {}, function( d ) {
|
|
351
|
+
if( "close" === d.action ) {
|
|
352
|
+
channelc.close()
|
|
353
|
+
}
|
|
354
|
+
} )
|
|
386
355
|
|
|
356
|
+
const channelc = await projectrtp.openchannel( {}, function( d ) {
|
|
357
|
+
if( "close" === d.action ) {
|
|
358
|
+
channeld.close()
|
|
359
|
+
}
|
|
360
|
+
} )
|
|
387
361
|
|
|
388
|
-
const
|
|
362
|
+
const channeld = await projectrtp.openchannel( {}, function( d ) {
|
|
389
363
|
if( "close" === d.action ) {
|
|
390
|
-
|
|
364
|
+
channele.close()
|
|
391
365
|
}
|
|
392
366
|
} )
|
|
393
367
|
|
|
394
|
-
const
|
|
368
|
+
const channele = await projectrtp.openchannel( {}, function( d ) {
|
|
395
369
|
if( "close" === d.action ) {
|
|
396
|
-
|
|
370
|
+
channelf.close()
|
|
397
371
|
}
|
|
398
372
|
} )
|
|
399
373
|
|
|
400
|
-
let
|
|
401
|
-
const
|
|
374
|
+
let channelclose = {}
|
|
375
|
+
const channelf = await projectrtp.openchannel( {}, function( d ) {
|
|
402
376
|
if( "close" === d.action ) {
|
|
403
|
-
|
|
377
|
+
channelclose = d
|
|
404
378
|
done()
|
|
405
379
|
}
|
|
406
380
|
} )
|
|
407
381
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
382
|
+
targeta.dtls.fingerprint.hash = channelb.local.dtls.fingerprint
|
|
383
|
+
targeta.port = channelb.local.port
|
|
384
|
+
expect( channela.remote( targeta ) ).to.be.true
|
|
385
|
+
targetb.port = channela.local.port
|
|
386
|
+
targetb.dtls.fingerprint.hash = channela.local.dtls.fingerprint
|
|
387
|
+
targetb.dtls.mode = "passive"
|
|
388
|
+
expect( channelb.remote( targetb ) ).to.be.true
|
|
415
389
|
|
|
416
|
-
|
|
390
|
+
targetc.port = channeld.local.port
|
|
391
|
+
expect( channelc.remote( targetc ) ).to.be.true
|
|
392
|
+
targetd.port = channelc.local.port
|
|
393
|
+
expect( channeld.remote( targetd ) ).to.be.true
|
|
417
394
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
expect(
|
|
395
|
+
targete.port = channelf.local.port
|
|
396
|
+
expect( channele.remote( targete ) ).to.be.true
|
|
397
|
+
targetf.port = channele.local.port
|
|
398
|
+
expect( channelf.remote( targetf ) ).to.be.true
|
|
422
399
|
|
|
423
|
-
|
|
400
|
+
/* play on one end */
|
|
401
|
+
channela.play( { "loop": true, "files": [
|
|
424
402
|
{ "wav": "/tmp/ukringing.wav" } ] } )
|
|
425
|
-
|
|
403
|
+
|
|
404
|
+
/* mix in the middle */
|
|
405
|
+
channelb.mix( channelc )
|
|
406
|
+
channelb.mix( channele )
|
|
407
|
+
|
|
408
|
+
/* echo at the other end */
|
|
409
|
+
expect( channeld.echo() ).to.be.true
|
|
426
410
|
|
|
427
411
|
await new Promise( ( r ) => { setTimeout( () => r(), 1500 ) } )
|
|
428
412
|
|
|
@@ -431,8 +415,8 @@ describe( "dtls", function() {
|
|
|
431
415
|
await fs.promises.unlink( "/tmp/ukringing.wav" ).catch( () => {} )
|
|
432
416
|
await finished
|
|
433
417
|
|
|
434
|
-
expect(
|
|
435
|
-
expect(
|
|
418
|
+
expect( channelclose.stats.in.count ).to.be.above( 30 )
|
|
419
|
+
expect( channelclose.stats.in.skip ).to.be.below( 2 ) // allow a little loss in test
|
|
436
420
|
|
|
437
421
|
} )
|
|
438
422
|
} )
|
|
@@ -432,6 +432,69 @@ describe( "channel mix", function() {
|
|
|
432
432
|
|
|
433
433
|
} )
|
|
434
434
|
|
|
435
|
+
it( "mix 2 channels - pcmu <-> g722 with recording", async function() {
|
|
436
|
+
|
|
437
|
+
this.timeout( 3000 )
|
|
438
|
+
this.slow( 2000 )
|
|
439
|
+
|
|
440
|
+
const endpointa = dgram.createSocket( "udp4" )
|
|
441
|
+
const endpointb = dgram.createSocket( "udp4" )
|
|
442
|
+
|
|
443
|
+
let endpointapkcount = 0
|
|
444
|
+
let endpointbpkcount = 0
|
|
445
|
+
|
|
446
|
+
endpointa.on( "message", function( msg ) {
|
|
447
|
+
endpointapkcount++
|
|
448
|
+
expect( 0x7f & msg [ 1 ] ).to.equal( 0 )
|
|
449
|
+
} )
|
|
450
|
+
|
|
451
|
+
endpointb.on( "message", function( msg ) {
|
|
452
|
+
|
|
453
|
+
endpointbpkcount++
|
|
454
|
+
expect( 0x7f & msg [ 1 ] ).to.equal( 9 )
|
|
455
|
+
endpointb.send( msg, channelb.local.port, "localhost" )
|
|
456
|
+
} )
|
|
457
|
+
|
|
458
|
+
endpointa.bind()
|
|
459
|
+
await new Promise( ( resolve ) => { endpointa.on( "listening", function() { resolve() } ) } )
|
|
460
|
+
|
|
461
|
+
endpointb.bind()
|
|
462
|
+
await new Promise( ( resolve ) => { endpointb.on( "listening", function() { resolve() } ) } )
|
|
463
|
+
|
|
464
|
+
let done
|
|
465
|
+
const finished = new Promise( ( r ) => { done = r } )
|
|
466
|
+
|
|
467
|
+
const channela = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": endpointa.address().port, "codec": 0 } }, function( d ) {
|
|
468
|
+
if( "close" === d.action ) channelb.close()
|
|
469
|
+
} )
|
|
470
|
+
|
|
471
|
+
const channelb = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": endpointb.address().port, "codec": 9 } }, function( d ) {
|
|
472
|
+
if( "close" === d.action ) done()
|
|
473
|
+
} )
|
|
474
|
+
|
|
475
|
+
/* mix */
|
|
476
|
+
expect( channela.mix( channelb ) ).to.be.true
|
|
477
|
+
|
|
478
|
+
channela.record( { "file": "/tmp/g722mix2recording.wav" } )
|
|
479
|
+
|
|
480
|
+
/* Now, when we send UDP on endpointb it passes through our mix then arrives at endpointa */
|
|
481
|
+
for( let i = 0; 50 > i; i ++ ) {
|
|
482
|
+
sendpk( i, i, channela.local.port, endpointa )
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
await new Promise( ( resolve ) => { setTimeout( () => resolve(), 1500 ) } )
|
|
486
|
+
|
|
487
|
+
channela.close()
|
|
488
|
+
endpointa.close()
|
|
489
|
+
endpointb.close()
|
|
490
|
+
|
|
491
|
+
expect( endpointapkcount ).to.be.above( 30 )
|
|
492
|
+
expect( endpointbpkcount ).to.be.above( 30 )
|
|
493
|
+
|
|
494
|
+
await finished
|
|
495
|
+
|
|
496
|
+
} )
|
|
497
|
+
|
|
435
498
|
it( "mix 3 channels - 1 writer 3 readers", async function() {
|
|
436
499
|
|
|
437
500
|
this.timeout( 3000 )
|