@babblevoice/projectrtp 2.4.12 → 2.4.16
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
|
@@ -121,11 +121,13 @@ projectrtpchannel::projectrtpchannel( unsigned short port ):
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
void projectrtpchannel::requestclose( std::string reason ) {
|
|
124
|
-
if( !this->_requestclose.exchange( true, std::memory_order_acquire ) ) {
|
|
125
|
-
this->closereason = reason;
|
|
126
|
-
}
|
|
127
124
|
|
|
128
|
-
this->
|
|
125
|
+
this->closereason = reason;
|
|
126
|
+
if( this->mixing ) {
|
|
127
|
+
this->removemixer = true;
|
|
128
|
+
} else {
|
|
129
|
+
this->_requestclose.exchange( true, std::memory_order_acquire );
|
|
130
|
+
}
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
void projectrtpchannel::remote( std::string address,
|
|
@@ -390,6 +392,11 @@ void projectrtpchannel::handletick( const boost::system::error_code& error ) {
|
|
|
390
392
|
if( error == boost::asio::error::operation_aborted ) return;
|
|
391
393
|
if( !this->active ) return;
|
|
392
394
|
|
|
395
|
+
if( this->_requestclose ) {
|
|
396
|
+
this->doclose();
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
393
400
|
if( this->dtlsnegotiate() ) {
|
|
394
401
|
this->setnexttick();
|
|
395
402
|
return;
|
|
@@ -400,11 +407,6 @@ void projectrtpchannel::handletick( const boost::system::error_code& error ) {
|
|
|
400
407
|
return;
|
|
401
408
|
};
|
|
402
409
|
|
|
403
|
-
if( this->_requestclose ) {
|
|
404
|
-
this->doclose();
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
410
|
this->startticktimer();
|
|
409
411
|
|
|
410
412
|
this->incrtsout();
|
|
@@ -1025,21 +1027,20 @@ bool projectrtpchannel::mix( projectrtpchannel::pointer other ) {
|
|
|
1025
1027
|
if( nullptr == this->mixer && nullptr != other->mixer ) {
|
|
1026
1028
|
this->mixer = other->mixer;
|
|
1027
1029
|
this->mixer->addchannel( shared_from_this() );
|
|
1028
|
-
|
|
1030
|
+
|
|
1029
1031
|
} else if ( nullptr != this->mixer && nullptr == other->mixer ) {
|
|
1030
1032
|
other->mixer = this->mixer;
|
|
1031
1033
|
this->mixer->addchannel( other );
|
|
1032
|
-
|
|
1034
|
+
|
|
1033
1035
|
} else if( nullptr == this->mixer && nullptr == other->mixer ) {
|
|
1034
1036
|
this->mixer = projectchannelmux::create( workercontext );
|
|
1035
1037
|
other->mixer = this->mixer;
|
|
1036
1038
|
|
|
1037
1039
|
this->mixer->addchannels( shared_from_this(), other );
|
|
1038
|
-
postdatabacktojsfromthread( shared_from_this(), "mix", "start" );
|
|
1039
|
-
postdatabacktojsfromthread( other, "mix", "start" );
|
|
1040
1040
|
} else {
|
|
1041
1041
|
/* If we get here this and other are already mixing and should be cleaned up first */
|
|
1042
1042
|
RELEASESPINLOCK( this->mixerlock );
|
|
1043
|
+
postdatabacktojsfromthread( shared_from_this(), "mix", "busy" );
|
|
1043
1044
|
return false;
|
|
1044
1045
|
}
|
|
1045
1046
|
|
|
@@ -1050,6 +1051,9 @@ bool projectrtpchannel::mix( projectrtpchannel::pointer other ) {
|
|
|
1050
1051
|
|
|
1051
1052
|
RELEASESPINLOCK( this->mixerlock );
|
|
1052
1053
|
|
|
1054
|
+
postdatabacktojsfromthread( shared_from_this(), "mix", "start" );
|
|
1055
|
+
postdatabacktojsfromthread( other, "mix", "start" );
|
|
1056
|
+
|
|
1053
1057
|
return true;
|
|
1054
1058
|
}
|
|
1055
1059
|
|
|
@@ -1059,7 +1063,11 @@ Add the other to a mixer - both channels have access to the same mixer.
|
|
|
1059
1063
|
n way relationship. Adds to queue for when our main thread calls into us.
|
|
1060
1064
|
*/
|
|
1061
1065
|
bool projectrtpchannel::unmix( void ) {
|
|
1062
|
-
|
|
1066
|
+
|
|
1067
|
+
AQUIRESPINLOCK( this->mixerlock );
|
|
1068
|
+
if( nullptr != this->mixer ) this->removemixer = true;
|
|
1069
|
+
RELEASESPINLOCK( this->mixerlock );
|
|
1070
|
+
|
|
1063
1071
|
return true;
|
|
1064
1072
|
}
|
|
1065
1073
|
|
|
@@ -1075,6 +1083,10 @@ void projectrtpchannel::dounmix( void ) {
|
|
|
1075
1083
|
RELEASESPINLOCK( this->mixerlock );
|
|
1076
1084
|
|
|
1077
1085
|
postdatabacktojsfromthread( shared_from_this(), "mix", "finished" );
|
|
1086
|
+
|
|
1087
|
+
if( this->closereason.length() > 0 ) {
|
|
1088
|
+
this->_requestclose.exchange( true, std::memory_order_acquire );
|
|
1089
|
+
}
|
|
1078
1090
|
}
|
|
1079
1091
|
|
|
1080
1092
|
/*
|
package/src/projectrtpcodecx.cpp
CHANGED
|
@@ -559,7 +559,7 @@ rawsound& codecx::getref( int pt ) {
|
|
|
559
559
|
}
|
|
560
560
|
case PCMAPAYLOADTYPE: {
|
|
561
561
|
if( this->pcmuref.size() > 0 ) {
|
|
562
|
-
this->
|
|
562
|
+
this->ulaw2alaw();
|
|
563
563
|
} else {
|
|
564
564
|
this->requirenarrowband();
|
|
565
565
|
this->l16topcma();
|
|
@@ -568,7 +568,7 @@ rawsound& codecx::getref( int pt ) {
|
|
|
568
568
|
}
|
|
569
569
|
case PCMUPAYLOADTYPE: {
|
|
570
570
|
if( this->pcmaref.size() > 0 ) {
|
|
571
|
-
this->
|
|
571
|
+
this->alaw2ulaw();
|
|
572
572
|
} else {
|
|
573
573
|
this->requirenarrowband();
|
|
574
574
|
this->l16topcmu();
|
|
@@ -697,8 +697,7 @@ codecx& operator << ( codecx& c, const char& a )
|
|
|
697
697
|
|
|
698
698
|
|
|
699
699
|
|
|
700
|
-
void codectests( void )
|
|
701
|
-
{
|
|
700
|
+
void codectests( void ) {
|
|
702
701
|
/* init transcoding stuff */
|
|
703
702
|
gen711convertdata();
|
|
704
703
|
|
|
@@ -715,8 +714,7 @@ void codectests( void )
|
|
|
715
714
|
|
|
716
715
|
|
|
717
716
|
g722_decode_state_t *g722decoder = g722_decode_init( NULL, 64000, G722_PACKED );
|
|
718
|
-
if( nullptr == g722decoder )
|
|
719
|
-
{
|
|
717
|
+
if( nullptr == g722decoder ) {
|
|
720
718
|
std::cerr << "Failed to init G722 decoder" << std::endl;
|
|
721
719
|
}
|
|
722
720
|
|
|
@@ -727,15 +725,13 @@ void codectests( void )
|
|
|
727
725
|
g722samplepk,
|
|
728
726
|
160 );
|
|
729
727
|
std::cout << "g722_decode returned " << l1616klength << " for an in packet of 160 bytes" << std::endl;
|
|
730
|
-
if( 320 != l1616klength )
|
|
731
|
-
{
|
|
728
|
+
if( 320 != l1616klength ) {
|
|
732
729
|
std::cerr << "ERROR - decoded length is not 320 bytes" << std::endl;
|
|
733
730
|
}
|
|
734
731
|
g722_decode_free( g722decoder );
|
|
735
732
|
|
|
736
733
|
std::cout << "L16 OUT (g722_decode) =" << std::endl;
|
|
737
|
-
for( int i = 0; i < 160; i ++ )
|
|
738
|
-
{
|
|
734
|
+
for( int i = 0; i < 160; i ++ ) {
|
|
739
735
|
std::cout << unsigned( outbuf[ i ] ) << " ";
|
|
740
736
|
}
|
|
741
737
|
std::cout << std::endl;
|
|
@@ -744,66 +740,123 @@ void codectests( void )
|
|
|
744
740
|
/*
|
|
745
741
|
Move onto test our interface.
|
|
746
742
|
*/
|
|
747
|
-
|
|
748
|
-
|
|
743
|
+
{
|
|
744
|
+
rawsound r( g722samplepk, sizeof( g722samplepk ), G722PAYLOADTYPE, 16000 );
|
|
745
|
+
std::cout << "G722 raw packet size " << r.size() << " with a format of " << r.getformat() << " and sample rate " << r.getsamplerate() << std::endl;
|
|
749
746
|
|
|
750
|
-
|
|
747
|
+
codecx ourcodec;
|
|
751
748
|
|
|
752
|
-
|
|
753
|
-
|
|
749
|
+
ourcodec << codecx::next;
|
|
750
|
+
ourcodec << r;
|
|
754
751
|
|
|
755
|
-
|
|
756
|
-
outpk.setpayloadtype( PCMAPAYLOADTYPE );
|
|
757
|
-
outpk.setpayloadlength( 160 );
|
|
758
|
-
outpk.setsequencenumber( 0 );
|
|
759
|
-
outpk.settimestamp( 0 );
|
|
760
|
-
outpk << ourcodec;
|
|
752
|
+
|
|
761
753
|
|
|
762
|
-
|
|
763
|
-
|
|
754
|
+
rtppacket outpk;
|
|
755
|
+
outpk.setpayloadtype( PCMAPAYLOADTYPE );
|
|
756
|
+
outpk.setpayloadlength( 160 );
|
|
757
|
+
outpk.setsequencenumber( 0 );
|
|
758
|
+
outpk.settimestamp( 0 );
|
|
759
|
+
outpk << ourcodec;
|
|
764
760
|
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
761
|
+
std::cout << "PCMA OUT =" << std::endl;
|
|
762
|
+
uint8_t *pl = outpk.getpayload();
|
|
763
|
+
|
|
764
|
+
for( int i = 0; i < 160; i ++ ) {
|
|
765
|
+
std::cout << unsigned( pl[ i ] ) << " ";
|
|
766
|
+
}
|
|
767
|
+
std::cout << std::endl;
|
|
768
|
+
|
|
769
|
+
if( 213 != pl[ 0 ] ) std::cout << "ERROR ERROR First byte should be 213???" << std::endl;
|
|
770
|
+
if( 85 != pl[ 9 ] ) std::cout << "ERROR ERROR 9th byte should be 85???" << std::endl;
|
|
771
|
+
|
|
772
|
+
rawsound &ref8k = ourcodec.getref( L168KPAYLOADTYPE );
|
|
773
|
+
|
|
774
|
+
if( ref8k.isdirty() ) std::cout << "ERROR our 8k out ref should not be dirty" << std::endl;
|
|
775
|
+
|
|
776
|
+
/* Repeat as this will use a different bit of code getting cached bit */
|
|
777
|
+
ref8k = ourcodec.getref( L168KPAYLOADTYPE );
|
|
778
|
+
if( ref8k.isdirty() ) std::cout << "ERROR our 8k out ref should not be dirty" << std::endl;
|
|
779
|
+
|
|
780
|
+
std::cout << "8k is dirty: " << std::boolalpha << ref8k.isdirty() << std::endl;
|
|
781
|
+
std::cout << "8k size: " << ref8k.size() << std::endl;
|
|
782
|
+
std::cout << "8k bytes per sample (should be 2): " << ref8k.getbytespersample() << std::endl;
|
|
770
783
|
|
|
771
|
-
|
|
772
|
-
|
|
784
|
+
/* 2 bytes per sample */
|
|
785
|
+
int16_t *pl16 = ( int16_t * ) ref8k.c_str();
|
|
786
|
+
for( size_t i = 0; i < ref8k.size(); i ++ ) {
|
|
787
|
+
std::cout << static_cast<int16_t>( pl16[ i ] ) << " ";
|
|
788
|
+
}
|
|
789
|
+
std::cout << std::endl;
|
|
773
790
|
|
|
774
|
-
rawsound &ref8k = ourcodec.getref( L168KPAYLOADTYPE );
|
|
775
791
|
|
|
776
|
-
|
|
792
|
+
rawsound &ref16k = ourcodec.getref( L1616KPAYLOADTYPE );
|
|
793
|
+
if( ref16k.isdirty() ) std::cout << "ERROR our 16k out ref should not be dirty" << std::endl;
|
|
794
|
+
std::cout << "16k is dirty: " << std::boolalpha << ref16k.isdirty() << std::endl;
|
|
795
|
+
std::cout << "16k size: " << ref16k.size() << std::endl;
|
|
796
|
+
std::cout << "16k bytes per sample (should be 2): " << ref16k.getbytespersample() << std::endl;
|
|
777
797
|
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
798
|
+
pl16 = ( int16_t * ) ref16k.c_str();
|
|
799
|
+
for( size_t i = 0; i < ref16k.size(); i ++ ) {
|
|
800
|
+
std::cout << static_cast<int16_t>( pl16[ i ] ) << " ";
|
|
801
|
+
}
|
|
802
|
+
std::cout << std::endl;
|
|
803
|
+
}
|
|
781
804
|
|
|
782
|
-
std::cout << "8k is dirty: " << std::boolalpha << ref8k.isdirty() << std::endl;
|
|
783
|
-
std::cout << "8k size: " << ref8k.size() << std::endl;
|
|
784
|
-
std::cout << "8k bytes per sample (should be 2): " << ref8k.getbytespersample() << std::endl;
|
|
785
805
|
|
|
786
|
-
/* 2 bytes per sample */
|
|
787
|
-
int16_t *pl16 = ( int16_t * ) ref8k.c_str();
|
|
788
|
-
for( size_t i = 0; i < ref8k.size(); i ++ )
|
|
789
806
|
{
|
|
790
|
-
|
|
807
|
+
/* problem with converting pcmu to pcma */
|
|
808
|
+
/* use the same data, but pretend it is PCMU */
|
|
809
|
+
rawsound r( g722samplepk, sizeof( g722samplepk ), PCMUPAYLOADTYPE, 8000 );
|
|
810
|
+
|
|
811
|
+
codecx ourcodec;
|
|
812
|
+
|
|
813
|
+
ourcodec << codecx::next;
|
|
814
|
+
ourcodec << r;
|
|
815
|
+
|
|
816
|
+
rtppacket outpk;
|
|
817
|
+
outpk.setpayloadtype( PCMAPAYLOADTYPE );
|
|
818
|
+
outpk.setpayloadlength( 160 );
|
|
819
|
+
outpk.setsequencenumber( 0 );
|
|
820
|
+
outpk.settimestamp( 0 );
|
|
821
|
+
outpk << ourcodec;
|
|
822
|
+
|
|
823
|
+
std::cout << "PCMA OUT (it should not be all zeros) = " << std::endl;
|
|
824
|
+
|
|
825
|
+
uint8_t *pl = outpk.getpayload();
|
|
826
|
+
|
|
827
|
+
for( int i = 0; i < 160; i ++ ) {
|
|
828
|
+
std::cout << unsigned( pl[ i ] ) << " ";
|
|
829
|
+
}
|
|
830
|
+
std::cout << std::endl;
|
|
791
831
|
}
|
|
792
|
-
std::cout << std::endl;
|
|
793
832
|
|
|
833
|
+
{
|
|
834
|
+
/* problem with converting pcmu to pcma */
|
|
835
|
+
/* use the same data, but pretend it is PCMU */
|
|
836
|
+
rawsound r( g722samplepk, sizeof( g722samplepk ), PCMAPAYLOADTYPE, 8000 );
|
|
794
837
|
|
|
795
|
-
|
|
796
|
-
if( ref16k.isdirty() ) std::cout << "ERROR our 16k out ref should not be dirty" << std::endl;
|
|
797
|
-
std::cout << "16k is dirty: " << std::boolalpha << ref16k.isdirty() << std::endl;
|
|
798
|
-
std::cout << "16k size: " << ref16k.size() << std::endl;
|
|
799
|
-
std::cout << "16k bytes per sample (should be 2): " << ref16k.getbytespersample() << std::endl;
|
|
838
|
+
codecx ourcodec;
|
|
800
839
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
840
|
+
ourcodec << codecx::next;
|
|
841
|
+
ourcodec << r;
|
|
842
|
+
|
|
843
|
+
rtppacket outpk;
|
|
844
|
+
outpk.setpayloadtype( PCMUPAYLOADTYPE );
|
|
845
|
+
outpk.setpayloadlength( 160 );
|
|
846
|
+
outpk.setsequencenumber( 0 );
|
|
847
|
+
outpk.settimestamp( 0 );
|
|
848
|
+
outpk << ourcodec;
|
|
849
|
+
|
|
850
|
+
std::cout << "PCMU OUT (it should not be all zeros) = " << std::endl;
|
|
851
|
+
|
|
852
|
+
uint8_t *pl = outpk.getpayload();
|
|
853
|
+
|
|
854
|
+
for( int i = 0; i < 160; i ++ ) {
|
|
855
|
+
std::cout << unsigned( pl[ i ] ) << " ";
|
|
856
|
+
}
|
|
857
|
+
std::cout << std::endl;
|
|
805
858
|
}
|
|
806
|
-
|
|
859
|
+
|
|
807
860
|
}
|
|
808
861
|
|
|
809
862
|
#ifdef NODE_MODULE
|
|
@@ -620,6 +620,7 @@ describe( "dtmf", function() {
|
|
|
620
620
|
expect( receivedmessages[ 1 ].action ).to.equal( "telephone-event" )
|
|
621
621
|
expect( receivedmessages[ 2 ].action ).to.equal( "telephone-event" )
|
|
622
622
|
expect( receivedmessages[ 3 ].action ).to.equal( "mix" )
|
|
623
|
+
expect( receivedmessages[ 3 ].event ).to.equal( "finished" )
|
|
623
624
|
expect( receivedmessages[ 4 ].action ).to.equal( "close" )
|
|
624
625
|
|
|
625
626
|
expect( receivedmessages[ 0 ].event ).to.equal( "start" )
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
const prtp = require( "../../index" )
|
|
3
3
|
const node = require( "../../lib/node" )
|
|
4
4
|
const expect = require( "chai" ).expect
|
|
5
|
+
const fs = require( "node:fs" )
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Test file to run tests acting as a remote note. Starts a babble-rtp node in the background
|
|
@@ -25,7 +26,7 @@ describe( "server connect interface", () => {
|
|
|
25
26
|
|
|
26
27
|
it( "server connect and open channel", async function () {
|
|
27
28
|
this.timeout( 6000 )
|
|
28
|
-
this.slow(
|
|
29
|
+
this.slow( 30000 )
|
|
29
30
|
|
|
30
31
|
const totalotherchannelcount = 100
|
|
31
32
|
let chanclosecount = 0
|
|
@@ -37,6 +38,8 @@ describe( "server connect interface", () => {
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
// A very short wav file
|
|
41
|
+
await fs.promises.rm( "/tmp/serverconnecttestwav.wav", { force: true } )
|
|
42
|
+
await fs.promises.rm( "/tmp/otherserverconnecttestwav.wav", { force: true } )
|
|
40
43
|
prtp.projectrtp.tone.generate( "350+440*0.5:100", "/tmp/serverconnecttestwav.wav" )
|
|
41
44
|
prtp.projectrtp.tone.generate( "350+440*0.5:100", "/tmp/otherserverconnecttestwav.wav" )
|
|
42
45
|
|
|
@@ -48,16 +51,13 @@ describe( "server connect interface", () => {
|
|
|
48
51
|
for( let i = 0; 3 > i; i++ ) {
|
|
49
52
|
let done
|
|
50
53
|
const finished = new Promise( resolve => done = resolve )
|
|
51
|
-
|
|
52
54
|
const receivedmessages = []
|
|
53
55
|
const chan = await prtp.projectrtp.openchannel( ( e ) => {
|
|
54
56
|
receivedmessages.push( e )
|
|
55
57
|
if( "play" == e.action && "end" == e.event ) chan.close()
|
|
56
58
|
if( "close" == e.action ) done()
|
|
57
59
|
} )
|
|
58
|
-
|
|
59
60
|
chan.play( { "interupt":true, "files": [ { "wav": "/tmp/serverconnecttestwav.wav" }, { "wav": "/tmp/otherserverconnecttestwav.wav" } ] } )
|
|
60
|
-
|
|
61
61
|
await finished
|
|
62
62
|
|
|
63
63
|
//console.log(receivedmessages)
|
|
@@ -172,6 +172,101 @@ describe( "channel mix", function() {
|
|
|
172
172
|
|
|
173
173
|
} )
|
|
174
174
|
|
|
175
|
+
|
|
176
|
+
it( "mix 2 channels then unmix then mix again", async function() {
|
|
177
|
+
|
|
178
|
+
this.timeout( 6000 )
|
|
179
|
+
this.slow( 5000 )
|
|
180
|
+
|
|
181
|
+
const endpointa = dgram.createSocket( "udp4" )
|
|
182
|
+
const endpointb = dgram.createSocket( "udp4" )
|
|
183
|
+
|
|
184
|
+
const endpointapkcount = [ 0, 0, 0, 0 ]
|
|
185
|
+
const endpointbpkcount = [ 0, 0, 0, 0 ]
|
|
186
|
+
|
|
187
|
+
endpointa.on( "message", function( msg ) {
|
|
188
|
+
endpointapkcount[ 0x7f & msg[ 50 ] ]++
|
|
189
|
+
expect( msg.length ).to.equal( 172 )
|
|
190
|
+
expect( 0x7f & msg [ 1 ] ).to.equal( 0 )
|
|
191
|
+
} )
|
|
192
|
+
|
|
193
|
+
endpointb.on( "message", function( msg ) {
|
|
194
|
+
endpointbpkcount[ 0x7f & msg[ 50 ] ]++
|
|
195
|
+
expect( msg.length ).to.equal( 172 )
|
|
196
|
+
expect( 0x7f & msg [ 1 ] ).to.equal( 0 )
|
|
197
|
+
} )
|
|
198
|
+
|
|
199
|
+
endpointa.bind()
|
|
200
|
+
await new Promise( ( resolve ) => { endpointa.on( "listening", function() { resolve() } ) } )
|
|
201
|
+
|
|
202
|
+
endpointb.bind()
|
|
203
|
+
await new Promise( ( resolve ) => { endpointb.on( "listening", function() { resolve() } ) } )
|
|
204
|
+
|
|
205
|
+
let promisearesolve, promisebresolve
|
|
206
|
+
const promisea = new Promise( r => promisearesolve = r )
|
|
207
|
+
const promiseb = new Promise( r => promisebresolve = r )
|
|
208
|
+
|
|
209
|
+
const channela = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": endpointa.address().port, "codec": 0 } }, function( d ) {
|
|
210
|
+
if( "close" === d.action ) {
|
|
211
|
+
promisearesolve()
|
|
212
|
+
}
|
|
213
|
+
} )
|
|
214
|
+
|
|
215
|
+
const channelb = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": endpointb.address().port, "codec": 0 } }, function( d ) {
|
|
216
|
+
if( "close" === d.action ) {
|
|
217
|
+
promisebresolve()
|
|
218
|
+
}
|
|
219
|
+
} )
|
|
220
|
+
|
|
221
|
+
/* mix */
|
|
222
|
+
expect( channela.mix( channelb ) ).to.be.true
|
|
223
|
+
/* Now, when we send UDP on endpointb it passes through our mix then arrives at endpointa */
|
|
224
|
+
let dataa = Buffer.alloc( 172 - 12 ).fill( 0 )
|
|
225
|
+
let datab = Buffer.alloc( 172 - 12 ).fill( 1 )
|
|
226
|
+
|
|
227
|
+
for( let i = 0; 50 > i; i ++ ) {
|
|
228
|
+
sendpk( i, i, channela.local.port, endpointa, dataa )
|
|
229
|
+
sendpk( i, i, channelb.local.port, endpointb, datab )
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/* 1S for 50 packets to get through, 0.5 seconds to allow all through jitter buffers */
|
|
233
|
+
await new Promise( ( resolve ) => { setTimeout( () => resolve(), 1700 ) } )
|
|
234
|
+
|
|
235
|
+
channela.direction( { send: true, recv: false } )
|
|
236
|
+
expect( channelb.unmix( channela ) ).to.be.true
|
|
237
|
+
channelb.play( { "loop": true, "files": [
|
|
238
|
+
{ "wav": "/tmp/ukringing.wav" } ] } )
|
|
239
|
+
|
|
240
|
+
await new Promise( ( resolve ) => { setTimeout( () => resolve(), 200 ) } )
|
|
241
|
+
|
|
242
|
+
channela.direction( { send: true, recv: true } )
|
|
243
|
+
expect( channelb.mix( channela ) ).to.be.true
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
dataa = Buffer.alloc( 172 - 12 ).fill( 2 )
|
|
247
|
+
datab = Buffer.alloc( 172 - 12 ).fill( 3 )
|
|
248
|
+
for( let i = 0; 50 > i; i ++ ) {
|
|
249
|
+
sendpk( i, i, channela.local.port, endpointa, dataa )
|
|
250
|
+
sendpk( i, i, channelb.local.port, endpointb, datab )
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
await new Promise( ( resolve ) => { setTimeout( () => resolve(), 1700 ) } )
|
|
254
|
+
|
|
255
|
+
channelb.close()
|
|
256
|
+
channela.close()
|
|
257
|
+
endpointa.close()
|
|
258
|
+
endpointb.close()
|
|
259
|
+
|
|
260
|
+
/* have we cleaned up? */
|
|
261
|
+
await Promise.all( [ promisea, promiseb ] )
|
|
262
|
+
|
|
263
|
+
expect( endpointapkcount[ 1 ] ).to.be.within( 49, 51 )
|
|
264
|
+
expect( endpointapkcount[ 3 ] ).to.be.within( 49, 51 )
|
|
265
|
+
expect( endpointbpkcount[ 0 ] ).to.be.within( 49, 51 )
|
|
266
|
+
expect( endpointbpkcount[ 2 ] ).to.be.within( 49, 51 )
|
|
267
|
+
|
|
268
|
+
} )
|
|
269
|
+
|
|
175
270
|
it( "mix 2 channels then close b", async function() {
|
|
176
271
|
|
|
177
272
|
this.timeout( 3000 )
|