@babblevoice/projectrtp 2.4.17 → 2.5.20

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.
@@ -1,5 +1,7 @@
1
1
 
2
2
  #include <iostream>
3
+ #include <cstdlib>
4
+ #include <iomanip>
3
5
  #include <math.h>
4
6
 
5
7
  #include "projectrtpcodecx.h"
@@ -320,10 +322,10 @@ bool codecx::ilbctol16( void ) {
320
322
 
321
323
  if( -1 == l168klength ) {
322
324
  this->l168kref.size( 0 );
323
- this->l168kref.dirty( false );
324
325
  return false;
325
326
  }
326
327
 
328
+ this->l168kref.dirty( false );
327
329
  this->l168kref.size( l168klength );
328
330
  return true;
329
331
  }
@@ -518,9 +520,10 @@ rawsound& codecx::requirel16( void )
518
520
  return this->l168kref;
519
521
  }
520
522
 
521
- /*
522
- # getref
523
- returns a reference to the relavent rawsound and ensures it is transcoded if required.
523
+ /**
524
+ * Obtain a reference to a rawsound for the codec type pt. i.e. we alrteady have
525
+ * the input sound and based on the format we want to convert it to that
526
+ * format.
524
527
  */
525
528
  rawsound& codecx::getref( int pt ) {
526
529
  /* If we have already have or converted this packet... */
@@ -558,7 +561,7 @@ rawsound& codecx::getref( int pt ) {
558
561
  return this->g722ref;
559
562
  }
560
563
  case PCMAPAYLOADTYPE: {
561
- if( this->pcmuref.size() > 0 ) {
564
+ if( !this->pcmuref.isdirty() && this->pcmuref.size() > 0 ) {
562
565
  this->ulaw2alaw();
563
566
  } else {
564
567
  this->requirenarrowband();
@@ -567,7 +570,7 @@ rawsound& codecx::getref( int pt ) {
567
570
  return this->pcmaref;
568
571
  }
569
572
  case PCMUPAYLOADTYPE: {
570
- if( this->pcmaref.size() > 0 ) {
573
+ if( !this->pcmaref.isdirty() && this->pcmaref.size() > 0 ) {
571
574
  this->alaw2ulaw();
572
575
  } else {
573
576
  this->requirenarrowband();
@@ -586,7 +589,7 @@ rawsound& codecx::getref( int pt ) {
586
589
  }
587
590
 
588
591
  /* We should ever get here unless an invalid param has been passed in */
589
- std::cerr << "codecx::getref call with bad pt" << std::endl;
592
+ std::cerr << "codecx::getref call with bad pt: " << pt << std::endl;
590
593
  return this->pcmuref;
591
594
  }
592
595
 
@@ -3,6 +3,8 @@
3
3
  #ifndef PROJECTRTPCODECX_H
4
4
  #define PROJECTRTPCODECX_H
5
5
 
6
+ #include <iostream>
7
+ #include <cstdlib>
6
8
 
7
9
  #include <ilbc.h>
8
10
  #include <spandsp.h>
@@ -127,6 +129,8 @@ auto* operator << ( auto *pk, codecx& c ) {
127
129
 
128
130
  switch( outpayloadtype ) {
129
131
  case ILBCPAYLOADTYPE: {
132
+ pk->setpayloadlength( ILBC20PAYLOADBYTES );
133
+
130
134
  if( !c.ilbcref.isdirty() ) {
131
135
  pk->copy( c.ilbcref.c_str(), c.ilbcref.size() * c.ilbcref.getbytespersample() );
132
136
  return pk;
@@ -135,6 +139,7 @@ auto* operator << ( auto *pk, codecx& c ) {
135
139
  break;
136
140
  }
137
141
  case G722PAYLOADTYPE: {
142
+ pk->setpayloadlength( G722PAYLOADBYTES );
138
143
  if( !c.g722ref.isdirty() ) {
139
144
  pk->copy( c.g722ref.c_str(), c.g722ref.size() * c.g722ref.getbytespersample() );
140
145
  return pk;
@@ -143,6 +148,7 @@ auto* operator << ( auto *pk, codecx& c ) {
143
148
  break;
144
149
  }
145
150
  case PCMAPAYLOADTYPE: {
151
+ pk->setpayloadlength( G711PAYLOADBYTES );
146
152
  if( !c.pcmaref.isdirty() ) {
147
153
  pk->copy( c.pcmaref.c_str(), c.pcmaref.size() * c.pcmaref.getbytespersample() );
148
154
  return pk;
@@ -151,6 +157,7 @@ auto* operator << ( auto *pk, codecx& c ) {
151
157
  break;
152
158
  }
153
159
  case PCMUPAYLOADTYPE: {
160
+ pk->setpayloadlength( G711PAYLOADBYTES );
154
161
  if( !c.pcmuref.isdirty() ) {
155
162
  pk->copy( c.pcmuref.c_str(), c.pcmuref.size() * c.pcmuref.getbytespersample() );
156
163
  return pk;
@@ -159,6 +166,7 @@ auto* operator << ( auto *pk, codecx& c ) {
159
166
  break;
160
167
  }
161
168
  case L168KPAYLOADTYPE: {
169
+ pk->setpayloadlength( L16NARROWBANDBYTES );
162
170
  if( !c.l168kref.isdirty() ) {
163
171
  pk->copy( c.l168kref.c_str(), c.l168kref.size() * c.l168kref.getbytespersample() );
164
172
  return pk;
@@ -168,6 +176,7 @@ auto* operator << ( auto *pk, codecx& c ) {
168
176
  }
169
177
 
170
178
  case L1616KPAYLOADTYPE: {
179
+ pk->setpayloadlength( L16WIDEBANDBYTES );
171
180
  if( !c.l1616kref.isdirty() ) {
172
181
  pk->copy( c.l1616kref.c_str(), c.l1616kref.size() * c.l1616kref.getbytespersample() );
173
182
  return pk;
@@ -175,10 +184,16 @@ auto* operator << ( auto *pk, codecx& c ) {
175
184
  c.l1616kref = rawsound( *pk, true );
176
185
  break;
177
186
  }
187
+ default: {
188
+ /* this should not happen */
189
+ std::cerr << "Unknown CODEC when encoding: " << outpayloadtype << std::endl;
190
+ return pk;
191
+ }
178
192
  }
179
193
 
180
- rawsound r = c.getref( outpayloadtype );
181
- pk->setpayloadlength( r.size() );
194
+ /* encode */
195
+ c.getref( outpayloadtype );
196
+
182
197
  return pk;
183
198
  }
184
199
 
@@ -1,8 +1,7 @@
1
1
 
2
- #ifdef TESTSUITE
3
2
  #include <iostream>
3
+ #include <cstdlib>
4
4
  #include <iomanip>
5
- #endif
6
5
 
7
6
  #include "projectrtppacket.h"
8
7
  #include "globals.h"
@@ -43,7 +42,7 @@ void rtppacket::copy( rtppacket *src )
43
42
  src->pk + 12 + ( src->getpacketcsrccount() * 4 ),
44
43
  src->getpayloadlength() );
45
44
 
46
- this->length = src->getpayloadlength() + 12 + ( this->getpacketcsrccount() * 4 );
45
+ this->length = src->length;
47
46
  }
48
47
 
49
48
  /*!md
@@ -139,28 +138,11 @@ uint8_t rtppacket::getpayloadtype( void )
139
138
  /*!md
140
139
  ## setpayloadtype
141
140
  As it says. We also set the length of the packet to a default amount for that CODEC.
141
+ If setting a dynamic payloadtype - don't mess with the length as we won't know it
142
+ and it must already be set.
142
143
  */
143
- void rtppacket::setpayloadtype( uint8_t pt )
144
- {
144
+ void rtppacket::setpayloadtype( uint8_t pt ) {
145
145
  this->pk[ 1 ] = ( this->pk[ 1 ] & 0x80 ) | ( pt & 0x7f );
146
-
147
- switch( pt )
148
- {
149
- case ILBC20PAYLOADBYTES:
150
- {
151
- this->length = 12 + ILBC20PAYLOADBYTES;
152
- break;
153
- }
154
- case ILBC30PAYLOADBYTES:
155
- {
156
- this->length = 12 + ILBC30PAYLOADBYTES;
157
- break;
158
- }
159
- default:
160
- {
161
- this->length = 12 + G711PAYLOADBYTES;
162
- }
163
- }
164
146
  }
165
147
 
166
148
  /*!md
@@ -243,8 +225,7 @@ uint32_t rtppacket::getcsrc( uint8_t index )
243
225
  ## getpayload
244
226
  Returns a pointer to the start of the payload.
245
227
  */
246
- uint8_t *rtppacket::getpayload( void )
247
- {
228
+ uint8_t *rtppacket::getpayload( void ) {
248
229
  uint8_t *ptr = this->pk;
249
230
  ptr += 12;
250
231
  ptr += ( this->getpacketcsrccount() * 4 );
@@ -256,11 +237,9 @@ uint8_t *rtppacket::getpayload( void )
256
237
  ## getpayloadlength
257
238
  As it says.
258
239
  */
259
- uint16_t rtppacket::getpayloadlength( void )
260
- {
240
+ uint16_t rtppacket::getpayloadlength( void ) {
261
241
 
262
- if( this->length < ( 12 - ( (size_t)this->getpacketcsrccount() * 4 ) ) )
263
- {
242
+ if( this->length < ( 12 - ( (size_t) this->getpacketcsrccount() * 4 ) ) ) {
264
243
  fprintf( stderr, "RTP Packet has a nonsense size\n" );
265
244
  return 0;
266
245
  }
@@ -271,30 +250,26 @@ uint16_t rtppacket::getpayloadlength( void )
271
250
  ## setpayloadlength
272
251
  As it says.
273
252
  */
274
- void rtppacket::setpayloadlength( size_t length )
275
- {
253
+ void rtppacket::setpayloadlength( size_t length ) {
276
254
  this->length = 12 + ( this->getpacketcsrccount() * 4 ) + length;
277
255
  }
278
256
 
279
- #ifdef TESTSUITE
280
- /* show the contents to cout */
257
+ /* dump the contents to cout */
281
258
  void rtppacket::dump() {
282
259
  std::cout << "=================BEGIN=================" << std::endl;
283
- std::cout << "length: " << this->length << std::endl;
284
- std::cout << "payload length: " << this->getpayloadlength() << std::endl;
260
+ std::cout << "length: " << std::dec << this->length << std::endl;
261
+ std::cout << "payload length: " << std::dec << this->getpayloadlength() << std::endl;
285
262
  std::cout << "marker: " << +this->getpacketmarker() << std::endl;
286
263
  std::cout << "pt: " << +this->getpayloadtype() << std::endl;
287
- std::cout << "sn: " << this->getsequencenumber() << std::endl;
288
- std::cout << "ts: " << this->gettimestamp() << std::endl;
289
- std::cout << "ssrc: " << this->getssrc() << std::endl;
264
+ std::cout << "sn: " << std::dec << this->getsequencenumber() << std::endl;
265
+ std::cout << "ts: " << std::dec << this->gettimestamp() << std::endl;
266
+ std::cout << "ssrc: " << std::dec << this->getssrc() << std::endl;
290
267
 
291
268
  auto v = this->getpayload();
292
269
  for( auto i = 0; i < this->getpayloadlength(); i ++ ) {
293
270
  std::cout << std::showbase << std::setfill( '0' ) << std::setw( 2 ) << std::hex << std::right << +(*(v+i)) << ' ';
294
- if( 0 == i % 16 ) std::cout << std::endl;
271
+ if( 0 != i && 0 == i % 16 ) std::cout << std::endl;
295
272
  }
296
273
  std::cout << std::dec;
297
-
298
274
  std::cout << std::endl << "=================END===================" << std::endl;
299
275
  }
300
- #endif
@@ -45,9 +45,7 @@ public:
45
45
  void copy( rtppacket *src );
46
46
  void copy( uint8_t *src, size_t len );
47
47
  void copyheader( rtppacket *src );
48
- #ifdef TESTSUITE
49
48
  void dump();
50
- #endif
51
49
 
52
50
  };
53
51
 
@@ -1,5 +1,7 @@
1
1
 
2
2
  #include <iostream> // cerr
3
+ #include <cstdlib>
4
+ #include <iomanip>
3
5
 
4
6
  #include "projectrtprawsound.h"
5
7
  #include "projectrtpcodecx.h"
@@ -241,15 +243,12 @@ void rawsound::malloc( size_t samplecount, size_t bytespersample, int format )
241
243
  this->bytespersample = bytespersample;
242
244
  this->format = format;
243
245
  size_t requiredsize = samplecount * bytespersample;
244
- if( L1616KPAYLOADTYPE == format )
245
- {
246
+ if( L1616KPAYLOADTYPE == format ) {
246
247
  requiredsize = requiredsize * 2;
247
248
  }
248
249
 
249
- if( this->allocatedlength > 0 )
250
- {
251
- if( this->allocatedlength >= requiredsize )
252
- {
250
+ if( this->allocatedlength > 0 ) {
251
+ if( this->allocatedlength >= requiredsize ) {
253
252
  return;
254
253
  }
255
254
 
@@ -354,3 +353,21 @@ rawsound& rawsound::operator-=( codecx& rhs )
354
353
 
355
354
  return *this;
356
355
  }
356
+
357
+
358
+ void rawsound::dump() {
359
+
360
+ std::cout << "=================BEGIN=================" << std::endl;
361
+ std::cout << "samples: " << std::dec << this->samples << std::endl;
362
+ std::cout << "bytespersample: " << std::dec << this->bytespersample << std::endl;
363
+ std::cout << "format: " << std::dec << this->format << std::endl;
364
+
365
+ auto v = this->data;
366
+ size_t len = this->samples * this->bytespersample;
367
+ for( size_t i = 0; i < len; i ++ ) {
368
+ std::cout << std::showbase << std::setfill( '0' ) << std::setw( 2 ) << std::hex << std::right << +(*(v+i)) << ' ';
369
+ if( 0 != i && 0 == i % 16 ) std::cout << std::endl;
370
+ }
371
+ std::cout << std::dec;
372
+ std::cout << std::endl << "=================END===================" << std::endl;
373
+ }
@@ -6,8 +6,7 @@
6
6
  #include "projectrtppacket.h"
7
7
 
8
8
  class codecx;
9
- class rawsound
10
- {
9
+ class rawsound {
11
10
  public:
12
11
  rawsound();
13
12
  rawsound( uint8_t *ptr, std::size_t samples, int format, uint16_t samplerate );
@@ -39,6 +38,8 @@ public:
39
38
  rawsound& operator+=( codecx& rhs );
40
39
  rawsound& operator-=( codecx& rhs );
41
40
 
41
+ void dump();
42
+
42
43
  private:
43
44
  void frompt( int payloadtype );
44
45
 
@@ -605,7 +605,10 @@ static napi_value wavinfo( napi_env env, napi_callback_info info ) {
605
605
  return NULL;
606
606
  }
607
607
 
608
- read( fd, &hd, sizeof( wavheader ) );
608
+ if( sizeof( wavheader ) != read( fd, &hd, sizeof( wavheader ) ) ) {
609
+ napi_throw_type_error( env, "0", "Bad wav header" );
610
+ goto done;
611
+ }
609
612
 
610
613
  if( 'R' != hd.riff_header[ 0 ] ||
611
614
  'I' != hd.riff_header[ 1 ] ||
@@ -51,13 +51,11 @@ static void gentone( int16_t *outbuffer, int sizeofblock, double startfrequency,
51
51
  }
52
52
 
53
53
 
54
- static void gen( std::string tone, std::string filename )
55
- {
54
+ static void gen( std::string tone, std::string filename ) {
56
55
  vectorofstrings freqscadence;
57
56
  boost::split( freqscadence, tone, boost::is_any_of( ":" ) );
58
57
 
59
- if( 2 != freqscadence.size() )
60
- {
58
+ if( 2 != freqscadence.size() ) {
61
59
  std::cerr << "You must supply a cadence, eg. 400:1000" << std::endl;
62
60
  return;
63
61
  }
@@ -76,8 +74,7 @@ static void gen( std::string tone, std::string filename )
76
74
  vectorofstrings cadenceparts;
77
75
  int cadencepos = 0;
78
76
  int cadencetotal = 0;
79
- for( it = frequencies.begin(); it != frequencies.end(); it++ )
80
- {
77
+ for( it = frequencies.begin(); it != frequencies.end(); it++ ) {
81
78
  cadencetotal += std::atoi( cadences[ cadencepos ].c_str() );
82
79
  cadencepos = ( cadencepos + 1 ) % cadences.size();
83
80
  }
@@ -94,8 +91,7 @@ static void gen( std::string tone, std::string filename )
94
91
  /* 3. Generate tones */
95
92
  int pos = 0;
96
93
  cadencepos = 0;
97
- for( it = frequencies.begin(); it != frequencies.end(); it++ )
98
- {
94
+ for( it = frequencies.begin(); it != frequencies.end(); it++ ) {
99
95
  /* Current cadence. */
100
96
  int cadence = std::atoi( cadences[ cadencepos ].c_str() );
101
97
  cadencepos = ( cadencepos + 1 ) % cadences.size();
@@ -109,14 +105,12 @@ static void gen( std::string tone, std::string filename )
109
105
  boost::split( freqamp, *it, boost::is_any_of( "*" ) );
110
106
  double startamp = 1;
111
107
  double endamp = 1;
112
- if( freqamp.size() > 1 )
113
- {
108
+ if( freqamp.size() > 1 ) {
114
109
  vectorofstrings ampfromto;
115
110
  boost::split( ampfromto, freqamp[ 1 ], boost::is_any_of( "~" ) );
116
111
  startamp = std::atof( ampfromto[ 0 ].c_str() );
117
112
  endamp = startamp;
118
- if( ampfromto.size() > 1 )
119
- {
113
+ if( ampfromto.size() > 1 ) {
120
114
  endamp = std::atof( ampfromto[ 1 ].c_str() );
121
115
  }
122
116
  }
@@ -127,27 +121,20 @@ static void gen( std::string tone, std::string filename )
127
121
  double endfreq = -1;
128
122
 
129
123
  std::size_t found = freqamp[ 0 ].find_first_of( "+x~" );
130
- if( std::string::npos == found )
131
- {
124
+ if( std::string::npos == found ) {
132
125
  startfreq = std::atof( freqparts[ 0 ].c_str() );
133
126
  gentone( outbuffer, sizeofblock, startfreq, startfreq, startamp, endamp, outwavheader.sample_rate );
134
127
  goto continueloop;
135
- }
136
- else
137
- {
138
- switch( freqamp[ 0 ][ found ] )
139
- {
140
- case '+':
141
- {
142
- for( auto freqit = freqparts.begin(); freqit != freqparts.end(); freqit++ )
143
- {
128
+ } else {
129
+ switch( freqamp[ 0 ][ found ] ) {
130
+ case '+': {
131
+ for( auto freqit = freqparts.begin(); freqit != freqparts.end(); freqit++ ) {
144
132
  startfreq = std::atof( freqit->c_str() );
145
133
  gentone( outbuffer, sizeofblock, startfreq, startfreq, startamp, endamp, outwavheader.sample_rate );
146
134
  }
147
135
  break;
148
136
  }
149
- case '~':
150
- {
137
+ case '~': {
151
138
  startfreq = std::atof( freqparts[ 0 ].c_str() );
152
139
  endfreq = std::atof( freqparts[ 1 ].c_str() );
153
140
  gentone( outbuffer, sizeofblock, startfreq, endfreq, startamp, endamp, outwavheader.sample_rate );
@@ -164,39 +151,35 @@ continueloop:
164
151
  /* Write */
165
152
  int file = open( filename.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR );
166
153
  off_t position = lseek( file, 0, SEEK_END );
167
- if( 0 == position )
168
- {
169
- write( file, &outwavheader, sizeof( wavheader ) );
170
- write( file, readbuffer, outwavheader.chunksize );
171
- }
172
- else
173
- {
154
+ if( 0 == position ) {
155
+ if( -1 == write( file, &outwavheader, sizeof( wavheader ) ) ) std::cerr << "Error writing to tone file" << std::endl;
156
+ if( -1 == write( file, readbuffer, outwavheader.chunksize ) ) std::cerr << "Error writing to tone file" << std::endl;
157
+ } else {
174
158
  wavheader currentheader;
175
159
  lseek( file, 0, SEEK_SET );
176
- read( file, &currentheader, sizeof( wavheader ) );
160
+ if( sizeof( wavheader ) != read( file, &currentheader, sizeof( wavheader ) ) ) {
161
+ std::cerr << "Error reading existing tone file" << std::endl;
162
+ goto cleanuupgen;
163
+ }
177
164
  lseek( file, 0, SEEK_END );
178
165
 
179
166
  if( currentheader.audio_format == outwavheader.audio_format &&
180
- currentheader.sample_rate == outwavheader.sample_rate )
181
- {
167
+ currentheader.sample_rate == outwavheader.sample_rate ) {
182
168
  /* Ok, good enough! */
183
169
  currentheader.chunksize += outwavheader.chunksize;
184
170
  currentheader.subchunksize += outwavheader.subchunksize;
185
171
 
186
172
  lseek( file, 0, SEEK_SET );
187
- write( file, &currentheader, sizeof( wavheader ) );
173
+ if( -1 == write( file, &currentheader, sizeof( wavheader ) ) ) std::cerr << "Error writing to tone file" << std::endl;
188
174
  lseek( file, 0, SEEK_END );
189
- write( file, readbuffer, outwavheader.chunksize );
190
- }
191
- else
192
- {
175
+ if( -1 == write( file, readbuffer, outwavheader.chunksize ) ) std::cerr << "Error writing to tone file" << std::endl;
176
+ } else {
193
177
  std::cerr << "File format to append should be the same" << std::endl;
194
178
  }
195
179
  }
196
180
 
197
- /* Clean up */
198
- if( nullptr != readbuffer )
199
- {
181
+ cleanuupgen:
182
+ if( nullptr != readbuffer ) {
200
183
  delete[] readbuffer;
201
184
  }
202
185
 
@@ -381,8 +381,7 @@ describe( "rtpchannel", function() {
381
381
  lastts = ts
382
382
 
383
383
  receviedpkcount++
384
- //console.log(receviedpkcount, sn, ts)
385
- if( 185 == receviedpkcount ) channel.close()
384
+
386
385
  } )
387
386
 
388
387
  this.timeout( 15000 )
@@ -390,8 +389,7 @@ describe( "rtpchannel", function() {
390
389
 
391
390
  server.bind()
392
391
 
393
- let done
394
- const finished = new Promise( ( r ) => done = r )
392
+
395
393
  let closedstats = {}
396
394
  server.on( "listening", async function() {
397
395
 
@@ -402,7 +400,6 @@ describe( "rtpchannel", function() {
402
400
  if( "close" === d.action ) {
403
401
  closedstats = d
404
402
  server.close()
405
- done()
406
403
  }
407
404
  } )
408
405
 
@@ -410,7 +407,7 @@ describe( "rtpchannel", function() {
410
407
 
411
408
  /* send a packet every 20mS x 50 */
412
409
  let i
413
- for( i = 0; 50 > i; i++ ) {
410
+ for( i = 0; 120 > i; i++ ) {
414
411
  sendpk( i, i, channel.local.port, server )
415
412
  }
416
413
 
@@ -425,7 +422,10 @@ describe( "rtpchannel", function() {
425
422
  }
426
423
  } )
427
424
 
428
- await finished
425
+ await new Promise( resolve => setTimeout( resolve, 6500 ) )
426
+ // @ts-ignore
427
+ channel.close()
428
+ await new Promise( resolve => setTimeout( resolve, 50 ) )
429
429
 
430
430
  /*
431
431
  We should receive
@@ -435,10 +435,10 @@ describe( "rtpchannel", function() {
435
435
  */
436
436
  expect( receviedpkcount ).to.equal( closedstats.stats.out.count )
437
437
  expect( closedstats.stats.in.count ).to.equal( 300 )
438
- expect( closedstats.stats.out.count ).to.be.within( 180, 190 )
438
+ expect( closedstats.stats.out.count ).to.be.above( 250 )
439
439
  expect( totalsndiff ).to.equal( 0 ) // received should be reordered
440
- expect( totaltsdiff ).to.be.within( 18240, 18400 ) // Allow some loss in test
441
- expect( lastsn - firstsn ).to.be.within( 180, 192 )
440
+ expect( totaltsdiff ).to.be.within( 5000, 18400 ) // Allow some loss in test
441
+ expect( lastsn - firstsn ).to.be.within( 250, 300 )
442
442
  } )
443
443
 
444
444
  it( "create channel echo whilst wrapping the sn", function( done ) {
@@ -23,6 +23,21 @@ function sendpayload( sendtime, pk, dstport, server ) {
23
23
  }, sendtime )
24
24
  }
25
25
 
26
+ /**
27
+ * Limitation of not parsing ccrc.
28
+ * @param { Buffer } packet
29
+ * @return { object }
30
+ */
31
+ function parsepk( packet ) {
32
+ return {
33
+ sn: packet.readUInt16BE( 2 ),
34
+ ts: packet.readUInt32BE( 4 ),
35
+ pt: packet.readUInt8( 1 ) & 0x7f,
36
+ ssrc: packet.readUInt32BE( 8 ),
37
+ payload: new Uint8Array( packet.slice( 12 ) )
38
+ }
39
+ }
40
+
26
41
  /* helper functions */
27
42
  function sendpk( sn, ts, sendtime, dstport, server, pt = 0, ssrc ) {
28
43
 
@@ -253,6 +268,74 @@ describe( "dtmf", function() {
253
268
  expect( dtmfpkcount ).to.equal( 3*3 )
254
269
  } )
255
270
 
271
+ it( "2 channels mixing and request rtp server to send 2833 to one with dynamic payloadtype", async function() {
272
+
273
+ /* create our RTP/UDP endpoint */
274
+ const clienta = dgram.createSocket( "udp4" )
275
+ const clientb = dgram.createSocket( "udp4" )
276
+
277
+ const rfc2833pt = 44
278
+
279
+ let dtmfpkcount = 0
280
+ clienta.on( "message", function( msg ) {
281
+ if( rfc2833pt == ( 0x7f & msg [ 1 ] ) ) {
282
+ dtmfpkcount++
283
+ } else {
284
+ expect( msg.length ).to.equal( 172 )
285
+ expect( 0x7f & msg [ 1 ] ).to.equal( 0 )
286
+ }
287
+ } )
288
+
289
+ clientb.on( "message", function( msg ) {
290
+ if( 101 == ( 0x7f & msg [ 1 ] ) ) {
291
+ expect( true ).to.equal( false ) //here = bad
292
+ dtmfpkcount++
293
+ }
294
+ clientb.send( msg, channelb.local.port, "localhost" )
295
+ } )
296
+
297
+ this.timeout( 3000 )
298
+ this.slow( 2500 )
299
+
300
+ clienta.bind()
301
+ await new Promise( ( resolve ) => { clienta.on( "listening", () => resolve() ) } )
302
+ clientb.bind()
303
+ await new Promise( ( resolve ) => { clientb.on( "listening", () => resolve() ) } )
304
+
305
+ const ouraport = clienta.address().port
306
+ const ourbport = clientb.address().port
307
+
308
+ let done
309
+ const finished = new Promise( ( r ) => { done = r } )
310
+
311
+ const channela = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": ouraport, "codec": 0, rfc2833pt } }, function( d ) {
312
+ if( "close" === d.action ) channelb.close()
313
+ } )
314
+
315
+ const channelb = await projectrtp.openchannel( { "remote": { "address": "localhost", "port": ourbport, "codec": 0 } }, function( d ) {
316
+ if( "close" === d.action ) done()
317
+ } )
318
+
319
+ expect( channela.mix( channelb ) ).to.be.true
320
+
321
+ /* send a packet every 20mS x 70 */
322
+ for( let i = 0; 50 > i; i ++ ) {
323
+ sendpk( i, i*160, i*20, channela.local.port, clienta )
324
+ }
325
+
326
+ await new Promise( ( resolve ) => { setTimeout( () => resolve(), 400 ) } )
327
+ channela.dtmf( "*9F" )
328
+ await new Promise( ( resolve ) => { setTimeout( () => resolve(), 800 ) } )
329
+ channela.close()
330
+
331
+ await finished
332
+
333
+ clienta.close()
334
+ clientb.close()
335
+
336
+ expect( dtmfpkcount ).to.equal( 3*3 )
337
+ } )
338
+
256
339
  it( "3 channels mixing and request rtp server to send 2833 to one", async function() {
257
340
 
258
341
  /* create our RTP/UDP endpoint */
@@ -262,11 +345,12 @@ describe( "dtmf", function() {
262
345
 
263
346
  let dtmfpkcount = 0
264
347
  clienta.on( "message", function( msg ) {
265
- if( 101 == ( 0x7f & msg [ 1 ] ) ) {
348
+ const pk = parsepk( msg )
349
+ if( 101 == pk.pt ) {
266
350
  dtmfpkcount++
267
351
  } else {
268
352
  expect( msg.length ).to.equal( 172 )
269
- expect( 0x7f & msg [ 1 ] ).to.equal( 0 )
353
+ expect( pk.pt ).to.equal( 0 )
270
354
  }
271
355
  } )
272
356
 
@@ -904,8 +904,7 @@ describe( "channel mix", function() {
904
904
  expect( endpointbpkcountzero ).to.be.within( 65, 75 )
905
905
  expect( endpointcpkcountzero ).to.be.within( 65, 75 )
906
906
  expect( endpointapkcountnotzero ).to.be.within( 4, 12 )
907
- expect( endpointbpkcountnotzero ).to.be.within( 4
908
- , 12 )
907
+ expect( endpointbpkcountnotzero ).to.be.within( 4, 12 )
909
908
  expect( endpointcpkcountnotzero ).to.be.below( 2 )
910
909
 
911
910
  await finished