4 * H.323 protocol handler
8 * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
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/
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
20 * The Original Code is Open H323 Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions of this code were written with the assisance of funding from
25 * Vovida Networks, Inc. http://www.vovida.com.
27 * Contributor(s): ______________________________________.
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.
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
36 * Revision 1.90 2005/01/03 06:25:54 csoutheren
37 * Added extensive support for disabling code modules at compile time
39 * Revision 1.89 2004/11/29 06:30:53 csoutheren
40 * Added support for wideband codecs
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
48 * Revision 1.87 2004/05/09 10:22:26 csoutheren
49 * Changed new DecodeFrame to handle bytes per frame
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
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.
58 * Revision 1.84 2004/04/16 04:04:28 csoutheren
59 * Prevent codecs with variable length frrames from doing strange things
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
64 * Revision 1.82 2003/11/12 11:14:51 csoutheren
65 * Added H323FramedAudioCodec::DecodeSilenceFrame thanks to Henry Harrison of AliceStreet
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
71 * Revision 1.80 2002/12/16 09:11:19 robertj
72 * Added new video bit rate control, thanks Walter H. Whitlock
74 * Revision 1.79 2002/08/05 10:03:47 robertj
75 * Cosmetic changes to normalise the usage of pragma interface/implementation.
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
81 * Revision 1.77 2002/04/16 03:27:54 dereks
82 * Correct logical flaw in CloseRawDataChannel method.
84 * Revision 1.76 2002/04/05 00:52:17 dereks
85 * Minor tweaks to cope with received h261 messages.
87 * Revision 1.75 2002/02/26 18:00:18 rogerh
88 * Improve the information given in the trace for codec truncation
90 * Revision 1.74 2002/01/23 06:13:56 robertj
91 * Added filter function hooks to codec raw data channel.
93 * Revision 1.73 2002/01/23 01:58:28 robertj
94 * Added function to determine if codecs raw data channel is native format.
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.
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.
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.
109 * Revision 1.69 2002/01/06 05:34:05 robertj
110 * Fixed encoding error for 4 bit streamed codecs.
112 * Revision 1.68 2001/12/04 05:13:12 robertj
113 * Added videa bandwidth limiting code for H.261, thanks Jose Luis Urien.
115 * Revision 1.67 2001/11/28 00:09:14 dereks
116 * Additional information in PTRACE output.
118 * Revision 1.66 2001/11/16 01:05:35 craigs
119 * Changed to allow access to uLaw/ALaw to/from linear functions
121 * Revision 1.65 2001/10/23 02:17:16 dereks
122 * Initial release of cu30 video codec.
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!
128 * Revision 1.63 2001/09/21 02:50:06 robertj
129 * Implemented static object for all "known" media formats.
131 * Revision 1.62 2001/09/12 07:48:05 robertj
132 * Fixed various problems with tracing.
134 * Revision 1.61 2001/09/11 01:24:36 robertj
135 * Added conditional compilation to remove video and/or audio codecs.
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.
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
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.
147 * Revision 1.57 2001/02/09 05:13:55 craigs
148 * Added pragma implementation to (hopefully) reduce the executable image size
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.
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.
159 * Revision 1.54 2000/09/22 01:35:49 robertj
160 * Added support for handling LID's that only do symmetric codecs.
162 * Revision 1.53 2000/08/31 08:15:41 robertj
163 * Added support for dynamic RTP payload types in H.245 OpenLogicalChannel negotiations.
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.
168 * Revision 1.51 2000/05/16 02:04:17 craigs
169 * Added access functions for silence compression mode
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.
175 * Revision 1.49 2000/05/02 04:32:26 robertj
176 * Fixed copyright notice comment.
178 * Revision 1.48 2000/04/28 12:58:37 robertj
179 * Changed silence detection code so does not PTRACE unless threshold actually changes.
181 * Revision 1.47 2000/04/10 18:52:45 robertj
182 * Improved "bootstrap" of silence detection algorithm.
184 * Revision 1.46 2000/03/23 03:00:06 robertj
185 * Changed framed codec so only writes max of bytesPerFrame regardless of length.
187 * Revision 1.45 2000/02/04 05:11:19 craigs
188 * Updated for new Makefiles and for new video transmission code
190 * Revision 1.44 2000/01/13 04:03:45 robertj
191 * Added video transmission
193 * Revision 1.43 1999/12/31 00:05:36 robertj
194 * Added Microsoft ACM G.723.1 codec capability.
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.
199 * Revision 1.41 1999/12/21 07:36:43 craigs
200 * Fixed problem in H323VideoCodec destructor that caused hang or segv on exit
202 * Revision 1.40 1999/11/29 08:59:09 craigs
203 * Added new code for new video code interface
205 * Revision 1.39 1999/11/29 04:50:11 robertj
206 * Added adaptive threshold calculation to silence detection.
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
211 * Revision 1.37 1999/11/13 14:10:59 robertj
212 * Changes to make silence detection selectable.
214 * Revision 1.36 1999/11/11 23:28:46 robertj
215 * Added first cut silence detection algorithm.
217 * Revision 1.35 1999/11/04 00:45:07 robertj
218 * Added extra constructors for nonStandard codecs and fixed receiveAndTransmitAudioCapability problem.
220 * Revision 1.34 1999/11/01 00:51:13 robertj
221 * Fixed problem where codec close does not dispose of attached channel.
223 * Revision 1.33 1999/10/19 00:04:57 robertj
224 * Changed OpenAudioChannel and OpenVideoChannel to allow a codec AttachChannel with no autodelete.
226 * Revision 1.32 1999/10/14 12:02:40 robertj
227 * Fixed assignment of t35 info in nonstandard capabilities (wrong way around).
229 * Revision 1.31 1999/10/10 23:00:15 craigs
230 * Fixed problem with raw channel ptrs not being NULLed out after deletion
232 * Revision 1.30 1999/10/09 02:15:08 craigs
233 * Added codec to OpenVideoDevice and OpenAudioChannel
235 * Revision 1.29 1999/10/09 01:20:48 robertj
236 * Fixed error in G711 packet size and trace message
238 * Revision 1.28 1999/10/08 09:59:03 robertj
239 * Rewrite of capability for sending multiple audio frames
241 * Revision 1.27 1999/10/08 08:32:22 robertj
242 * Fixed misleading trace text.
244 * Revision 1.26 1999/10/08 04:58:38 robertj
245 * Added capability for sending multiple audio frames in single RTP packet
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.
250 * Revision 1.24 1999/09/21 14:51:34 robertj
251 * Fixed NonStandardCapabilityInfo class virtual destructor (and name).
253 * Revision 1.23 1999/09/21 14:14:36 robertj
254 * Added non-standard codec capability classes
256 * Revision 1.22 1999/09/21 08:10:03 craigs
257 * Added support for video devices and H261 codec
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
263 * Revision 1.20 1999/09/13 13:59:14 robertj
264 * Removed incorrect comment.
266 * Revision 1.19 1999/09/08 04:05:49 robertj
267 * Added support for video capabilities & codec, still needs the actual codec itself!
269 * Revision 1.18 1999/08/31 12:34:18 robertj
270 * Added gatekeeper support.
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.
277 * Revision 1.16 1999/07/16 16:05:48 robertj
278 * Added "human readable" codec type name display.
280 * Revision 1.15 1999/07/16 15:01:30 robertj
281 * Added message print when starting GSM codec.
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.
287 * Revision 1.13 1999/07/13 09:53:24 robertj
288 * Fixed some problems with jitter buffer and added more debugging.
290 * Revision 1.12 1999/07/10 02:42:53 robertj
291 * Fixed interopability problem with NetMetting 2.1 G711 capability.
293 * Revision 1.11 1999/07/09 06:09:49 robertj
294 * Major implementation. An ENORMOUS amount of stuff added everywhere.
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
299 * Revision 1.9 1999/06/22 13:49:40 robertj
300 * Added GSM support and further RTP protocol enhancements.
302 * Revision 1.8 1999/06/14 15:08:40 robertj
303 * Added GSM codec class frame work (still no actual codec).
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
309 * Revision 1.6 1999/06/14 06:39:08 robertj
310 * Fixed problem with getting transmit flag to channel from PDU negotiator
312 * Revision 1.5 1999/06/14 05:15:55 robertj
313 * Changes for using RTP sessions correctly in H323 Logical Channel context
315 * Revision 1.4 1999/06/13 12:41:14 robertj
316 * Implement logical channel transmitter.
317 * Fixed H245 connect on receiving call.
319 * Revision 1.3 1999/06/09 05:26:19 robertj
320 * Major restructuring of classes.
322 * Revision 1.2 1999/06/06 06:06:36 robertj
323 * Changes for new ASN compiler and v2 protocol ASN files.
325 * Revision 1.1 1999/01/16 01:31:04 robertj
333 #pragma implementation "codecs.h"
338 #include "channels.h"
343 #include <ptclib/paec.h>
344 #pragma comment(lib,"paec.lib")
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);
358 /////////////////////////////////////////////////////////////////////////////
360 H323Codec::H323Codec(const char * fmt, Direction dir)
363 logicalChannel = NULL;
366 lastSequenceNumber = 1;
367 rawDataChannel = NULL;
368 deleteChannel = FALSE;
372 BOOL H323Codec::Open(H323Connection & /*connection*/)
378 unsigned H323Codec::GetFrameRate() const
380 return mediaFormat.GetFrameTime();
384 void H323Codec::OnFlowControl(long PTRACE_PARAM(bitRateRestriction))
386 PTRACE(3, "Codec\tOnFlowControl: " << bitRateRestriction);
390 void H323Codec::OnMiscellaneousCommand(const H245_MiscellaneousCommand_type & PTRACE_PARAM(type))
392 PTRACE(3, "Codec\tOnMiscellaneousCommand: " << type.GetTagName());
396 void H323Codec::OnMiscellaneousIndication(const H245_MiscellaneousIndication_type & PTRACE_PARAM(type))
398 PTRACE(3, "Codec\tOnMiscellaneousIndication: " << type.GetTagName());
402 BOOL H323Codec::AttachChannel(PChannel * channel, BOOL autoDelete)
404 PWaitAndSignal mutex(rawChannelMutex);
406 CloseRawDataChannel();
408 rawDataChannel = channel;
409 deleteChannel = autoDelete;
411 if (channel == NULL){
412 PTRACE(3, "Codec\tError attaching channel. channel is NULL");
416 return channel->IsOpen();
419 PChannel * H323Codec::SwapChannel(PChannel * newChannel, BOOL autoDelete)
421 PWaitAndSignal mutex(rawChannelMutex);
423 PChannel * oldChannel = rawDataChannel;
425 rawDataChannel = newChannel;
426 deleteChannel = autoDelete;
432 BOOL H323Codec::CloseRawDataChannel()
434 if (rawDataChannel == NULL)
437 BOOL closeOK = rawDataChannel->Close();
440 delete rawDataChannel;
441 rawDataChannel = NULL;
448 BOOL H323Codec::IsRawDataChannelNative() const
454 BOOL H323Codec::ReadRaw(void * data, PINDEX size, PINDEX & length)
456 if (rawDataChannel == NULL) {
457 PTRACE(1, "Codec\tNo audio channel for read");
461 if (!rawDataChannel->Read(data, size)) {
462 PTRACE(1, "Codec\tAudio read failed: " << rawDataChannel->GetErrorText(PChannel::LastReadError));
466 length = rawDataChannel->GetLastReadCount();
468 for (PINDEX i = 0; i < filters.GetSize(); i++) {
469 FilterInfo info(*this, data, size, length);
471 length = info.bufferLength;
478 BOOL H323Codec::WriteRaw(void * data, PINDEX length)
480 if (rawDataChannel == NULL) {
481 PTRACE(1, "Codec\tNo audio channel for write");
485 for (PINDEX i = 0; i < filters.GetSize(); i++) {
486 FilterInfo info(*this, data, length, length);
488 length = info.bufferLength;
491 if (rawDataChannel->Write(data, length))
494 PTRACE(1, "Codec\tWrite failed: " << rawDataChannel->GetErrorText(PChannel::LastWriteError));
499 BOOL H323Codec::AttachLogicalChannel(H323Channel *channel)
501 logicalChannel = channel;
507 void H323Codec::AddFilter(const PNotifier & notifier)
509 rawChannelMutex.Wait();
510 filters.Append(new PNotifier(notifier));
511 rawChannelMutex.Signal();
514 BOOL H323Codec::SetRawDataHeld(BOOL /*hold*/)
519 /////////////////////////////////////////////////////////////////////////////
521 #ifndef NO_H323_VIDEO
523 H323VideoCodec::H323VideoCodec(const char * fmt, Direction dir)
524 : H323Codec(fmt, dir)
526 frameWidth = frameHeight = 0;
527 targetFrameTimeMs = 0;
528 videoBitRateControlModes = None;
536 H323VideoCodec::~H323VideoCodec()
538 Close(); //The close operation may delete the rawDataChannel.
542 BOOL H323VideoCodec::Open(H323Connection & connection)
544 return connection.OpenVideoChannel(direction == Encoder, *this);
548 void H323VideoCodec::OnMiscellaneousCommand(const H245_MiscellaneousCommand_type & type)
550 switch (type.GetTag()) {
551 case H245_MiscellaneousCommand_type::e_videoFreezePicture :
555 case H245_MiscellaneousCommand_type::e_videoFastUpdatePicture :
556 OnFastUpdatePicture();
559 case H245_MiscellaneousCommand_type::e_videoFastUpdateGOB :
561 const H245_MiscellaneousCommand_type_videoFastUpdateGOB & fuGOB = type;
562 OnFastUpdateGOB(fuGOB.m_firstGOB, fuGOB.m_numberOfGOBs);
566 case H245_MiscellaneousCommand_type::e_videoFastUpdateMB :
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,
575 case H245_MiscellaneousCommand_type::e_lostPartialPicture :
576 OnLostPartialPicture();
579 case H245_MiscellaneousCommand_type::e_lostPicture :
583 case H245_MiscellaneousCommand_type::e_videoTemporalSpatialTradeOff :
585 const PASN_Integer & newQuality = type;
586 OnVideoTemporalSpatialTradeOffCommand(newQuality);
591 H323Codec::OnMiscellaneousCommand(type);
595 void H323VideoCodec::OnFreezePicture()
597 PTRACE(3, "Codec\tOnFreezePicture()");
601 void H323VideoCodec::OnFastUpdatePicture()
603 PTRACE(3, "Codec\tOnFastUpdatePicture()");
607 void H323VideoCodec::OnFastUpdateGOB(unsigned PTRACE_PARAM(firstGOB),
608 unsigned PTRACE_PARAM(numberOfGOBs))
610 PTRACE(3, "Codecs\tOnFastUpdateGOB(" << firstGOB << ',' << numberOfGOBs << ')');
614 void H323VideoCodec::OnFastUpdateMB(int PTRACE_PARAM(firstGOB),
615 int PTRACE_PARAM(firstMB),
616 unsigned PTRACE_PARAM(numberOfMBs))
618 PTRACE(3, "Codecs\tOnFastUpdateMB(" << firstGOB << ',' << firstMB << ',' << numberOfMBs << ')');
622 void H323VideoCodec::OnLostPartialPicture()
624 PTRACE(3, "Codec\tOnLostPartialPicture()");
628 void H323VideoCodec::OnLostPicture()
630 PTRACE(3, "Codec\tOnLostPicture()");
634 void H323VideoCodec::OnMiscellaneousIndication(const H245_MiscellaneousIndication_type & type)
636 switch (type.GetTag()) {
637 case H245_MiscellaneousIndication_type::e_videoIndicateReadyToActivate :
638 OnVideoIndicateReadyToActivate();
641 case H245_MiscellaneousIndication_type::e_videoTemporalSpatialTradeOff :
643 const PASN_Integer & newQuality = type;
644 OnVideoTemporalSpatialTradeOffIndication(newQuality);
648 case H245_MiscellaneousIndication_type::e_videoNotDecodedMBs :
650 const H245_MiscellaneousIndication_type_videoNotDecodedMBs & vndMB = type;
651 OnVideoNotDecodedMBs(vndMB.m_firstMB, vndMB.m_numberOfMBs, vndMB.m_temporalReference);
656 H323Codec::OnMiscellaneousIndication(type);
660 void H323VideoCodec::OnVideoIndicateReadyToActivate()
662 PTRACE(3, "Codec\tOnVideoIndicateReadyToActivate()");
666 void H323VideoCodec::OnVideoTemporalSpatialTradeOffCommand(int PTRACE_PARAM(newQuality))
668 PTRACE(3, "Codecs\tOnVideoTemporalSpatialTradeOffCommand(" << newQuality << ')');
672 void H323VideoCodec::OnVideoTemporalSpatialTradeOffIndication(int PTRACE_PARAM(newQuality))
674 PTRACE(3, "Codecs\tOnVideoTemporalSpatialTradeOffIndication(" << newQuality << ')');
678 void H323VideoCodec::OnVideoNotDecodedMBs(unsigned PTRACE_PARAM(firstMB),
679 unsigned PTRACE_PARAM(numberOfMBs),
680 unsigned PTRACE_PARAM(temporalReference))
682 PTRACE(3, "Codecs\tOnVideoNotDecodedMBs(" << firstMB << ',' << numberOfMBs << ',' << temporalReference << ')');
686 void H323VideoCodec::Close()
688 PWaitAndSignal mutex1(videoHandlerActive);
690 CloseRawDataChannel();
694 BOOL H323VideoCodec::SetMaxBitRate(unsigned bitRate)
696 PTRACE(1,"Set bitRateHighLimit for video to " << bitRate << " bps");
698 bitRateHighLimit = bitRate;
700 if (0 == bitRateHighLimit) // disable bitrate control
701 videoBitRateControlModes &= ~AdaptivePacketDelay;
705 BOOL H323VideoCodec::SetTargetFrameTimeMs(unsigned ms)
707 PTRACE(1,"Set targetFrameTimeMs for video to " << ms << " milliseconds");
709 targetFrameTimeMs = ms;
711 if (0 == targetFrameTimeMs)
712 videoBitRateControlModes &= ~DynamicVideoQuality;
717 void H323VideoCodec::SendMiscCommand(unsigned command)
719 if (logicalChannel != NULL)
720 logicalChannel->SendMiscCommand(command);
724 #endif // NO_H323_VIDEO
727 /////////////////////////////////////////////////////////////////////////////
729 #ifndef NO_H323_AUDIO_CODECS
731 H323AudioCodec::H323AudioCodec(const char * fmt, Direction dir)
732 : H323Codec(fmt, dir)
734 samplesPerFrame = (mediaFormat.GetFrameTime() * mediaFormat.GetTimeUnits()) / 8;
735 if (samplesPerFrame == 0)
736 samplesPerFrame = 8; // Default for non-frame based codecs.
738 // Start off in silent mode
741 IsRawDataHeld = FALSE;
743 // Initialise the adaptive threshold variables.
744 SetSilenceDetectionMode(AdaptiveSilenceDetection);
748 H323AudioCodec::~H323AudioCodec()
752 CloseRawDataChannel();
756 BOOL H323AudioCodec::Open(H323Connection & connection)
758 return connection.OpenAudioChannel(direction == Encoder, samplesPerFrame*2, *this);
762 void H323AudioCodec::Close()
764 PWaitAndSignal mutex(rawChannelMutex);
766 if (rawDataChannel != NULL)
767 rawDataChannel->Close();
771 unsigned H323AudioCodec::GetFrameRate() const
773 return samplesPerFrame;
777 H323AudioCodec::SilenceDetectionMode H323AudioCodec::GetSilenceDetectionMode(
778 BOOL * isInTalkBurst, unsigned * currentThreshold) const
780 if (isInTalkBurst != NULL)
781 *isInTalkBurst = inTalkBurst;
783 if (currentThreshold != NULL)
784 *currentThreshold = ulaw2linear((BYTE)(levelThreshold ^ 0xff));
786 return silenceDetectMode;
790 void H323AudioCodec::SetSilenceDetectionMode(SilenceDetectionMode mode,
792 unsigned signalDeadband,
793 unsigned silenceDeadband,
794 unsigned adaptivePeriod)
796 silenceDetectMode = mode;
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;
803 // This is the period over which the adaptive algorithm operates
804 adaptiveThresholdFrames = (adaptivePeriod+samplesPerFrame-1)/samplesPerFrame;
806 if (mode != AdaptiveSilenceDetection) {
807 levelThreshold = threshold;
811 // Initials threshold levels
814 // Initialise the adaptive threshold variables.
815 signalMinimum = UINT_MAX;
817 signalFramesReceived = 0;
818 silenceFramesReceived = 0;
820 // Restart in silent mode
825 BOOL H323AudioCodec::DetectSilence()
827 // Can never have silence if NoSilenceDetection
828 if (silenceDetectMode == NoSilenceDetection)
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)
837 // Convert to a logarithmic scale - use uLaw which is complemented
838 level = linear2ulaw(level) ^ 0xff;
840 // Now if signal level above threshold we are "talking"
841 BOOL haveSignal = level > levelThreshold;
843 // If no change ie still talking or still silent, resent frame counter
844 if (inTalkBurst == haveSignal)
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);
855 // If we had talk/silence transition restart adaptive threshold measurements
856 signalMinimum = UINT_MAX;
858 signalFramesReceived = 0;
859 silenceFramesReceived = 0;
863 if (silenceDetectMode == FixedSilenceDetection)
866 if (levelThreshold == 0) {
868 // Bootstrap condition, use first frame level as silence level
869 levelThreshold = level/2;
870 PTRACE(4, "Codec\tSilence detection threshold initialised to: " << levelThreshold);
872 return TRUE; // inTalkBurst always FALSE here, so return silent
875 // Count the number of silent and signal frames and calculate min/max
877 if (level < signalMinimum)
878 signalMinimum = level;
879 signalFramesReceived++;
882 if (level > silenceMaximum)
883 silenceMaximum = level;
884 silenceFramesReceived++;
887 // See if we have had enough frames to look at proportions of silence/signal
888 if ((signalFramesReceived + silenceFramesReceived) > adaptiveThresholdFrames) {
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:
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.
899 int delta = (signalMinimum - levelThreshold)/4;
901 levelThreshold += delta;
902 PTRACE(4, "Codec\tSilence detection threshold increased to: " << levelThreshold);
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.
912 unsigned newThreshold = (levelThreshold + silenceMaximum)/2 + 1;
913 if (levelThreshold != newThreshold) {
914 levelThreshold = newThreshold;
915 PTRACE(4, "Codec\tSilence detection threshold decreased to: " << levelThreshold);
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.
924 PTRACE(4, "Codec\tSilence detection threshold incremented to: " << levelThreshold
925 << " signal=" << signalFramesReceived << ' ' << signalMinimum
926 << " silence=" << silenceFramesReceived << ' ' << silenceMaximum);
929 signalMinimum = UINT_MAX;
931 signalFramesReceived = 0;
932 silenceFramesReceived = 0;
939 unsigned H323AudioCodec::GetAverageSignalLevel()
944 BOOL H323AudioCodec::SetRawDataHeld(BOOL hold) {
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
953 /////////////////////////////////////////////////////////////////////////////
955 H323FramedAudioCodec::H323FramedAudioCodec(const char * fmt, Direction dir)
956 : H323AudioCodec(fmt, dir),
957 sampleBuffer(samplesPerFrame)
959 bytesPerFrame = mediaFormat.GetFrameSize();
963 BOOL H323FramedAudioCodec::Read(BYTE * buffer, unsigned & length, RTP_DataFrame &)
965 PWaitAndSignal mutex(rawChannelMutex);
967 if (direction != Encoder) {
968 PTRACE(1, "Codec\tAttempt to decode from encoder");
972 if (IsRawDataHeld) { // If connection is onHold
973 PProcess::Sleep(5); // Sleep to avoid CPU overload. <--Should be a better method but it works :)
980 aec->Send(buffer,length);
983 PINDEX numBytes = samplesPerFrame*2;
985 if (!ReadRaw(sampleBuffer.GetPointer(samplesPerFrame), numBytes, count))
993 if (count != numBytes) {
994 PTRACE(1, "Codec\tRead truncated frame of raw data. Wanted " << numBytes << " and got "<<count);
998 if (DetectSilence()) {
1003 // Default length is the frame size
1004 length = bytesPerFrame;
1005 return EncodeFrame(buffer, length);
1009 BOOL H323FramedAudioCodec::Write(const BYTE * buffer,
1011 const RTP_DataFrame & /*rtpFrame*/,
1014 PWaitAndSignal mutex(rawChannelMutex);
1016 if (direction != Decoder) {
1017 PTRACE(1, "Codec\tAttempt to encode from decoder");
1021 // If length is zero then it indicates silence, do nothing.
1024 unsigned bytesDecoded = samplesPerFrame*2;
1027 if (length > bytesPerFrame)
1028 length = bytesPerFrame;
1029 written = bytesPerFrame;
1032 if (!DecodeFrame(buffer, length, written, bytesDecoded)) {
1038 // was memset(sampleBuffer.GetPointer(samplesPerFrame), 0, bytesDecoded);
1040 DecodeSilenceFrame(sampleBuffer.GetPointer(bytesDecoded), bytesDecoded);
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.
1047 if (!WriteRaw(sampleBuffer.GetPointer(), bytesDecoded))
1052 aec->Receive((BYTE *)sampleBuffer.GetPointer(), bytesDecoded);
1060 unsigned H323FramedAudioCodec::GetAverageSignalLevel()
1062 // Calculate the average signal level of this frame
1065 const short * pcm = sampleBuffer;
1066 const short * end = pcm + samplesPerFrame;
1067 while (pcm != end) {
1074 return sum/samplesPerFrame;
1078 BOOL H323FramedAudioCodec::DecodeFrame(const BYTE * buffer,
1081 unsigned & /*decodedBytes*/)
1083 return DecodeFrame(buffer, length, written);
1087 BOOL H323FramedAudioCodec::DecodeFrame(const BYTE * /*buffer*/,
1088 unsigned /*length*/,
1089 unsigned & /*written*/)
1091 PAssertAlways(PUnimplementedFunction);
1096 void H323FramedAudioCodec::AttachAEC(PAec * _aec)
1102 /////////////////////////////////////////////////////////////////////////////
1104 H323StreamedAudioCodec::H323StreamedAudioCodec(const char * fmt,
1108 : H323FramedAudioCodec(fmt, dir)
1110 samplesPerFrame = samples;
1111 bytesPerFrame = (samples*bits+7)/8;
1112 bitsPerSample = bits;
1116 BOOL H323StreamedAudioCodec::EncodeFrame(BYTE * buffer, unsigned &)
1119 unsigned short position = 0;
1121 switch (bitsPerSample) {
1123 for (i = 0; i < (PINDEX)samplesPerFrame; i++)
1124 *buffer++ = (BYTE)Encode(sampleBuffer[i]);
1126 case 5 : // g.726-40 payload encoding....
1127 for (i = 0; i < (PINDEX)samplesPerFrame;i++)
1129 // based on a 40 bits encoding, we have 8 words of 5 bits each
1130 encoded = (BYTE)Encode(sampleBuffer[i]);
1133 case 0: // 0 bits overflow
1137 case 1: // 2 bits overflow
1138 *buffer++ |= (encoded << 5);
1139 *buffer = (BYTE)(encoded >> 3);
1143 *buffer |= (encoded << 2);
1146 case 3: // one bit left for word 4
1147 *buffer++ |= (encoded << 7);
1148 *buffer = (BYTE)(encoded >> 1);
1152 *buffer++ |= (encoded << 4);
1153 *buffer = (BYTE)(encoded >> 4);
1157 *buffer |= (encoded << 1);
1160 case 6: //two bits left for the new encoded word
1161 *buffer++ |= (encoded << 6);
1162 *buffer = (BYTE)(encoded >> 2);
1165 case 7: // now five bits left for the last word
1166 *buffer++ |= (encoded << 3);
1174 for (i = 0; i < (PINDEX)samplesPerFrame; i++) {
1176 *buffer = (BYTE)Encode(sampleBuffer[i]);
1178 *buffer++ |= (BYTE)(Encode(sampleBuffer[i]) << 4);
1183 for (i = 0;i < (PINDEX)samplesPerFrame;i++)
1185 encoded = (BYTE)Encode(sampleBuffer[i]);
1188 case 0: // 0 bits overflow
1192 case 1: // 2 bits overflow
1193 *buffer |= (encoded << 3);
1197 *buffer++ |= (encoded << 6);
1198 *buffer = (BYTE)(encoded >> 2);
1201 case 3: // one bit left for word 4
1202 *buffer |= (encoded << 1);
1206 *buffer |= (encoded << 4);
1210 *buffer++ |= (encoded << 7);
1211 *buffer = (BYTE)(encoded >> 1);
1214 case 6: //two bits left for the new encoded word
1215 *buffer |= (encoded << 2);
1218 case 7: // now five bits left for the last word
1219 *buffer++ |= (encoded << 5);
1227 for (i = 0; i < (PINDEX)samplesPerFrame; i++)
1232 *buffer = (BYTE)Encode(sampleBuffer[i]);
1236 *buffer |= (BYTE)(Encode(sampleBuffer[i]) << 2);
1240 *buffer |= (BYTE)(Encode(sampleBuffer[i]) << 4);
1244 *buffer++ |= (BYTE)(Encode(sampleBuffer[i]) << 6);
1252 PAssertAlways("Unsupported bit size");
1260 BOOL H323StreamedAudioCodec::DecodeFrame(const BYTE * buffer,
1263 unsigned & decodedBytes)
1267 short * sampleBufferPtr = sampleBuffer.GetPointer(samplesPerFrame);
1268 short * out = sampleBufferPtr;
1269 unsigned short position = 0;
1270 unsigned remaining = 0;
1272 switch (bitsPerSample) {
1274 for (i = 0; i < length; i++)
1275 *out++ = Decode(*buffer++);
1278 // those case are for ADPCM G.726
1280 for (i = 0; i < length; i++) {
1284 *out++ = Decode(*buffer & 31);
1285 remaining = *buffer >> 5; // get the three remaining bytes for the next word
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;
1297 *out++ = Decode( remaining | ((*buffer&15) << 1));
1298 remaining = *buffer >> 4;
1303 *out++ = Decode( remaining | ((*buffer&1) << 4));
1304 *out++ = Decode( (*buffer >> 1) & 31);
1305 remaining = *buffer >> 6;
1310 *out++ = Decode( remaining | ((*buffer&7) << 2));
1311 *out++ = Decode(*buffer >> 3);
1320 for (i = 0; i < length; i++) {
1321 *out++ = Decode(*buffer & 15);
1322 *out++ = Decode(*buffer >> 4);
1328 for (i = 0; i < length; i++) {
1332 *out++ = Decode(*buffer & 7);
1333 *out++ = Decode((*buffer>>3)&7);
1334 remaining = *buffer >> 6;
1339 *out++ = Decode(remaining | ((*buffer&1) << 2));
1340 *out++ = Decode((*buffer >> 1) & 7);
1341 *out++ = Decode((*buffer >> 4)&7);
1342 remaining = *buffer >> 7;
1347 *out++ = Decode(remaining | ((*buffer&3) << 1));
1348 *out++ = Decode((*buffer >> 2) & 7);
1349 *out++ = Decode((*buffer >> 5) & 7);
1358 for (i = 0; i < length; i++)
1360 *out++ = Decode(*buffer & 3);
1361 *out++ = Decode((*buffer >> 2) & 3);
1362 *out++ = Decode((*buffer >> 4) & 3);
1363 *out++ = Decode((*buffer >> 6) & 3);
1370 PAssertAlways("Unsupported bit size");
1375 decodedBytes = (out - sampleBufferPtr)*2;
1381 /////////////////////////////////////////////////////////////////////////////
1383 H323_ALawCodec::H323_ALawCodec(Direction dir,
1386 : H323StreamedAudioCodec(OpalG711ALaw, dir, frameSize, 8)
1388 sevenBit = at56kbps;
1390 PTRACE(3, "Codec\tG711 ALaw " << (dir == Encoder ? "en" : "de")
1391 << "coder created for at "
1392 << (sevenBit ? "56k" : "64k") << ", " << frameSize << " samples");
1397 int H323_ALawCodec::EncodeSample(short sample)
1399 return linear2alaw(sample);
1403 short H323_ALawCodec::DecodeSample(int sample)
1405 return (short)alaw2linear((unsigned char)sample);
1409 /////////////////////////////////////////////////////////////////////////////
1411 H323_muLawCodec::H323_muLawCodec(Direction dir,
1414 : H323StreamedAudioCodec(OpalG711uLaw, dir, frameSize, 8)
1416 sevenBit = at56kbps;
1418 PTRACE(3, "Codec\tG711 uLaw " << (dir == Encoder ? "en" : "de")
1419 << "coder created for at "
1420 << (sevenBit ? "56k" : "64k") << ", frame of " << frameSize << " samples");
1424 int H323_muLawCodec::EncodeSample(short sample)
1426 return linear2ulaw(sample);
1430 short H323_muLawCodec::DecodeSample(int sample)
1432 return (short)ulaw2linear((unsigned char)sample);
1436 /////////////////////////////////////////////////////////////////////////////
1438 #endif // NO_H323_AUDIO_CODECS