OSDN Git Service

Add MS7619SE
[uclinux-h8/uClinux-dist.git] / lib / libopenh323 / src / codecs.cxx
1 /*
2  * codecs.cxx
3  *
4  * H.323 protocol handler
5  *
6  * Open H323 Library
7  *
8  * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
9  *
10  * The contents of this file are subject to the Mozilla Public License
11  * Version 1.0 (the "License"); you may not use this file except in
12  * compliance with the License. You may obtain a copy of the License at
13  * http://www.mozilla.org/MPL/
14  *
15  * Software distributed under the License is distributed on an "AS IS"
16  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17  * the License for the specific language governing rights and limitations
18  * under the License.
19  *
20  * The Original Code is Open H323 Library.
21  *
22  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23  *
24  * Portions of this code were written with the assisance of funding from
25  * Vovida Networks, Inc. http://www.vovida.com.
26  *
27  * Contributor(s): ______________________________________.
28  *
29  * $Log: codecs.cxx,v $
30  * Revision 1.92  2006/05/16 11:28:58  shorne
31  * added AEC support and  more call hold support.
32  *
33  * Revision 1.91  2006/01/26 03:31:09  shorne
34  * Add the ability to remove a local input device when placing a call on hold
35  *
36  * Revision 1.90  2005/01/03 06:25:54  csoutheren
37  * Added extensive support for disabling code modules at compile time
38  *
39  * Revision 1.89  2004/11/29 06:30:53  csoutheren
40  * Added support for wideband codecs
41  *
42  * Revision 1.88  2004/07/03 06:49:28  rjongbloed
43  * Split video temporal/spatial trade off H.245 packets to separate command and
44  *   indication functions and added quality parameter, thanks Guilhem Tardy.
45  * Added PTRACE_PARAM() macro to fix warnings on parameters used in PTRACE
46  *  macros only.
47  *
48  * Revision 1.87  2004/05/09 10:22:26  csoutheren
49  * Changed new DecodeFrame to handle bytes per frame
50  *
51  * Revision 1.86  2004/05/09 10:08:36  csoutheren
52  * Changed new DecodeFrame to return bytes decoded rather than samples decoded
53  * Added support for new DecodeFrame to plugin manager
54  *
55  * Revision 1.85  2004/05/02 04:52:24  rjongbloed
56  * Fixed problems with G.711 caused by fixing problem with G.723.1-5k3 mode.
57  *
58  * Revision 1.84  2004/04/16 04:04:28  csoutheren
59  * Prevent codecs with variable length frrames from doing strange things
60  *
61  * Revision 1.83  2004/02/04 10:29:27  rjongbloed
62  * Fixed G.726 by allowing for more bits per pixels sizes in streamed codec, thanks Kevin Bouchard
63  *
64  * Revision 1.82  2003/11/12 11:14:51  csoutheren
65  * Added H323FramedAudioCodec::DecodeSilenceFrame thanks to Henry Harrison of AliceStreet
66  *
67  * Revision 1.81  2003/07/16 10:43:13  csoutheren
68  * Added SwapChannel function to H323Codec to allow media hold channels
69  * to work better. Thanks to Federico Pinna
70  *
71  * Revision 1.80  2002/12/16 09:11:19  robertj
72  * Added new video bit rate control, thanks Walter H. Whitlock
73  *
74  * Revision 1.79  2002/08/05 10:03:47  robertj
75  * Cosmetic changes to normalise the usage of pragma interface/implementation.
76  *
77  * Revision 1.78  2002/05/29 04:48:48  robertj
78  * Changed framed codec so if cannot decode frame just plays silence instead
79  *   of returning error and thus shutting down channel, thanks Federico Pinna
80  *
81  * Revision 1.77  2002/04/16 03:27:54  dereks
82  * Correct logical flaw in CloseRawDataChannel method.
83  *
84  * Revision 1.76  2002/04/05 00:52:17  dereks
85  * Minor tweaks to cope with received h261 messages.
86  *
87  * Revision 1.75  2002/02/26 18:00:18  rogerh
88  * Improve the information given in the trace for codec truncation
89  *
90  * Revision 1.74  2002/01/23 06:13:56  robertj
91  * Added filter function hooks to codec raw data channel.
92  *
93  * Revision 1.73  2002/01/23 01:58:28  robertj
94  * Added function to determine if codecs raw data channel is native format.
95  *
96  * Revision 1.72  2002/01/22 16:09:38  rogerh
97  * Back out the DTMF detection from H323FramedAudioCodec::Write().
98  * There will shortly be a better place for it.
99  *
100  * Revision 1.71  2002/01/22 15:21:47  rogerh
101  * Add DTMF decoding to PCM audio streams. This has been tested with
102  * NetMeeting sending Dial Pad codes, using the G.711 codec.
103  * At this time, DTMF codes (fron NetMeeting) are just displayed on the
104  * screen and are not passed up to the users application.
105  *
106  * Revision 1.70  2002/01/13 23:55:21  robertj
107  * Added mutex so can change raw data channel while reading/writing from codec.
108  *
109  * Revision 1.69  2002/01/06 05:34:05  robertj
110  * Fixed encoding error for 4 bit streamed codecs.
111  *
112  * Revision 1.68  2001/12/04 05:13:12  robertj
113  * Added videa bandwidth limiting code for H.261, thanks Jose Luis Urien.
114  *
115  * Revision 1.67  2001/11/28 00:09:14  dereks
116  * Additional information in PTRACE output.
117  *
118  * Revision 1.66  2001/11/16 01:05:35  craigs
119  * Changed to allow access to uLaw/ALaw to/from linear functions
120  *
121  * Revision 1.65  2001/10/23 02:17:16  dereks
122  * Initial release of cu30 video codec.
123  *
124  * Revision 1.64  2001/09/25 03:14:47  dereks
125  * Add constant bitrate control for the h261 video codec.
126  * Thanks Tiziano Morganti for the code to set bit rate. Good work!
127  *
128  * Revision 1.63  2001/09/21 02:50:06  robertj
129  * Implemented static object for all "known" media formats.
130  *
131  * Revision 1.62  2001/09/12 07:48:05  robertj
132  * Fixed various problems with tracing.
133  *
134  * Revision 1.61  2001/09/11 01:24:36  robertj
135  * Added conditional compilation to remove video and/or audio codecs.
136  *
137  * Revision 1.60  2001/08/06 03:08:56  robertj
138  * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
139  *
140  * Revision 1.59  2001/04/03 09:34:13  robertj
141  * Fixed output of partial frames when short changed by transmitter with G.711
142  *
143  * Revision 1.58  2001/03/29 23:45:08  robertj
144  * Added ability to get current silence detect state and threshold.
145  * Changed default signal on deadband time to be much shorter.
146  *
147  * Revision 1.57  2001/02/09 05:13:55  craigs
148  * Added pragma implementation to (hopefully) reduce the executable image size
149  * under Linux
150  *
151  * Revision 1.56  2001/01/25 07:27:16  robertj
152  * Major changes to add more flexible OpalMediaFormat class to normalise
153  *   all information about media types, especially codecs.
154  *
155  * Revision 1.55  2000/12/19 22:33:44  dereks
156  * Adjust so that the video channel is used for reading/writing raw video
157  * data, which better modularizes the video codec.
158  *
159  * Revision 1.54  2000/09/22 01:35:49  robertj
160  * Added support for handling LID's that only do symmetric codecs.
161  *
162  * Revision 1.53  2000/08/31 08:15:41  robertj
163  * Added support for dynamic RTP payload types in H.245 OpenLogicalChannel negotiations.
164  *
165  * Revision 1.52  2000/07/14 14:08:10  robertj
166  * Fixed stream based codec so can support stream "frames" less than maximum specified.
167  *
168  * Revision 1.51  2000/05/16 02:04:17  craigs
169  * Added access functions for silence compression mode
170  *
171  * Revision 1.50  2000/05/04 11:52:35  robertj
172  * Added Packets Too Late statistics, requiring major rearrangement of jitter
173  *    buffer code, not also changes semantics of codec Write() function slightly.
174  *
175  * Revision 1.49  2000/05/02 04:32:26  robertj
176  * Fixed copyright notice comment.
177  *
178  * Revision 1.48  2000/04/28 12:58:37  robertj
179  * Changed silence detection code so does not PTRACE unless threshold actually changes.
180  *
181  * Revision 1.47  2000/04/10 18:52:45  robertj
182  * Improved "bootstrap" of silence detection algorithm.
183  *
184  * Revision 1.46  2000/03/23 03:00:06  robertj
185  * Changed framed codec so only writes max of bytesPerFrame regardless of length.
186  *
187  * Revision 1.45  2000/02/04 05:11:19  craigs
188  * Updated for new Makefiles and for new video transmission code
189  *
190  * Revision 1.44  2000/01/13 04:03:45  robertj
191  * Added video transmission
192  *
193  * Revision 1.43  1999/12/31 00:05:36  robertj
194  * Added Microsoft ACM G.723.1 codec capability.
195  *
196  * Revision 1.42  1999/12/23 23:02:35  robertj
197  * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
198  *
199  * Revision 1.41  1999/12/21 07:36:43  craigs
200  * Fixed problem in H323VideoCodec destructor that caused hang or segv on exit
201  *
202  * Revision 1.40  1999/11/29 08:59:09  craigs
203  * Added new code for new video code interface
204  *
205  * Revision 1.39  1999/11/29 04:50:11  robertj
206  * Added adaptive threshold calculation to silence detection.
207  *
208  * Revision 1.38  1999/11/20 00:53:47  robertj
209  * Fixed ability to have variable sized frames in single RTP packet under G.723.1
210  *
211  * Revision 1.37  1999/11/13 14:10:59  robertj
212  * Changes to make silence detection selectable.
213  *
214  * Revision 1.36  1999/11/11 23:28:46  robertj
215  * Added first cut silence detection algorithm.
216  *
217  * Revision 1.35  1999/11/04 00:45:07  robertj
218  * Added extra constructors for nonStandard codecs and fixed receiveAndTransmitAudioCapability problem.
219  *
220  * Revision 1.34  1999/11/01 00:51:13  robertj
221  * Fixed problem where codec close does not dispose of attached channel.
222  *
223  * Revision 1.33  1999/10/19 00:04:57  robertj
224  * Changed OpenAudioChannel and OpenVideoChannel to allow a codec AttachChannel with no autodelete.
225  *
226  * Revision 1.32  1999/10/14 12:02:40  robertj
227  * Fixed assignment of t35 info in nonstandard capabilities (wrong way around).
228  *
229  * Revision 1.31  1999/10/10 23:00:15  craigs
230  * Fixed problem with raw channel ptrs not being NULLed out after deletion
231  *
232  * Revision 1.30  1999/10/09 02:15:08  craigs
233  * Added codec to OpenVideoDevice and OpenAudioChannel
234  *
235  * Revision 1.29  1999/10/09 01:20:48  robertj
236  * Fixed error in G711 packet size and trace message
237  *
238  * Revision 1.28  1999/10/08 09:59:03  robertj
239  * Rewrite of capability for sending multiple audio frames
240  *
241  * Revision 1.27  1999/10/08 08:32:22  robertj
242  * Fixed misleading trace text.
243  *
244  * Revision 1.26  1999/10/08 04:58:38  robertj
245  * Added capability for sending multiple audio frames in single RTP packet
246  *
247  * Revision 1.25  1999/09/23 07:25:12  robertj
248  * Added open audio and video function to connection and started multi-frame codec send functionality.
249  *
250  * Revision 1.24  1999/09/21 14:51:34  robertj
251  * Fixed NonStandardCapabilityInfo class virtual destructor (and name).
252  *
253  * Revision 1.23  1999/09/21 14:14:36  robertj
254  * Added non-standard codec capability classes
255  *
256  * Revision 1.22  1999/09/21 08:10:03  craigs
257  * Added support for video devices and H261 codec
258  *
259  * Revision 1.21  1999/09/18 13:24:38  craigs
260  * Added ability to disable jitter buffer
261  * Added ability to access entire RTP packet in codec Write
262  *
263  * Revision 1.20  1999/09/13 13:59:14  robertj
264  * Removed incorrect comment.
265  *
266  * Revision 1.19  1999/09/08 04:05:49  robertj
267  * Added support for video capabilities & codec, still needs the actual codec itself!
268  *
269  * Revision 1.18  1999/08/31 12:34:18  robertj
270  * Added gatekeeper support.
271  *
272  * Revision 1.17  1999/08/25 05:05:36  robertj
273  * Added UserInput capability.
274  * Allowed the attachment of a channel on a codec to optionally delete the channel object,
275  * Improved opening of audio codecs, PSoundChannel creation now in endpoint.
276  *
277  * Revision 1.16  1999/07/16 16:05:48  robertj
278  * Added "human readable" codec type name display.
279  *
280  * Revision 1.15  1999/07/16 15:01:30  robertj
281  * Added message print when starting GSM codec.
282  *
283  * Revision 1.14  1999/07/15 14:45:36  robertj
284  * Added propagation of codec open error to shut down logical channel.
285  * Fixed control channel start up bug introduced with tunnelling.
286  *
287  * Revision 1.13  1999/07/13 09:53:24  robertj
288  * Fixed some problems with jitter buffer and added more debugging.
289  *
290  * Revision 1.12  1999/07/10 02:42:53  robertj
291  * Fixed interopability problem with NetMetting 2.1 G711 capability.
292  *
293  * Revision 1.11  1999/07/09 06:09:49  robertj
294  * Major implementation. An ENORMOUS amount of stuff added everywhere.
295  *
296  * Revision 1.10  1999/06/24 13:32:45  robertj
297  * Fixed ability to change sound device on codec and fixed NM3 G.711 compatibility
298  *
299  * Revision 1.9  1999/06/22 13:49:40  robertj
300  * Added GSM support and further RTP protocol enhancements.
301  *
302  * Revision 1.8  1999/06/14 15:08:40  robertj
303  * Added GSM codec class frame work (still no actual codec).
304  *
305  * Revision 1.7  1999/06/14 08:44:58  robertj
306  * Fixed sound buffers to be correct size for stream based audio.
307  * GNU C++ compatibility
308  *
309  * Revision 1.6  1999/06/14 06:39:08  robertj
310  * Fixed problem with getting transmit flag to channel from PDU negotiator
311  *
312  * Revision 1.5  1999/06/14 05:15:55  robertj
313  * Changes for using RTP sessions correctly in H323 Logical Channel context
314  *
315  * Revision 1.4  1999/06/13 12:41:14  robertj
316  * Implement logical channel transmitter.
317  * Fixed H245 connect on receiving call.
318  *
319  * Revision 1.3  1999/06/09 05:26:19  robertj
320  * Major restructuring of classes.
321  *
322  * Revision 1.2  1999/06/06 06:06:36  robertj
323  * Changes for new ASN compiler and v2 protocol ASN files.
324  *
325  * Revision 1.1  1999/01/16 01:31:04  robertj
326  * Initial revision
327  *
328  */
329
330 #include <ptlib.h>
331
332 #ifdef __GNUC__
333 #pragma implementation "codecs.h"
334 #endif
335
336 #include "codecs.h"
337
338 #include "channels.h"
339 #include "h323pdu.h"
340 #include "h323con.h"
341
342 #ifdef HAS_AEC
343 #include <ptclib/paec.h>
344 #pragma comment(lib,"paec.lib")
345 #endif
346
347 #define new PNEW
348
349
350 extern "C" {
351   unsigned char linear2ulaw(int pcm_val);
352   int ulaw2linear(unsigned char u_val);
353   unsigned char linear2alaw(int pcm_val);
354   int alaw2linear(unsigned char u_val);
355 };
356
357
358 /////////////////////////////////////////////////////////////////////////////
359
360 H323Codec::H323Codec(const char * fmt, Direction dir)
361   : mediaFormat(fmt)
362 {
363   logicalChannel = NULL;
364   direction = dir;
365
366   lastSequenceNumber = 1;
367   rawDataChannel = NULL;
368   deleteChannel  = FALSE;
369 }
370
371
372 BOOL H323Codec::Open(H323Connection & /*connection*/)
373 {
374   return TRUE;
375 }
376
377
378 unsigned H323Codec::GetFrameRate() const
379 {
380   return mediaFormat.GetFrameTime();
381 }
382
383
384 void H323Codec::OnFlowControl(long PTRACE_PARAM(bitRateRestriction))
385 {
386   PTRACE(3, "Codec\tOnFlowControl: " << bitRateRestriction);
387 }
388
389
390 void H323Codec::OnMiscellaneousCommand(const H245_MiscellaneousCommand_type & PTRACE_PARAM(type))
391 {
392   PTRACE(3, "Codec\tOnMiscellaneousCommand: " << type.GetTagName());
393 }
394
395
396 void H323Codec::OnMiscellaneousIndication(const H245_MiscellaneousIndication_type & PTRACE_PARAM(type))
397 {
398   PTRACE(3, "Codec\tOnMiscellaneousIndication: " << type.GetTagName());
399 }
400
401
402 BOOL H323Codec::AttachChannel(PChannel * channel, BOOL autoDelete)
403 {
404   PWaitAndSignal mutex(rawChannelMutex);
405
406   CloseRawDataChannel();
407
408   rawDataChannel = channel;
409   deleteChannel = autoDelete;
410
411   if (channel == NULL){
412         PTRACE(3, "Codec\tError attaching channel. channel is NULL");
413     return FALSE;
414   }
415
416   return channel->IsOpen();
417 }
418
419 PChannel * H323Codec::SwapChannel(PChannel * newChannel, BOOL autoDelete)
420 {
421   PWaitAndSignal mutex(rawChannelMutex);
422
423   PChannel * oldChannel = rawDataChannel;
424
425   rawDataChannel = newChannel;
426   deleteChannel = autoDelete;
427
428   return oldChannel;
429 }
430
431
432 BOOL H323Codec::CloseRawDataChannel()
433 {
434   if (rawDataChannel == NULL)
435     return FALSE;
436   
437   BOOL closeOK = rawDataChannel->Close();
438   
439   if (deleteChannel) {
440      delete rawDataChannel;
441      rawDataChannel = NULL;
442   }
443   
444   return closeOK;
445 }  
446
447
448 BOOL H323Codec::IsRawDataChannelNative() const
449 {
450   return FALSE;
451 }
452
453
454 BOOL H323Codec::ReadRaw(void * data, PINDEX size, PINDEX & length)
455 {
456   if (rawDataChannel == NULL) {
457     PTRACE(1, "Codec\tNo audio channel for read");
458     return FALSE;
459   }
460
461   if (!rawDataChannel->Read(data, size)) {
462     PTRACE(1, "Codec\tAudio read failed: " << rawDataChannel->GetErrorText(PChannel::LastReadError));
463     return FALSE;
464   }
465
466   length = rawDataChannel->GetLastReadCount();
467
468   for (PINDEX i = 0; i < filters.GetSize(); i++) {
469     FilterInfo info(*this, data, size, length);
470     filters[i](info, 0);
471     length = info.bufferLength;
472   }
473
474   return TRUE;
475 }
476
477
478 BOOL H323Codec::WriteRaw(void * data, PINDEX length)
479 {
480   if (rawDataChannel == NULL) {
481     PTRACE(1, "Codec\tNo audio channel for write");
482     return FALSE;
483   }
484
485   for (PINDEX i = 0; i < filters.GetSize(); i++) {
486     FilterInfo info(*this, data, length, length);
487     filters[i](info, 0);
488     length = info.bufferLength;
489   }
490
491   if (rawDataChannel->Write(data, length))
492     return TRUE;
493
494   PTRACE(1, "Codec\tWrite failed: " << rawDataChannel->GetErrorText(PChannel::LastWriteError));
495   return FALSE;
496 }
497
498
499 BOOL H323Codec::AttachLogicalChannel(H323Channel *channel)
500 {
501   logicalChannel = channel;
502
503   return TRUE;
504 }
505
506
507 void H323Codec::AddFilter(const PNotifier & notifier)
508 {
509   rawChannelMutex.Wait();
510   filters.Append(new PNotifier(notifier));
511   rawChannelMutex.Signal();
512 }
513
514 BOOL H323Codec::SetRawDataHeld(BOOL /*hold*/) 
515 {
516         return FALSE;
517 }
518
519 /////////////////////////////////////////////////////////////////////////////
520
521 #ifndef NO_H323_VIDEO
522
523 H323VideoCodec::H323VideoCodec(const char * fmt, Direction dir)
524   : H323Codec(fmt, dir)
525 {
526   frameWidth = frameHeight = 0;
527   targetFrameTimeMs = 0;
528   videoBitRateControlModes = None;
529
530   oldLength = 0;
531   oldTime = 0;
532   newTime = 0;
533 }
534
535
536 H323VideoCodec::~H323VideoCodec()
537 {
538   Close();    //The close operation may delete the rawDataChannel.
539 }
540
541
542 BOOL H323VideoCodec::Open(H323Connection & connection)
543 {
544   return connection.OpenVideoChannel(direction == Encoder, *this);
545 }
546
547
548 void H323VideoCodec::OnMiscellaneousCommand(const H245_MiscellaneousCommand_type & type)
549 {
550   switch (type.GetTag()) {
551     case H245_MiscellaneousCommand_type::e_videoFreezePicture :
552       OnFreezePicture();
553       break;
554
555     case H245_MiscellaneousCommand_type::e_videoFastUpdatePicture :
556       OnFastUpdatePicture();
557       break;
558
559     case H245_MiscellaneousCommand_type::e_videoFastUpdateGOB :
560     {
561       const H245_MiscellaneousCommand_type_videoFastUpdateGOB & fuGOB = type;
562       OnFastUpdateGOB(fuGOB.m_firstGOB, fuGOB.m_numberOfGOBs);
563       break;
564     }
565
566     case H245_MiscellaneousCommand_type::e_videoFastUpdateMB :
567     {
568       const H245_MiscellaneousCommand_type_videoFastUpdateMB & fuMB = type;
569       OnFastUpdateMB(fuMB.HasOptionalField(H245_MiscellaneousCommand_type_videoFastUpdateMB::e_firstGOB) ? (int)fuMB.m_firstGOB : -1,
570                      fuMB.HasOptionalField(H245_MiscellaneousCommand_type_videoFastUpdateMB::e_firstMB)  ? (int)fuMB.m_firstMB  : -1,
571                      fuMB.m_numberOfMBs);
572       break;
573     }
574
575     case H245_MiscellaneousCommand_type::e_lostPartialPicture :
576       OnLostPartialPicture();
577       break;
578
579     case H245_MiscellaneousCommand_type::e_lostPicture :
580       OnLostPicture();
581       break;
582
583     case H245_MiscellaneousCommand_type::e_videoTemporalSpatialTradeOff :
584     {
585       const PASN_Integer & newQuality = type;
586       OnVideoTemporalSpatialTradeOffCommand(newQuality);
587       break;
588     }
589   }
590
591   H323Codec::OnMiscellaneousCommand(type);
592 }
593
594
595 void H323VideoCodec::OnFreezePicture()
596 {
597   PTRACE(3, "Codec\tOnFreezePicture()");
598 }
599
600
601 void H323VideoCodec::OnFastUpdatePicture()
602 {
603   PTRACE(3, "Codec\tOnFastUpdatePicture()");
604 }
605
606
607 void H323VideoCodec::OnFastUpdateGOB(unsigned PTRACE_PARAM(firstGOB),
608                                      unsigned PTRACE_PARAM(numberOfGOBs))
609 {
610   PTRACE(3, "Codecs\tOnFastUpdateGOB(" << firstGOB << ',' << numberOfGOBs << ')');
611 }
612
613
614 void H323VideoCodec::OnFastUpdateMB(int PTRACE_PARAM(firstGOB),
615                                     int PTRACE_PARAM(firstMB),
616                                     unsigned PTRACE_PARAM(numberOfMBs))
617 {
618   PTRACE(3, "Codecs\tOnFastUpdateMB(" << firstGOB << ',' << firstMB << ',' << numberOfMBs << ')');
619 }
620
621
622 void H323VideoCodec::OnLostPartialPicture()
623 {
624   PTRACE(3, "Codec\tOnLostPartialPicture()");
625 }
626
627
628 void H323VideoCodec::OnLostPicture()
629 {
630   PTRACE(3, "Codec\tOnLostPicture()");
631 }
632
633
634 void H323VideoCodec::OnMiscellaneousIndication(const H245_MiscellaneousIndication_type & type)
635 {
636   switch (type.GetTag()) {
637     case H245_MiscellaneousIndication_type::e_videoIndicateReadyToActivate :
638       OnVideoIndicateReadyToActivate();
639       break;
640
641     case H245_MiscellaneousIndication_type::e_videoTemporalSpatialTradeOff :
642     {
643       const PASN_Integer & newQuality = type;
644       OnVideoTemporalSpatialTradeOffIndication(newQuality);
645       break;
646     }
647
648     case H245_MiscellaneousIndication_type::e_videoNotDecodedMBs :
649     {
650       const H245_MiscellaneousIndication_type_videoNotDecodedMBs & vndMB = type;
651       OnVideoNotDecodedMBs(vndMB.m_firstMB, vndMB.m_numberOfMBs, vndMB.m_temporalReference);
652       break;
653     }
654   }
655
656   H323Codec::OnMiscellaneousIndication(type);
657 }
658
659
660 void H323VideoCodec::OnVideoIndicateReadyToActivate()
661 {
662   PTRACE(3, "Codec\tOnVideoIndicateReadyToActivate()");
663 }
664
665
666 void H323VideoCodec::OnVideoTemporalSpatialTradeOffCommand(int PTRACE_PARAM(newQuality))
667 {
668   PTRACE(3, "Codecs\tOnVideoTemporalSpatialTradeOffCommand(" << newQuality << ')');
669 }
670
671
672 void H323VideoCodec::OnVideoTemporalSpatialTradeOffIndication(int PTRACE_PARAM(newQuality))
673 {
674   PTRACE(3, "Codecs\tOnVideoTemporalSpatialTradeOffIndication(" << newQuality << ')');
675 }
676
677
678 void H323VideoCodec::OnVideoNotDecodedMBs(unsigned PTRACE_PARAM(firstMB),
679                                           unsigned PTRACE_PARAM(numberOfMBs),
680                                           unsigned PTRACE_PARAM(temporalReference))
681 {
682   PTRACE(3, "Codecs\tOnVideoNotDecodedMBs(" << firstMB << ',' << numberOfMBs << ',' << temporalReference << ')');
683 }
684
685
686 void H323VideoCodec::Close()
687 {
688   PWaitAndSignal mutex1(videoHandlerActive);  
689
690   CloseRawDataChannel();
691 }
692
693
694 BOOL H323VideoCodec::SetMaxBitRate(unsigned bitRate)
695 {
696   PTRACE(1,"Set bitRateHighLimit for video to " << bitRate << " bps");
697         
698   bitRateHighLimit = bitRate;
699
700   if (0 == bitRateHighLimit) // disable bitrate control
701     videoBitRateControlModes &= ~AdaptivePacketDelay;
702   return TRUE;
703 }
704
705 BOOL H323VideoCodec::SetTargetFrameTimeMs(unsigned ms)
706 {
707   PTRACE(1,"Set targetFrameTimeMs for video to " << ms << " milliseconds");
708
709   targetFrameTimeMs = ms;
710
711   if (0 == targetFrameTimeMs)
712     videoBitRateControlModes &= ~DynamicVideoQuality;
713   return TRUE;
714 }
715
716
717 void H323VideoCodec::SendMiscCommand(unsigned command)
718 {
719   if (logicalChannel != NULL)
720     logicalChannel->SendMiscCommand(command);
721 }
722
723
724 #endif // NO_H323_VIDEO
725
726
727 /////////////////////////////////////////////////////////////////////////////
728
729 #ifndef NO_H323_AUDIO_CODECS
730
731 H323AudioCodec::H323AudioCodec(const char * fmt, Direction dir)
732   : H323Codec(fmt, dir)
733 {
734   samplesPerFrame = (mediaFormat.GetFrameTime() * mediaFormat.GetTimeUnits()) / 8;
735   if (samplesPerFrame == 0)
736     samplesPerFrame = 8; // Default for non-frame based codecs.
737
738   // Start off in silent mode
739   inTalkBurst = FALSE;
740
741   IsRawDataHeld = FALSE;
742
743   // Initialise the adaptive threshold variables.
744   SetSilenceDetectionMode(AdaptiveSilenceDetection);
745 }
746
747
748 H323AudioCodec::~H323AudioCodec()
749 {
750   Close();
751
752   CloseRawDataChannel();
753 }
754
755
756 BOOL H323AudioCodec::Open(H323Connection & connection)
757 {
758   return connection.OpenAudioChannel(direction == Encoder, samplesPerFrame*2, *this);
759 }
760
761
762 void H323AudioCodec::Close()
763 {
764   PWaitAndSignal mutex(rawChannelMutex);
765
766   if (rawDataChannel != NULL)
767     rawDataChannel->Close();
768 }
769
770
771 unsigned H323AudioCodec::GetFrameRate() const
772 {
773   return samplesPerFrame;
774 }
775
776
777 H323AudioCodec::SilenceDetectionMode H323AudioCodec::GetSilenceDetectionMode(
778                                 BOOL * isInTalkBurst, unsigned * currentThreshold) const
779 {
780   if (isInTalkBurst != NULL)
781     *isInTalkBurst = inTalkBurst;
782
783   if (currentThreshold != NULL)
784     *currentThreshold = ulaw2linear((BYTE)(levelThreshold ^ 0xff));
785
786   return silenceDetectMode;
787 }
788
789
790 void H323AudioCodec::SetSilenceDetectionMode(SilenceDetectionMode mode,
791                                              unsigned threshold,
792                                              unsigned signalDeadband,
793                                              unsigned silenceDeadband,
794                                              unsigned adaptivePeriod)
795 {
796   silenceDetectMode = mode;
797
798   // The silence deadband is the number of frames of low energy that have to
799   // occur before the system stops sending data over the RTP link.
800   signalDeadbandFrames = (signalDeadband+samplesPerFrame-1)/samplesPerFrame;
801   silenceDeadbandFrames = (silenceDeadband+samplesPerFrame-1)/samplesPerFrame;
802
803   // This is the period over which the adaptive algorithm operates
804   adaptiveThresholdFrames = (adaptivePeriod+samplesPerFrame-1)/samplesPerFrame;
805
806   if (mode != AdaptiveSilenceDetection) {
807     levelThreshold = threshold;
808     return;
809   }
810
811   // Initials threshold levels
812   levelThreshold = 0;
813
814   // Initialise the adaptive threshold variables.
815   signalMinimum = UINT_MAX;
816   silenceMaximum = 0;
817   signalFramesReceived = 0;
818   silenceFramesReceived = 0;
819
820   // Restart in silent mode
821   inTalkBurst = FALSE;
822 }
823
824
825 BOOL H323AudioCodec::DetectSilence()
826 {
827   // Can never have silence if NoSilenceDetection
828   if (silenceDetectMode == NoSilenceDetection)
829     return FALSE;
830
831   // Can never have average signal level that high, this indicates that the
832   // hardware cannot do silence detection.
833   unsigned level = GetAverageSignalLevel();
834   if (level == UINT_MAX)
835     return FALSE;
836
837   // Convert to a logarithmic scale - use uLaw which is complemented
838   level = linear2ulaw(level) ^ 0xff;
839
840   // Now if signal level above threshold we are "talking"
841   BOOL haveSignal = level > levelThreshold;
842
843   // If no change ie still talking or still silent, resent frame counter
844   if (inTalkBurst == haveSignal)
845     framesReceived = 0;
846   else {
847     framesReceived++;
848     // If have had enough consecutive frames talking/silent, swap modes.
849     if (framesReceived >= (inTalkBurst ? silenceDeadbandFrames : signalDeadbandFrames)) {
850       inTalkBurst = !inTalkBurst;
851       PTRACE(4, "Codec\tSilence detection transition: "
852              << (inTalkBurst ? "Talk" : "Silent")
853              << " level=" << level << " threshold=" << levelThreshold);
854
855       // If we had talk/silence transition restart adaptive threshold measurements
856       signalMinimum = UINT_MAX;
857       silenceMaximum = 0;
858       signalFramesReceived = 0;
859       silenceFramesReceived = 0;
860     }
861   }
862
863   if (silenceDetectMode == FixedSilenceDetection)
864     return !inTalkBurst;
865
866   if (levelThreshold == 0) {
867     if (level > 1) {
868       // Bootstrap condition, use first frame level as silence level
869       levelThreshold = level/2;
870       PTRACE(4, "Codec\tSilence detection threshold initialised to: " << levelThreshold);
871     }
872     return TRUE; // inTalkBurst always FALSE here, so return silent
873   }
874
875   // Count the number of silent and signal frames and calculate min/max
876   if (haveSignal) {
877     if (level < signalMinimum)
878       signalMinimum = level;
879     signalFramesReceived++;
880   }
881   else {
882     if (level > silenceMaximum)
883       silenceMaximum = level;
884     silenceFramesReceived++;
885   }
886
887   // See if we have had enough frames to look at proportions of silence/signal
888   if ((signalFramesReceived + silenceFramesReceived) > adaptiveThresholdFrames) {
889
890     /* Now we have had a period of time to look at some average values we can
891        make some adjustments to the threshold. There are four cases:
892      */
893     if (signalFramesReceived >= adaptiveThresholdFrames) {
894       /* If every frame was noisy, move threshold up. Don't want to move too
895          fast so only go a quarter of the way to minimum signal value over the
896          period. This avoids oscillations, and time will continue to make the
897          level go up if there really is a lot of background noise.
898        */
899       int delta = (signalMinimum - levelThreshold)/4;
900       if (delta != 0) {
901         levelThreshold += delta;
902         PTRACE(4, "Codec\tSilence detection threshold increased to: " << levelThreshold);
903       }
904     }
905     else if (silenceFramesReceived >= adaptiveThresholdFrames) {
906       /* If every frame was silent, move threshold down. Again do not want to
907          move too quickly, but we do want it to move faster down than up, so
908          move to halfway to maximum value of the quiet period. As a rule the
909          lower the threshold the better as it would improve response time to
910          the start of a talk burst.
911        */
912       unsigned newThreshold = (levelThreshold + silenceMaximum)/2 + 1;
913       if (levelThreshold != newThreshold) {
914         levelThreshold = newThreshold;
915         PTRACE(4, "Codec\tSilence detection threshold decreased to: " << levelThreshold);
916       }
917     }
918     else if (signalFramesReceived > silenceFramesReceived) {
919       /* We haven't got a definitive silent or signal period, but if we are
920          constantly hovering at the threshold and have more signal than
921          silence we should creep up a bit.
922        */
923       levelThreshold++;
924       PTRACE(4, "Codec\tSilence detection threshold incremented to: " << levelThreshold
925              << " signal=" << signalFramesReceived << ' ' << signalMinimum
926              << " silence=" << silenceFramesReceived << ' ' << silenceMaximum);
927     }
928
929     signalMinimum = UINT_MAX;
930     silenceMaximum = 0;
931     signalFramesReceived = 0;
932     silenceFramesReceived = 0;
933   }
934
935   return !inTalkBurst;
936 }
937
938
939 unsigned H323AudioCodec::GetAverageSignalLevel()
940 {
941   return UINT_MAX;
942 }
943
944 BOOL H323AudioCodec::SetRawDataHeld(BOOL hold) { 
945         
946   PTimedMutex m;
947         m.Wait(50);    // wait for 50ms to avoid current locks
948         IsRawDataHeld = hold; 
949         m.Wait(50);     // wait for 50ms to avoid any further locks
950         return TRUE;
951
952
953 /////////////////////////////////////////////////////////////////////////////
954
955 H323FramedAudioCodec::H323FramedAudioCodec(const char * fmt, Direction dir)
956   : H323AudioCodec(fmt, dir),
957     sampleBuffer(samplesPerFrame)
958 {
959   bytesPerFrame = mediaFormat.GetFrameSize();
960 }
961
962
963 BOOL H323FramedAudioCodec::Read(BYTE * buffer, unsigned & length, RTP_DataFrame &)
964 {
965   PWaitAndSignal mutex(rawChannelMutex);
966
967   if (direction != Encoder) {
968     PTRACE(1, "Codec\tAttempt to decode from encoder");
969     return FALSE;
970   }
971
972   if (IsRawDataHeld) {   // If connection is onHold
973     PProcess::Sleep(5);  // Sleep to avoid CPU overload. <--Should be a better method but it works :)
974     length = 0;
975     return TRUE;
976   }
977
978 #ifdef HAS_AEC
979   if (aec != NULL)
980      aec->Send(buffer,length);
981 #endif
982
983   PINDEX numBytes = samplesPerFrame*2;
984   PINDEX count;
985   if (!ReadRaw(sampleBuffer.GetPointer(samplesPerFrame), numBytes, count))
986     return FALSE;
987
988   if (IsRawDataHeld) {
989     length = 0;
990     return TRUE;
991   }
992
993   if (count != numBytes) {
994     PTRACE(1, "Codec\tRead truncated frame of raw data. Wanted " << numBytes << " and got "<<count);
995     return FALSE;
996   }
997
998   if (DetectSilence()) {
999     length = 0;
1000     return TRUE;
1001   }
1002
1003   // Default length is the frame size
1004   length = bytesPerFrame;
1005   return EncodeFrame(buffer, length);
1006 }
1007
1008
1009 BOOL H323FramedAudioCodec::Write(const BYTE * buffer,
1010                                  unsigned length,
1011                                  const RTP_DataFrame & /*rtpFrame*/,
1012                                  unsigned & written)
1013 {
1014   PWaitAndSignal mutex(rawChannelMutex);
1015
1016   if (direction != Decoder) {
1017     PTRACE(1, "Codec\tAttempt to encode from decoder");
1018     return FALSE;
1019   }
1020
1021   // If length is zero then it indicates silence, do nothing.
1022   written = 0;
1023
1024   unsigned bytesDecoded = samplesPerFrame*2;
1025
1026   if (length != 0) {
1027     if (length > bytesPerFrame)
1028       length = bytesPerFrame;
1029     written = bytesPerFrame;
1030
1031     // Decode the data
1032     if (!DecodeFrame(buffer, length, written, bytesDecoded)) {
1033       written = length;
1034       length = 0;
1035     }
1036   }
1037
1038   // was memset(sampleBuffer.GetPointer(samplesPerFrame), 0, bytesDecoded);
1039   if (length == 0)
1040     DecodeSilenceFrame(sampleBuffer.GetPointer(bytesDecoded), bytesDecoded);
1041
1042   // Write as 16bit PCM to sound channel
1043   if (IsRawDataHeld) {          // If Connection om Hold 
1044         PProcess::Sleep(5);     // Sleep to avoid CPU Overload <--- Must be a better way but need it to work.
1045         return TRUE;
1046   } else {
1047       if (!WriteRaw(sampleBuffer.GetPointer(), bytesDecoded)) 
1048                   return FALSE;
1049
1050 #ifdef HAS_AEC
1051            if (aec != NULL)
1052                   aec->Receive((BYTE *)sampleBuffer.GetPointer(), bytesDecoded);
1053 #endif
1054            return TRUE;
1055
1056   }
1057 }
1058
1059
1060 unsigned H323FramedAudioCodec::GetAverageSignalLevel()
1061 {
1062   // Calculate the average signal level of this frame
1063   int sum = 0;
1064
1065   const short * pcm = sampleBuffer;
1066   const short * end = pcm + samplesPerFrame;
1067   while (pcm != end) {
1068     if (*pcm < 0)
1069       sum -= *pcm++;
1070     else
1071       sum += *pcm++;
1072   }
1073
1074   return sum/samplesPerFrame;
1075 }
1076
1077
1078 BOOL H323FramedAudioCodec::DecodeFrame(const BYTE * buffer,
1079                                        unsigned length,
1080                                        unsigned & written,
1081                                        unsigned & /*decodedBytes*/)
1082 {
1083   return DecodeFrame(buffer, length, written);
1084 }
1085
1086
1087 BOOL H323FramedAudioCodec::DecodeFrame(const BYTE * /*buffer*/,
1088                                        unsigned /*length*/,
1089                                        unsigned & /*written*/)
1090 {
1091   PAssertAlways(PUnimplementedFunction);
1092   return FALSE;
1093 }
1094
1095 #if HAS_AEC 
1096 void H323FramedAudioCodec::AttachAEC(PAec * _aec)
1097 {
1098   aec = _aec;
1099 }
1100 #endif
1101
1102 /////////////////////////////////////////////////////////////////////////////
1103
1104 H323StreamedAudioCodec::H323StreamedAudioCodec(const char * fmt,
1105                                                Direction dir,
1106                                                unsigned samples,
1107                                                unsigned bits)
1108   : H323FramedAudioCodec(fmt, dir)
1109 {
1110   samplesPerFrame = samples;
1111   bytesPerFrame = (samples*bits+7)/8;
1112   bitsPerSample = bits;
1113 }
1114
1115
1116 BOOL H323StreamedAudioCodec::EncodeFrame(BYTE * buffer, unsigned &)
1117 {
1118   PINDEX i;
1119   unsigned short position = 0;
1120   BYTE encoded;
1121   switch (bitsPerSample) {
1122     case 8 :
1123       for (i = 0; i < (PINDEX)samplesPerFrame; i++)
1124         *buffer++ = (BYTE)Encode(sampleBuffer[i]);
1125       break;
1126     case 5 : // g.726-40 payload encoding....
1127       for (i = 0; i < (PINDEX)samplesPerFrame;i++)
1128       {
1129         // based on a 40 bits encoding, we have 8 words of 5 bits each
1130         encoded = (BYTE)Encode(sampleBuffer[i]);
1131         switch(position)
1132         {
1133           case 0: // 0 bits overflow
1134             *buffer = encoded;
1135             position++;
1136             break;
1137           case 1: // 2 bits overflow
1138             *buffer++ |= (encoded << 5);
1139             *buffer = (BYTE)(encoded >> 3);
1140             position++;
1141             break;
1142           case 2: 
1143             *buffer |= (encoded << 2);
1144             position++;
1145             break;
1146           case 3: // one bit left for word 4
1147             *buffer++ |= (encoded << 7);
1148             *buffer = (BYTE)(encoded >> 1);
1149             position++;
1150             break;
1151           case 4:
1152             *buffer++ |= (encoded << 4);
1153             *buffer = (BYTE)(encoded >> 4);
1154             position++;
1155             break;
1156           case 5:
1157             *buffer |= (encoded << 1);
1158             position++;
1159             break;
1160           case 6: //two bits left for the new encoded word
1161             *buffer++ |= (encoded << 6);
1162             *buffer =  (BYTE)(encoded >> 2);
1163             position++;
1164             break;
1165           case 7: // now five bits left for the last word
1166             *buffer++ |= (encoded << 3);
1167             position = 0;
1168             break;
1169         }
1170       }
1171       break;
1172
1173     case 4 :
1174       for (i = 0; i < (PINDEX)samplesPerFrame; i++) {
1175         if ((i&1) == 0)
1176           *buffer = (BYTE)Encode(sampleBuffer[i]);
1177         else
1178           *buffer++ |= (BYTE)(Encode(sampleBuffer[i]) << 4);
1179       }
1180       break;
1181
1182     case 3 :
1183       for (i = 0;i < (PINDEX)samplesPerFrame;i++)
1184       {
1185         encoded = (BYTE)Encode(sampleBuffer[i]);
1186         switch(position)
1187         {
1188           case 0: // 0 bits overflow
1189             *buffer = encoded;
1190             position++;
1191             break;
1192           case 1: // 2 bits overflow
1193             *buffer |= (encoded << 3);
1194             position++;
1195             break;
1196           case 2: 
1197             *buffer++ |= (encoded << 6);
1198             *buffer = (BYTE)(encoded >> 2);
1199             position++;
1200             break;
1201           case 3: // one bit left for word 4
1202             *buffer |= (encoded << 1);
1203             position++;
1204             break;
1205           case 4:
1206             *buffer |= (encoded << 4);
1207             position++;
1208             break;
1209           case 5:
1210             *buffer++ |= (encoded << 7);
1211             *buffer = (BYTE)(encoded >> 1);
1212             position++;
1213             break;
1214           case 6: //two bits left for the new encoded word
1215             *buffer |= (encoded << 2);
1216             position++;
1217             break;
1218           case 7: // now five bits left for the last word
1219             *buffer++ |= (encoded << 5);
1220             position = 0;
1221             break;
1222         }
1223       }
1224       break;
1225
1226     case 2:
1227       for (i = 0; i < (PINDEX)samplesPerFrame; i++) 
1228       {
1229         switch(position)
1230         {
1231           case 0:
1232             *buffer = (BYTE)Encode(sampleBuffer[i]);
1233             position++;
1234             break;
1235           case 1:
1236             *buffer |= (BYTE)(Encode(sampleBuffer[i]) << 2);
1237             position++;
1238             break;
1239           case 2:
1240             *buffer |= (BYTE)(Encode(sampleBuffer[i]) << 4);
1241             position++;
1242             break;
1243           case 3:
1244             *buffer++ |= (BYTE)(Encode(sampleBuffer[i]) << 6);
1245             position = 0;
1246             break;
1247         }
1248       }
1249       break;
1250
1251     default :
1252       PAssertAlways("Unsupported bit size");
1253       return FALSE;
1254   }
1255   
1256   return TRUE;
1257 }
1258
1259
1260 BOOL H323StreamedAudioCodec::DecodeFrame(const BYTE * buffer,
1261                                          unsigned length,
1262                                          unsigned & written,
1263                                          unsigned & decodedBytes)
1264 {
1265   unsigned i;
1266   
1267   short * sampleBufferPtr = sampleBuffer.GetPointer(samplesPerFrame);
1268   short * out = sampleBufferPtr;
1269   unsigned short position = 0;
1270   unsigned remaining = 0;
1271   
1272   switch (bitsPerSample) {
1273     case 8 :
1274       for (i = 0; i < length; i++)
1275         *out++ = Decode(*buffer++);
1276       break;
1277
1278     // those case are for ADPCM G.726
1279     case 5 :
1280       for (i = 0; i < length; i++) {
1281         switch(position)
1282         {
1283           case 0:
1284             *out++ = Decode(*buffer & 31);
1285             remaining = *buffer >> 5; // get the three remaining bytes for the next word
1286             buffer++;
1287             position++;
1288             break;
1289           case 1: // we can decode more than one word in second buffer
1290             *out++ = Decode (((*buffer&3) << 3) | remaining);
1291             *out++ = Decode( (*buffer >> 2) & 31);
1292             remaining = *buffer >> 7;
1293             buffer++;
1294             position++;
1295             break;
1296           case 2:
1297             *out++ = Decode( remaining | ((*buffer&15) << 1));
1298             remaining = *buffer >> 4;
1299             buffer++;
1300             position++;
1301             break;
1302           case 3:
1303             *out++ = Decode( remaining | ((*buffer&1) << 4));
1304             *out++ = Decode( (*buffer >> 1) & 31);
1305             remaining = *buffer >> 6;
1306             buffer++;
1307             position++;
1308             break;
1309           case 4 :
1310             *out++ = Decode( remaining | ((*buffer&7) << 2));
1311             *out++ = Decode(*buffer >> 3);
1312             buffer++;
1313             position = 0;
1314             break;
1315         }
1316       }
1317       break;
1318
1319     case 4 :
1320       for (i = 0; i < length; i++) {
1321         *out++ = Decode(*buffer & 15);
1322         *out++ = Decode(*buffer >> 4);
1323         buffer++;
1324       }
1325       break;
1326
1327     case 3:
1328       for (i = 0; i < length; i++) {
1329         switch(position)
1330         {
1331         case 0:
1332           *out++ = Decode(*buffer & 7);
1333           *out++ = Decode((*buffer>>3)&7);
1334           remaining = *buffer >> 6;
1335           buffer++;
1336           position++;
1337           break;
1338         case 1:
1339           *out++ = Decode(remaining | ((*buffer&1) << 2));
1340           *out++ = Decode((*buffer >> 1) & 7);
1341           *out++ = Decode((*buffer >> 4)&7);
1342           remaining = *buffer >> 7;
1343           buffer++;
1344           position++;
1345           break;
1346         case 2:
1347           *out++ = Decode(remaining | ((*buffer&3) << 1));
1348           *out++ = Decode((*buffer >> 2) & 7);
1349           *out++ = Decode((*buffer >> 5) & 7);
1350           buffer++;
1351           position = 0;
1352           break;
1353         }
1354       }
1355       break;
1356
1357     case 2:
1358       for (i = 0; i < length; i++) 
1359       {
1360         *out++ = Decode(*buffer & 3);
1361         *out++ = Decode((*buffer >> 2) & 3);
1362         *out++ = Decode((*buffer >> 4) & 3);
1363         *out++ = Decode((*buffer >> 6) & 3);
1364         buffer++;
1365       
1366       }
1367       break;
1368
1369     default :
1370       PAssertAlways("Unsupported bit size");
1371       return FALSE;
1372   }
1373
1374   written = length;
1375   decodedBytes = (out - sampleBufferPtr)*2;
1376   
1377   return TRUE;
1378 }
1379
1380
1381 /////////////////////////////////////////////////////////////////////////////
1382
1383 H323_ALawCodec::H323_ALawCodec(Direction dir,
1384                                BOOL at56kbps,
1385                                unsigned frameSize)
1386   : H323StreamedAudioCodec(OpalG711ALaw, dir, frameSize, 8)
1387 {
1388   sevenBit = at56kbps;
1389
1390   PTRACE(3, "Codec\tG711 ALaw " << (dir == Encoder ? "en" : "de")
1391          << "coder created for at "
1392          << (sevenBit ? "56k" : "64k") << ", " << frameSize << " samples");
1393 }
1394
1395
1396
1397 int H323_ALawCodec::EncodeSample(short sample)
1398 {
1399   return linear2alaw(sample);
1400 }
1401
1402
1403 short H323_ALawCodec::DecodeSample(int sample)
1404 {
1405   return (short)alaw2linear((unsigned char)sample);
1406 }
1407
1408
1409 /////////////////////////////////////////////////////////////////////////////
1410
1411 H323_muLawCodec::H323_muLawCodec(Direction dir,
1412                                  BOOL at56kbps,
1413                                  unsigned frameSize)
1414   : H323StreamedAudioCodec(OpalG711uLaw, dir, frameSize, 8)
1415 {
1416   sevenBit = at56kbps;
1417
1418   PTRACE(3, "Codec\tG711 uLaw " << (dir == Encoder ? "en" : "de")
1419          << "coder created for at "
1420          << (sevenBit ? "56k" : "64k") << ", frame of " << frameSize << " samples");
1421 }
1422
1423
1424 int H323_muLawCodec::EncodeSample(short sample)
1425 {
1426   return linear2ulaw(sample);
1427 }
1428
1429
1430 short H323_muLawCodec::DecodeSample(int sample)
1431 {
1432   return (short)ulaw2linear((unsigned char)sample);
1433 }
1434
1435
1436 /////////////////////////////////////////////////////////////////////////////
1437
1438 #endif // NO_H323_AUDIO_CODECS