D:/Storage/CVS_Head/h323plus/src/codecs.cxx

00001 /*
00002  * codecs.cxx
00003  *
00004  * H.323 protocol handler
00005  *
00006  * Open H323 Library
00007  *
00008  * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
00009  *
00010  * The contents of this file are subject to the Mozilla Public License
00011  * Version 1.0 (the "License"); you may not use this file except in
00012  * compliance with the License. You may obtain a copy of the License at
00013  * http://www.mozilla.org/MPL/
00014  *
00015  * Software distributed under the License is distributed on an "AS IS"
00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00017  * the License for the specific language governing rights and limitations
00018  * under the License.
00019  *
00020  * The Original Code is Open H323 Library.
00021  *
00022  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
00023  *
00024  * Portions of this code were written with the assisance of funding from
00025  * Vovida Networks, Inc. http://www.vovida.com.
00026  *
00027  * Contributor(s): ______________________________________.
00028  *
00029  * $Log: codecs.cxx,v $
00030  * Revision 1.2  2007/10/19 19:54:17  shorne
00031  * ported latest Video updates in OpenH323 committed after h323plus initial fork thanks
00032  *  Robert
00033  *
00034  * Revision 1.1  2007/08/06 20:51:03  shorne
00035  * First commit of h323plus
00036  *
00037  * Revision 1.92.2.8  2007/09/03 09:45:47  rjongbloed
00038  * Fixed failure to propagate meda format options to codec.
00039  *
00040  * Revision 1.92.2.7  2007/07/19 20:10:28  shorne
00041  * Changed HAS_AEC to H323_AEC
00042  *
00043  * Revision 1.92.2.6  2007/03/24 23:39:43  shorne
00044  * More H.239 work
00045  *
00046  * Revision 1.92.2.5  2007/03/06 00:18:13  shorne
00047  * Added Debug AEC support
00048  *
00049  * Revision 1.92.2.4  2007/03/05 11:57:12  shorne
00050  * Fixed compile issue with AEC
00051  *
00052  * Revision 1.92.2.3  2007/02/18 18:59:26  shorne
00053  * AEC tweaks
00054  *
00055  * Revision 1.92.2.2  2007/02/06 11:45:59  shorne
00056  * Added ability to send general codec options to Video Plugins
00057  *
00058  * Revision 1.92.2.1  2006/12/23 19:08:02  shorne
00059  * Plugin video codecs & sundry
00060  *
00061  * Revision 1.92  2006/05/16 11:28:58  shorne
00062  * added AEC support and  more call hold support.
00063  *
00064  * Revision 1.91  2006/01/26 03:31:09  shorne
00065  * Add the ability to remove a local input device when placing a call on hold
00066  *
00067  * Revision 1.90  2005/01/03 06:25:54  csoutheren
00068  * Added extensive support for disabling code modules at compile time
00069  *
00070  * Revision 1.89  2004/11/29 06:30:53  csoutheren
00071  * Added support for wideband codecs
00072  *
00073  * Revision 1.88  2004/07/03 06:49:28  rjongbloed
00074  * Split video temporal/spatial trade off H.245 packets to separate command and
00075  *   indication functions and added quality parameter, thanks Guilhem Tardy.
00076  * Added PTRACE_PARAM() macro to fix warnings on parameters used in PTRACE
00077  *  macros only.
00078  *
00079  * Revision 1.87  2004/05/09 10:22:26  csoutheren
00080  * Changed new DecodeFrame to handle bytes per frame
00081  *
00082  * Revision 1.86  2004/05/09 10:08:36  csoutheren
00083  * Changed new DecodeFrame to return bytes decoded rather than samples decoded
00084  * Added support for new DecodeFrame to plugin manager
00085  *
00086  * Revision 1.85  2004/05/02 04:52:24  rjongbloed
00087  * Fixed problems with G.711 caused by fixing problem with G.723.1-5k3 mode.
00088  *
00089  * Revision 1.84  2004/04/16 04:04:28  csoutheren
00090  * Prevent codecs with variable length frrames from doing strange things
00091  *
00092  * Revision 1.83  2004/02/04 10:29:27  rjongbloed
00093  * Fixed G.726 by allowing for more bits per pixels sizes in streamed codec, thanks Kevin Bouchard
00094  *
00095  * Revision 1.82  2003/11/12 11:14:51  csoutheren
00096  * Added H323FramedAudioCodec::DecodeSilenceFrame thanks to Henry Harrison of AliceStreet
00097  *
00098  * Revision 1.81  2003/07/16 10:43:13  csoutheren
00099  * Added SwapChannel function to H323Codec to allow media hold channels
00100  * to work better. Thanks to Federico Pinna
00101  *
00102  * Revision 1.80  2002/12/16 09:11:19  robertj
00103  * Added new video bit rate control, thanks Walter H. Whitlock
00104  *
00105  * Revision 1.79  2002/08/05 10:03:47  robertj
00106  * Cosmetic changes to normalise the usage of pragma interface/implementation.
00107  *
00108  * Revision 1.78  2002/05/29 04:48:48  robertj
00109  * Changed framed codec so if cannot decode frame just plays silence instead
00110  *   of returning error and thus shutting down channel, thanks Federico Pinna
00111  *
00112  * Revision 1.77  2002/04/16 03:27:54  dereks
00113  * Correct logical flaw in CloseRawDataChannel method.
00114  *
00115  * Revision 1.76  2002/04/05 00:52:17  dereks
00116  * Minor tweaks to cope with received h261 messages.
00117  *
00118  * Revision 1.75  2002/02/26 18:00:18  rogerh
00119  * Improve the information given in the trace for codec truncation
00120  *
00121  * Revision 1.74  2002/01/23 06:13:56  robertj
00122  * Added filter function hooks to codec raw data channel.
00123  *
00124  * Revision 1.73  2002/01/23 01:58:28  robertj
00125  * Added function to determine if codecs raw data channel is native format.
00126  *
00127  * Revision 1.72  2002/01/22 16:09:38  rogerh
00128  * Back out the DTMF detection from H323FramedAudioCodec::Write().
00129  * There will shortly be a better place for it.
00130  *
00131  * Revision 1.71  2002/01/22 15:21:47  rogerh
00132  * Add DTMF decoding to PCM audio streams. This has been tested with
00133  * NetMeeting sending Dial Pad codes, using the G.711 codec.
00134  * At this time, DTMF codes (fron NetMeeting) are just displayed on the
00135  * screen and are not passed up to the users application.
00136  *
00137  * Revision 1.70  2002/01/13 23:55:21  robertj
00138  * Added mutex so can change raw data channel while reading/writing from codec.
00139  *
00140  * Revision 1.69  2002/01/06 05:34:05  robertj
00141  * Fixed encoding error for 4 bit streamed codecs.
00142  *
00143  * Revision 1.68  2001/12/04 05:13:12  robertj
00144  * Added videa bandwidth limiting code for H.261, thanks Jose Luis Urien.
00145  *
00146  * Revision 1.67  2001/11/28 00:09:14  dereks
00147  * Additional information in PTRACE output.
00148  *
00149  * Revision 1.66  2001/11/16 01:05:35  craigs
00150  * Changed to allow access to uLaw/ALaw to/from linear functions
00151  *
00152  * Revision 1.65  2001/10/23 02:17:16  dereks
00153  * Initial release of cu30 video codec.
00154  *
00155  * Revision 1.64  2001/09/25 03:14:47  dereks
00156  * Add constant bitrate control for the h261 video codec.
00157  * Thanks Tiziano Morganti for the code to set bit rate. Good work!
00158  *
00159  * Revision 1.63  2001/09/21 02:50:06  robertj
00160  * Implemented static object for all "known" media formats.
00161  *
00162  * Revision 1.62  2001/09/12 07:48:05  robertj
00163  * Fixed various problems with tracing.
00164  *
00165  * Revision 1.61  2001/09/11 01:24:36  robertj
00166  * Added conditional compilation to remove video and/or audio codecs.
00167  *
00168  * Revision 1.60  2001/08/06 03:08:56  robertj
00169  * Fission of h323.h to h323ep.h & h323con.h, h323.h now just includes files.
00170  *
00171  * Revision 1.59  2001/04/03 09:34:13  robertj
00172  * Fixed output of partial frames when short changed by transmitter with G.711
00173  *
00174  * Revision 1.58  2001/03/29 23:45:08  robertj
00175  * Added ability to get current silence detect state and threshold.
00176  * Changed default signal on deadband time to be much shorter.
00177  *
00178  * Revision 1.57  2001/02/09 05:13:55  craigs
00179  * Added pragma implementation to (hopefully) reduce the executable image size
00180  * under Linux
00181  *
00182  * Revision 1.56  2001/01/25 07:27:16  robertj
00183  * Major changes to add more flexible OpalMediaFormat class to normalise
00184  *   all information about media types, especially codecs.
00185  *
00186  * Revision 1.55  2000/12/19 22:33:44  dereks
00187  * Adjust so that the video channel is used for reading/writing raw video
00188  * data, which better modularizes the video codec.
00189  *
00190  * Revision 1.54  2000/09/22 01:35:49  robertj
00191  * Added support for handling LID's that only do symmetric codecs.
00192  *
00193  * Revision 1.53  2000/08/31 08:15:41  robertj
00194  * Added support for dynamic RTP payload types in H.245 OpenLogicalChannel negotiations.
00195  *
00196  * Revision 1.52  2000/07/14 14:08:10  robertj
00197  * Fixed stream based codec so can support stream "frames" less than maximum specified.
00198  *
00199  * Revision 1.51  2000/05/16 02:04:17  craigs
00200  * Added access functions for silence compression mode
00201  *
00202  * Revision 1.50  2000/05/04 11:52:35  robertj
00203  * Added Packets Too Late statistics, requiring major rearrangement of jitter
00204  *    buffer code, not also changes semantics of codec Write() function slightly.
00205  *
00206  * Revision 1.49  2000/05/02 04:32:26  robertj
00207  * Fixed copyright notice comment.
00208  *
00209  * Revision 1.48  2000/04/28 12:58:37  robertj
00210  * Changed silence detection code so does not PTRACE unless threshold actually changes.
00211  *
00212  * Revision 1.47  2000/04/10 18:52:45  robertj
00213  * Improved "bootstrap" of silence detection algorithm.
00214  *
00215  * Revision 1.46  2000/03/23 03:00:06  robertj
00216  * Changed framed codec so only writes max of bytesPerFrame regardless of length.
00217  *
00218  * Revision 1.45  2000/02/04 05:11:19  craigs
00219  * Updated for new Makefiles and for new video transmission code
00220  *
00221  * Revision 1.44  2000/01/13 04:03:45  robertj
00222  * Added video transmission
00223  *
00224  * Revision 1.43  1999/12/31 00:05:36  robertj
00225  * Added Microsoft ACM G.723.1 codec capability.
00226  *
00227  * Revision 1.42  1999/12/23 23:02:35  robertj
00228  * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
00229  *
00230  * Revision 1.41  1999/12/21 07:36:43  craigs
00231  * Fixed problem in H323VideoCodec destructor that caused hang or segv on exit
00232  *
00233  * Revision 1.40  1999/11/29 08:59:09  craigs
00234  * Added new code for new video code interface
00235  *
00236  * Revision 1.39  1999/11/29 04:50:11  robertj
00237  * Added adaptive threshold calculation to silence detection.
00238  *
00239  * Revision 1.38  1999/11/20 00:53:47  robertj
00240  * Fixed ability to have variable sized frames in single RTP packet under G.723.1
00241  *
00242  * Revision 1.37  1999/11/13 14:10:59  robertj
00243  * Changes to make silence detection selectable.
00244  *
00245  * Revision 1.36  1999/11/11 23:28:46  robertj
00246  * Added first cut silence detection algorithm.
00247  *
00248  * Revision 1.35  1999/11/04 00:45:07  robertj
00249  * Added extra constructors for nonStandard codecs and fixed receiveAndTransmitAudioCapability problem.
00250  *
00251  * Revision 1.34  1999/11/01 00:51:13  robertj
00252  * Fixed problem where codec close does not dispose of attached channel.
00253  *
00254  * Revision 1.33  1999/10/19 00:04:57  robertj
00255  * Changed OpenAudioChannel and OpenVideoChannel to allow a codec AttachChannel with no autodelete.
00256  *
00257  * Revision 1.32  1999/10/14 12:02:40  robertj
00258  * Fixed assignment of t35 info in nonstandard capabilities (wrong way around).
00259  *
00260  * Revision 1.31  1999/10/10 23:00:15  craigs
00261  * Fixed problem with raw channel ptrs not being NULLed out after deletion
00262  *
00263  * Revision 1.30  1999/10/09 02:15:08  craigs
00264  * Added codec to OpenVideoDevice and OpenAudioChannel
00265  *
00266  * Revision 1.29  1999/10/09 01:20:48  robertj
00267  * Fixed error in G711 packet size and trace message
00268  *
00269  * Revision 1.28  1999/10/08 09:59:03  robertj
00270  * Rewrite of capability for sending multiple audio frames
00271  *
00272  * Revision 1.27  1999/10/08 08:32:22  robertj
00273  * Fixed misleading trace text.
00274  *
00275  * Revision 1.26  1999/10/08 04:58:38  robertj
00276  * Added capability for sending multiple audio frames in single RTP packet
00277  *
00278  * Revision 1.25  1999/09/23 07:25:12  robertj
00279  * Added open audio and video function to connection and started multi-frame codec send functionality.
00280  *
00281  * Revision 1.24  1999/09/21 14:51:34  robertj
00282  * Fixed NonStandardCapabilityInfo class virtual destructor (and name).
00283  *
00284  * Revision 1.23  1999/09/21 14:14:36  robertj
00285  * Added non-standard codec capability classes
00286  *
00287  * Revision 1.22  1999/09/21 08:10:03  craigs
00288  * Added support for video devices and H261 codec
00289  *
00290  * Revision 1.21  1999/09/18 13:24:38  craigs
00291  * Added ability to disable jitter buffer
00292  * Added ability to access entire RTP packet in codec Write
00293  *
00294  * Revision 1.20  1999/09/13 13:59:14  robertj
00295  * Removed incorrect comment.
00296  *
00297  * Revision 1.19  1999/09/08 04:05:49  robertj
00298  * Added support for video capabilities & codec, still needs the actual codec itself!
00299  *
00300  * Revision 1.18  1999/08/31 12:34:18  robertj
00301  * Added gatekeeper support.
00302  *
00303  * Revision 1.17  1999/08/25 05:05:36  robertj
00304  * Added UserInput capability.
00305  * Allowed the attachment of a channel on a codec to optionally delete the channel object,
00306  * Improved opening of audio codecs, PSoundChannel creation now in endpoint.
00307  *
00308  * Revision 1.16  1999/07/16 16:05:48  robertj
00309  * Added "human readable" codec type name display.
00310  *
00311  * Revision 1.15  1999/07/16 15:01:30  robertj
00312  * Added message print when starting GSM codec.
00313  *
00314  * Revision 1.14  1999/07/15 14:45:36  robertj
00315  * Added propagation of codec open error to shut down logical channel.
00316  * Fixed control channel start up bug introduced with tunnelling.
00317  *
00318  * Revision 1.13  1999/07/13 09:53:24  robertj
00319  * Fixed some problems with jitter buffer and added more debugging.
00320  *
00321  * Revision 1.12  1999/07/10 02:42:53  robertj
00322  * Fixed interopability problem with NetMetting 2.1 G711 capability.
00323  *
00324  * Revision 1.11  1999/07/09 06:09:49  robertj
00325  * Major implementation. An ENORMOUS amount of stuff added everywhere.
00326  *
00327  * Revision 1.10  1999/06/24 13:32:45  robertj
00328  * Fixed ability to change sound device on codec and fixed NM3 G.711 compatibility
00329  *
00330  * Revision 1.9  1999/06/22 13:49:40  robertj
00331  * Added GSM support and further RTP protocol enhancements.
00332  *
00333  * Revision 1.8  1999/06/14 15:08:40  robertj
00334  * Added GSM codec class frame work (still no actual codec).
00335  *
00336  * Revision 1.7  1999/06/14 08:44:58  robertj
00337  * Fixed sound buffers to be correct size for stream based audio.
00338  * GNU C++ compatibility
00339  *
00340  * Revision 1.6  1999/06/14 06:39:08  robertj
00341  * Fixed problem with getting transmit flag to channel from PDU negotiator
00342  *
00343  * Revision 1.5  1999/06/14 05:15:55  robertj
00344  * Changes for using RTP sessions correctly in H323 Logical Channel context
00345  *
00346  * Revision 1.4  1999/06/13 12:41:14  robertj
00347  * Implement logical channel transmitter.
00348  * Fixed H245 connect on receiving call.
00349  *
00350  * Revision 1.3  1999/06/09 05:26:19  robertj
00351  * Major restructuring of classes.
00352  *
00353  * Revision 1.2  1999/06/06 06:06:36  robertj
00354  * Changes for new ASN compiler and v2 protocol ASN files.
00355  *
00356  * Revision 1.1  1999/01/16 01:31:04  robertj
00357  * Initial revision
00358  *
00359  */
00360 
00361 #include <ptlib.h>
00362 
00363 #ifdef __GNUC__
00364 #pragma implementation "codecs.h"
00365 #endif
00366 
00367 #include "codecs.h"
00368 
00369 #include "channels.h"
00370 #include "h323pdu.h"
00371 #include "h323con.h"
00372 
00373 #ifdef H323_AEC
00374 #include <ptclib/paec.h>
00375 
00376 #ifdef _DEBUG
00377 #pragma comment(lib,"paecd.lib")
00378 #else
00379 #pragma comment(lib,"paec.lib")
00380 #endif
00381 
00382 #endif
00383 
00384 #define new PNEW
00385 
00386 
00387 extern "C" {
00388   unsigned char linear2ulaw(int pcm_val);
00389   int ulaw2linear(unsigned char u_val);
00390   unsigned char linear2alaw(int pcm_val);
00391   int alaw2linear(unsigned char u_val);
00392 };
00393 
00394 
00396 
00397 H323Codec::H323Codec(const OpalMediaFormat & fmt, Direction dir)
00398   : mediaFormat(fmt)
00399 {
00400   logicalChannel = NULL;
00401   direction = dir;
00402 
00403   lastSequenceNumber = 1;
00404   rawDataChannel = NULL;
00405   deleteChannel  = FALSE;
00406 }
00407 
00408 
00409 BOOL H323Codec::Open(H323Connection & /*connection*/)
00410 {
00411   return TRUE;
00412 }
00413 
00414 
00415 unsigned H323Codec::GetFrameRate() const
00416 {
00417   return mediaFormat.GetFrameTime();
00418 }
00419 
00420 
00421 void H323Codec::OnFlowControl(long PTRACE_PARAM(bitRateRestriction))
00422 {
00423   PTRACE(3, "Codec\tOnFlowControl: " << bitRateRestriction);
00424 }
00425 
00426 
00427 void H323Codec::OnMiscellaneousCommand(const H245_MiscellaneousCommand_type & PTRACE_PARAM(type))
00428 {
00429   PTRACE(3, "Codec\tOnMiscellaneousCommand: " << type.GetTagName());
00430 }
00431 
00432 
00433 void H323Codec::OnMiscellaneousIndication(const H245_MiscellaneousIndication_type & PTRACE_PARAM(type))
00434 {
00435   PTRACE(3, "Codec\tOnMiscellaneousIndication: " << type.GetTagName());
00436 }
00437 
00438 
00439 BOOL H323Codec::AttachChannel(PChannel * channel, BOOL autoDelete)
00440 {
00441   PWaitAndSignal mutex(rawChannelMutex);
00442 
00443   CloseRawDataChannel();
00444 
00445   rawDataChannel = channel;
00446   deleteChannel = autoDelete;
00447 
00448   if (channel == NULL){
00449         PTRACE(3, "Codec\tError attaching channel. channel is NULL");
00450     return FALSE;
00451   }
00452 
00453   return channel->IsOpen();
00454 }
00455 
00456 PChannel * H323Codec::SwapChannel(PChannel * newChannel, BOOL autoDelete)
00457 {
00458   PWaitAndSignal mutex(rawChannelMutex);
00459 
00460   PChannel * oldChannel = rawDataChannel;
00461 
00462   rawDataChannel = newChannel;
00463   deleteChannel = autoDelete;
00464 
00465   return oldChannel;
00466 }
00467 
00468 
00469 BOOL H323Codec::CloseRawDataChannel()
00470 {
00471   if (rawDataChannel == NULL)
00472     return FALSE;
00473   
00474   BOOL closeOK = rawDataChannel->Close();
00475   
00476   if (deleteChannel) {
00477      delete rawDataChannel;
00478      rawDataChannel = NULL;
00479   }
00480   
00481   return closeOK;
00482 }  
00483 
00484 
00485 BOOL H323Codec::IsRawDataChannelNative() const
00486 {
00487   return FALSE;
00488 }
00489 
00490 
00491 BOOL H323Codec::ReadRaw(void * data, PINDEX size, PINDEX & length)
00492 {
00493   if (rawDataChannel == NULL) {
00494     PTRACE(1, "Codec\tNo audio channel for read");
00495     return FALSE;
00496   }
00497 
00498   if (!rawDataChannel->Read(data, size)) {
00499     PTRACE(1, "Codec\tAudio read failed: " << rawDataChannel->GetErrorText(PChannel::LastReadError));
00500     return FALSE;
00501   }
00502 
00503   length = rawDataChannel->GetLastReadCount();
00504 
00505   for (PINDEX i = 0; i < filters.GetSize(); i++) {
00506     FilterInfo info(*this, data, size, length);
00507     filters[i](info, 0);
00508     length = info.bufferLength;
00509   }
00510 
00511   return TRUE;
00512 }
00513 
00514 
00515 BOOL H323Codec::WriteRaw(void * data, PINDEX length)
00516 {
00517   if (rawDataChannel == NULL) {
00518     PTRACE(1, "Codec\tNo audio channel for write");
00519     return FALSE;
00520   }
00521 
00522   for (PINDEX i = 0; i < filters.GetSize(); i++) {
00523     FilterInfo info(*this, data, length, length);
00524     filters[i](info, 0);
00525     length = info.bufferLength;
00526   }
00527 
00528   if (rawDataChannel->Write(data, length))
00529     return TRUE;
00530 
00531   PTRACE(1, "Codec\tWrite failed: " << rawDataChannel->GetErrorText(PChannel::LastWriteError));
00532   return FALSE;
00533 }
00534 
00535 
00536 BOOL H323Codec::AttachLogicalChannel(H323Channel *channel)
00537 {
00538   logicalChannel = channel;
00539 
00540   return TRUE;
00541 }
00542 
00543 
00544 void H323Codec::AddFilter(const PNotifier & notifier)
00545 {
00546   rawChannelMutex.Wait();
00547   filters.Append(new PNotifier(notifier));
00548   rawChannelMutex.Signal();
00549 }
00550 
00551 BOOL H323Codec::SetRawDataHeld(BOOL /*hold*/) 
00552 {
00553         return FALSE;
00554 }
00555 
00557 
00558 #ifdef H323_VIDEO
00559 
00560 H323VideoCodec::H323VideoCodec(const OpalMediaFormat & fmt, Direction dir)
00561   : H323Codec(fmt, dir)
00562 {
00563   frameWidth = frameHeight = 0;
00564   targetFrameTimeMs = 0;
00565   videoBitRateControlModes = None;
00566 
00567   oldLength = 0;
00568   oldTime = 0;
00569   newTime = 0;
00570 }
00571 
00572 
00573 H323VideoCodec::~H323VideoCodec()
00574 {
00575   Close();    //The close operation may delete the rawDataChannel.
00576 }
00577 
00578 
00579 BOOL H323VideoCodec::Open(H323Connection & connection)
00580 {
00581 #ifdef H323_H239
00582   if (logicalChannel->GetSessionID() == OpalMediaFormat::DefaultExtVideoSessionID)
00583     return connection.OpenExtendedVideoChannel(direction == Encoder, *this);
00584   else 
00585 #endif
00586     return connection.OpenVideoChannel(direction == Encoder, *this);
00587 }
00588 
00589 
00590 void H323VideoCodec::OnMiscellaneousCommand(const H245_MiscellaneousCommand_type & type)
00591 {
00592   switch (type.GetTag()) {
00593     case H245_MiscellaneousCommand_type::e_videoFreezePicture :
00594       OnFreezePicture();
00595       break;
00596 
00597     case H245_MiscellaneousCommand_type::e_videoFastUpdatePicture :
00598       OnFastUpdatePicture();
00599       break;
00600 
00601     case H245_MiscellaneousCommand_type::e_videoFastUpdateGOB :
00602     {
00603       const H245_MiscellaneousCommand_type_videoFastUpdateGOB & fuGOB = type;
00604       OnFastUpdateGOB(fuGOB.m_firstGOB, fuGOB.m_numberOfGOBs);
00605       break;
00606     }
00607 
00608     case H245_MiscellaneousCommand_type::e_videoFastUpdateMB :
00609     {
00610       const H245_MiscellaneousCommand_type_videoFastUpdateMB & fuMB = type;
00611       OnFastUpdateMB(fuMB.HasOptionalField(H245_MiscellaneousCommand_type_videoFastUpdateMB::e_firstGOB) ? (int)fuMB.m_firstGOB : -1,
00612                      fuMB.HasOptionalField(H245_MiscellaneousCommand_type_videoFastUpdateMB::e_firstMB)  ? (int)fuMB.m_firstMB  : -1,
00613                      fuMB.m_numberOfMBs);
00614       break;
00615     }
00616 
00617     case H245_MiscellaneousCommand_type::e_lostPartialPicture :
00618       OnLostPartialPicture();
00619       break;
00620 
00621     case H245_MiscellaneousCommand_type::e_lostPicture :
00622       OnLostPicture();
00623       break;
00624 
00625     case H245_MiscellaneousCommand_type::e_videoTemporalSpatialTradeOff :
00626     {
00627       const PASN_Integer & newQuality = type;
00628       OnVideoTemporalSpatialTradeOffCommand(newQuality);
00629       break;
00630     }
00631   }
00632 
00633   H323Codec::OnMiscellaneousCommand(type);
00634 }
00635 
00636 
00637 void H323VideoCodec::OnFreezePicture()
00638 {
00639   PTRACE(3, "Codec\tOnFreezePicture()");
00640 }
00641 
00642 
00643 void H323VideoCodec::OnFastUpdatePicture()
00644 {
00645   PTRACE(3, "Codec\tOnFastUpdatePicture()");
00646 }
00647 
00648 
00649 void H323VideoCodec::OnFastUpdateGOB(unsigned PTRACE_PARAM(firstGOB),
00650                                      unsigned PTRACE_PARAM(numberOfGOBs))
00651 {
00652   PTRACE(3, "Codecs\tOnFastUpdateGOB(" << firstGOB << ',' << numberOfGOBs << ')');
00653 }
00654 
00655 
00656 void H323VideoCodec::OnFastUpdateMB(int PTRACE_PARAM(firstGOB),
00657                                     int PTRACE_PARAM(firstMB),
00658                                     unsigned PTRACE_PARAM(numberOfMBs))
00659 {
00660   PTRACE(3, "Codecs\tOnFastUpdateMB(" << firstGOB << ',' << firstMB << ',' << numberOfMBs << ')');
00661 }
00662 
00663 
00664 void H323VideoCodec::OnLostPartialPicture()
00665 {
00666   PTRACE(3, "Codec\tOnLostPartialPicture()");
00667 }
00668 
00669 
00670 void H323VideoCodec::OnLostPicture()
00671 {
00672   PTRACE(3, "Codec\tOnLostPicture()");
00673 }
00674 
00675 
00676 void H323VideoCodec::OnMiscellaneousIndication(const H245_MiscellaneousIndication_type & type)
00677 {
00678   switch (type.GetTag()) {
00679     case H245_MiscellaneousIndication_type::e_videoIndicateReadyToActivate :
00680       OnVideoIndicateReadyToActivate();
00681       break;
00682 
00683     case H245_MiscellaneousIndication_type::e_videoTemporalSpatialTradeOff :
00684     {
00685       const PASN_Integer & newQuality = type;
00686       OnVideoTemporalSpatialTradeOffIndication(newQuality);
00687       break;
00688     }
00689 
00690     case H245_MiscellaneousIndication_type::e_videoNotDecodedMBs :
00691     {
00692       const H245_MiscellaneousIndication_type_videoNotDecodedMBs & vndMB = type;
00693       OnVideoNotDecodedMBs(vndMB.m_firstMB, vndMB.m_numberOfMBs, vndMB.m_temporalReference);
00694       break;
00695     }
00696   }
00697 
00698   H323Codec::OnMiscellaneousIndication(type);
00699 }
00700 
00701 
00702 void H323VideoCodec::OnVideoIndicateReadyToActivate()
00703 {
00704   PTRACE(3, "Codec\tOnVideoIndicateReadyToActivate()");
00705 }
00706 
00707 
00708 void H323VideoCodec::OnVideoTemporalSpatialTradeOffCommand(int PTRACE_PARAM(newQuality))
00709 {
00710   PTRACE(3, "Codecs\tOnVideoTemporalSpatialTradeOffCommand(" << newQuality << ')');
00711 }
00712 
00713 
00714 void H323VideoCodec::OnVideoTemporalSpatialTradeOffIndication(int PTRACE_PARAM(newQuality))
00715 {
00716   PTRACE(3, "Codecs\tOnVideoTemporalSpatialTradeOffIndication(" << newQuality << ')');
00717 }
00718 
00719 
00720 void H323VideoCodec::OnVideoNotDecodedMBs(unsigned PTRACE_PARAM(firstMB),
00721                                           unsigned PTRACE_PARAM(numberOfMBs),
00722                                           unsigned PTRACE_PARAM(temporalReference))
00723 {
00724   PTRACE(3, "Codecs\tOnVideoNotDecodedMBs(" << firstMB << ',' << numberOfMBs << ',' << temporalReference << ')');
00725 }
00726 
00727 
00728 void H323VideoCodec::Close()
00729 {
00730   PWaitAndSignal mutex1(videoHandlerActive);  
00731 
00732   CloseRawDataChannel();
00733 }
00734 
00735 
00736 BOOL H323VideoCodec::SetMaxBitRate(unsigned bitRate)
00737 {
00738   PTRACE(1,"Set bitRateHighLimit for video to " << bitRate << " bps");
00739         
00740   bitRateHighLimit = bitRate;
00741 
00742   if (0 == bitRateHighLimit) // disable bitrate control
00743     videoBitRateControlModes &= ~AdaptivePacketDelay;
00744   return TRUE;
00745 }
00746 
00747 BOOL H323VideoCodec::SetTargetFrameTimeMs(unsigned ms)
00748 {
00749   PTRACE(1,"Set targetFrameTimeMs for video to " << ms << " milliseconds");
00750 
00751   targetFrameTimeMs = ms;
00752 
00753   if (0 == targetFrameTimeMs)
00754     videoBitRateControlModes &= ~DynamicVideoQuality;
00755   return TRUE;
00756 }
00757 
00758 void H323VideoCodec::SetGeneralCodecOption(const char * /*opt*/,  int /*val*/)
00759 {
00760 }
00761 
00762 
00763 void H323VideoCodec::SendMiscCommand(unsigned command)
00764 {
00765   if (logicalChannel != NULL)
00766     logicalChannel->SendMiscCommand(command);
00767 }
00768 
00769 
00770 #endif // NO_H323_VIDEO
00771 
00772 
00774 
00775 #ifndef NO_H323_AUDIO_CODECS
00776 
00777 H323AudioCodec::H323AudioCodec(const OpalMediaFormat & fmt, Direction dir)
00778   : H323Codec(fmt, dir)
00779 {
00780   samplesPerFrame = (mediaFormat.GetFrameTime() * mediaFormat.GetTimeUnits()) / 8;
00781   if (samplesPerFrame == 0)
00782     samplesPerFrame = 8; // Default for non-frame based codecs.
00783 
00784   // Start off in silent mode
00785   inTalkBurst = FALSE;
00786 
00787   IsRawDataHeld = FALSE;
00788 
00789   // Initialise the adaptive threshold variables.
00790   SetSilenceDetectionMode(AdaptiveSilenceDetection);
00791 }
00792 
00793 
00794 H323AudioCodec::~H323AudioCodec()
00795 {
00796   Close();
00797 
00798   CloseRawDataChannel();
00799 }
00800 
00801 
00802 BOOL H323AudioCodec::Open(H323Connection & connection)
00803 {
00804   return connection.OpenAudioChannel(direction == Encoder, samplesPerFrame*2, *this);
00805 }
00806 
00807 
00808 void H323AudioCodec::Close()
00809 {
00810   PWaitAndSignal mutex(rawChannelMutex);
00811 
00812   if (rawDataChannel != NULL)
00813     rawDataChannel->Close();
00814 }
00815 
00816 
00817 unsigned H323AudioCodec::GetFrameRate() const
00818 {
00819   return samplesPerFrame;
00820 }
00821 
00822 
00823 H323AudioCodec::SilenceDetectionMode H323AudioCodec::GetSilenceDetectionMode(
00824                                 BOOL * isInTalkBurst, unsigned * currentThreshold) const
00825 {
00826   if (isInTalkBurst != NULL)
00827     *isInTalkBurst = inTalkBurst;
00828 
00829   if (currentThreshold != NULL)
00830     *currentThreshold = ulaw2linear((BYTE)(levelThreshold ^ 0xff));
00831 
00832   return silenceDetectMode;
00833 }
00834 
00835 
00836 void H323AudioCodec::SetSilenceDetectionMode(SilenceDetectionMode mode,
00837                                              unsigned threshold,
00838                                              unsigned signalDeadband,
00839                                              unsigned silenceDeadband,
00840                                              unsigned adaptivePeriod)
00841 {
00842   silenceDetectMode = mode;
00843 
00844   // The silence deadband is the number of frames of low energy that have to
00845   // occur before the system stops sending data over the RTP link.
00846   signalDeadbandFrames = (signalDeadband+samplesPerFrame-1)/samplesPerFrame;
00847   silenceDeadbandFrames = (silenceDeadband+samplesPerFrame-1)/samplesPerFrame;
00848 
00849   // This is the period over which the adaptive algorithm operates
00850   adaptiveThresholdFrames = (adaptivePeriod+samplesPerFrame-1)/samplesPerFrame;
00851 
00852   if (mode != AdaptiveSilenceDetection) {
00853     levelThreshold = threshold;
00854     return;
00855   }
00856 
00857   // Initials threshold levels
00858   levelThreshold = 0;
00859 
00860   // Initialise the adaptive threshold variables.
00861   signalMinimum = UINT_MAX;
00862   silenceMaximum = 0;
00863   signalFramesReceived = 0;
00864   silenceFramesReceived = 0;
00865 
00866   // Restart in silent mode
00867   inTalkBurst = FALSE;
00868 }
00869 
00870 
00871 BOOL H323AudioCodec::DetectSilence()
00872 {
00873   // Can never have silence if NoSilenceDetection
00874   if (silenceDetectMode == NoSilenceDetection)
00875     return FALSE;
00876 
00877   // Can never have average signal level that high, this indicates that the
00878   // hardware cannot do silence detection.
00879   unsigned level = GetAverageSignalLevel();
00880   if (level == UINT_MAX)
00881     return FALSE;
00882 
00883   // Convert to a logarithmic scale - use uLaw which is complemented
00884   level = linear2ulaw(level) ^ 0xff;
00885 
00886   // Now if signal level above threshold we are "talking"
00887   BOOL haveSignal = level > levelThreshold;
00888 
00889   // If no change ie still talking or still silent, resent frame counter
00890   if (inTalkBurst == haveSignal)
00891     framesReceived = 0;
00892   else {
00893     framesReceived++;
00894     // If have had enough consecutive frames talking/silent, swap modes.
00895     if (framesReceived >= (inTalkBurst ? silenceDeadbandFrames : signalDeadbandFrames)) {
00896       inTalkBurst = !inTalkBurst;
00897       PTRACE(4, "Codec\tSilence detection transition: "
00898              << (inTalkBurst ? "Talk" : "Silent")
00899              << " level=" << level << " threshold=" << levelThreshold);
00900 
00901       // If we had talk/silence transition restart adaptive threshold measurements
00902       signalMinimum = UINT_MAX;
00903       silenceMaximum = 0;
00904       signalFramesReceived = 0;
00905       silenceFramesReceived = 0;
00906     }
00907   }
00908 
00909   if (silenceDetectMode == FixedSilenceDetection)
00910     return !inTalkBurst;
00911 
00912   if (levelThreshold == 0) {
00913     if (level > 1) {
00914       // Bootstrap condition, use first frame level as silence level
00915       levelThreshold = level/2;
00916       PTRACE(4, "Codec\tSilence detection threshold initialised to: " << levelThreshold);
00917     }
00918     return TRUE; // inTalkBurst always FALSE here, so return silent
00919   }
00920 
00921   // Count the number of silent and signal frames and calculate min/max
00922   if (haveSignal) {
00923     if (level < signalMinimum)
00924       signalMinimum = level;
00925     signalFramesReceived++;
00926   }
00927   else {
00928     if (level > silenceMaximum)
00929       silenceMaximum = level;
00930     silenceFramesReceived++;
00931   }
00932 
00933   // See if we have had enough frames to look at proportions of silence/signal
00934   if ((signalFramesReceived + silenceFramesReceived) > adaptiveThresholdFrames) {
00935 
00936     /* Now we have had a period of time to look at some average values we can
00937        make some adjustments to the threshold. There are four cases:
00938      */
00939     if (signalFramesReceived >= adaptiveThresholdFrames) {
00940       /* If every frame was noisy, move threshold up. Don't want to move too
00941          fast so only go a quarter of the way to minimum signal value over the
00942          period. This avoids oscillations, and time will continue to make the
00943          level go up if there really is a lot of background noise.
00944        */
00945       int delta = (signalMinimum - levelThreshold)/4;
00946       if (delta != 0) {
00947         levelThreshold += delta;
00948         PTRACE(4, "Codec\tSilence detection threshold increased to: " << levelThreshold);
00949       }
00950     }
00951     else if (silenceFramesReceived >= adaptiveThresholdFrames) {
00952       /* If every frame was silent, move threshold down. Again do not want to
00953          move too quickly, but we do want it to move faster down than up, so
00954          move to halfway to maximum value of the quiet period. As a rule the
00955          lower the threshold the better as it would improve response time to
00956          the start of a talk burst.
00957        */
00958       unsigned newThreshold = (levelThreshold + silenceMaximum)/2 + 1;
00959       if (levelThreshold != newThreshold) {
00960         levelThreshold = newThreshold;
00961         PTRACE(4, "Codec\tSilence detection threshold decreased to: " << levelThreshold);
00962       }
00963     }
00964     else if (signalFramesReceived > silenceFramesReceived) {
00965       /* We haven't got a definitive silent or signal period, but if we are
00966          constantly hovering at the threshold and have more signal than
00967          silence we should creep up a bit.
00968        */
00969       levelThreshold++;
00970       PTRACE(4, "Codec\tSilence detection threshold incremented to: " << levelThreshold
00971              << " signal=" << signalFramesReceived << ' ' << signalMinimum
00972              << " silence=" << silenceFramesReceived << ' ' << silenceMaximum);
00973     }
00974 
00975     signalMinimum = UINT_MAX;
00976     silenceMaximum = 0;
00977     signalFramesReceived = 0;
00978     silenceFramesReceived = 0;
00979   }
00980 
00981   return !inTalkBurst;
00982 }
00983 
00984 
00985 unsigned H323AudioCodec::GetAverageSignalLevel()
00986 {
00987   return UINT_MAX;
00988 }
00989 
00990 BOOL H323AudioCodec::SetRawDataHeld(BOOL hold) { 
00991         
00992   PTimedMutex m;
00993         m.Wait(50);    // wait for 50ms to avoid current locks
00994         IsRawDataHeld = hold; 
00995         m.Wait(50);     // wait for 50ms to avoid any further locks
00996         return TRUE;
00997 } 
00998 
01000 
01001 H323FramedAudioCodec::H323FramedAudioCodec(const OpalMediaFormat & fmt, Direction dir)
01002   : H323AudioCodec(fmt, dir),
01003     sampleBuffer(samplesPerFrame)
01004 {
01005   bytesPerFrame = mediaFormat.GetFrameSize();
01006 }
01007 
01008 
01009 BOOL H323FramedAudioCodec::Read(BYTE * buffer, unsigned & length, RTP_DataFrame &)
01010 {
01011   PWaitAndSignal mutex(rawChannelMutex);
01012 
01013   if (direction != Encoder) {
01014     PTRACE(1, "Codec\tAttempt to decode from encoder");
01015     return FALSE;
01016   }
01017 
01018   if (IsRawDataHeld) {   // If connection is onHold
01019     PProcess::Sleep(5);  // Sleep to avoid CPU overload. <--Should be a better method but it works :)
01020     length = 0;
01021     return TRUE;
01022   }
01023 
01024   PINDEX numBytes = samplesPerFrame*2;
01025   PINDEX count;
01026   if (!ReadRaw(sampleBuffer.GetPointer(samplesPerFrame), numBytes, count))
01027     return FALSE;
01028 
01029 #ifdef H323_AEC
01030     if (aec != NULL) {
01031        PTRACE(6,"AEC\tSend " << numBytes);
01032        aec->Send((BYTE*)sampleBuffer.GetPointer(samplesPerFrame),(unsigned &)numBytes);
01033     }
01034 #endif
01035 
01036   if (IsRawDataHeld) {
01037     length = 0;
01038     return TRUE;
01039   }
01040 
01041   if (count != numBytes) {
01042     PTRACE(1, "Codec\tRead truncated frame of raw data. Wanted " << numBytes << " and got "<<count);
01043     return FALSE;
01044   }
01045 
01046   if (DetectSilence()) {
01047     length = 0;
01048     return TRUE;
01049   }
01050 
01051   // Default length is the frame size
01052   length = bytesPerFrame;
01053   return EncodeFrame(buffer, length);
01054 }
01055 
01056 
01057 BOOL H323FramedAudioCodec::Write(const BYTE * buffer,
01058                                  unsigned length,
01059                                  const RTP_DataFrame & /*rtpFrame*/,
01060                                  unsigned & written)
01061 {
01062   PWaitAndSignal mutex(rawChannelMutex);
01063 
01064   if (direction != Decoder) {
01065     PTRACE(1, "Codec\tAttempt to encode from decoder");
01066     return FALSE;
01067   }
01068 
01069   // If length is zero then it indicates silence, do nothing.
01070   written = 0;
01071 
01072   unsigned bytesDecoded = samplesPerFrame*2;
01073 
01074   if (length != 0) {
01075     if (length > bytesPerFrame)
01076       length = bytesPerFrame;
01077     written = bytesPerFrame;
01078 
01079     // Decode the data
01080     if (!DecodeFrame(buffer, length, written, bytesDecoded)) {
01081       written = length;
01082       length = 0;
01083     }
01084   }
01085 
01086   // was memset(sampleBuffer.GetPointer(samplesPerFrame), 0, bytesDecoded);
01087   if (length == 0)
01088     DecodeSilenceFrame(sampleBuffer.GetPointer(bytesDecoded), bytesDecoded);
01089 
01090   // Write as 16bit PCM to sound channel
01091   if (IsRawDataHeld) {          // If Connection om Hold 
01092         PProcess::Sleep(5);     // Sleep to avoid CPU Overload <--- Must be a better way but need it to work.
01093         return TRUE;
01094   } else {
01095 #ifdef H323_AEC
01096           if (aec != NULL) {
01097                   PTRACE(6,"AEC\tReceive " << bytesDecoded);
01098                   aec->Receive((BYTE *)sampleBuffer.GetPointer(), bytesDecoded);
01099           }
01100 #endif
01101       if (!WriteRaw(sampleBuffer.GetPointer(), bytesDecoded)) 
01102                   return FALSE;
01103   }
01104           return TRUE;
01105 
01106 
01107 }
01108 
01109 
01110 unsigned H323FramedAudioCodec::GetAverageSignalLevel()
01111 {
01112   // Calculate the average signal level of this frame
01113   int sum = 0;
01114 
01115   const short * pcm = sampleBuffer;
01116   const short * end = pcm + samplesPerFrame;
01117   while (pcm != end) {
01118     if (*pcm < 0)
01119       sum -= *pcm++;
01120     else
01121       sum += *pcm++;
01122   }
01123 
01124   return sum/samplesPerFrame;
01125 }
01126 
01127 
01128 BOOL H323FramedAudioCodec::DecodeFrame(const BYTE * buffer,
01129                                        unsigned length,
01130                                        unsigned & written,
01131                                        unsigned & /*decodedBytes*/)
01132 {
01133   return DecodeFrame(buffer, length, written);
01134 }
01135 
01136 
01137 BOOL H323FramedAudioCodec::DecodeFrame(const BYTE * /*buffer*/,
01138                                        unsigned /*length*/,
01139                                        unsigned & /*written*/)
01140 {
01141   PAssertAlways(PUnimplementedFunction);
01142   return FALSE;
01143 }
01144 
01145 #ifdef H323_AEC 
01146 void H323FramedAudioCodec::AttachAEC(PAec * _aec)
01147 {
01148   aec = _aec;
01149 }
01150 #endif
01151 
01153 
01154 H323StreamedAudioCodec::H323StreamedAudioCodec(const OpalMediaFormat & fmt,
01155                                                Direction dir,
01156                                                unsigned samples,
01157                                                unsigned bits)
01158   : H323FramedAudioCodec(fmt, dir)
01159 {
01160   samplesPerFrame = samples;
01161   bytesPerFrame = (samples*bits+7)/8;
01162   bitsPerSample = bits;
01163 }
01164 
01165 
01166 BOOL H323StreamedAudioCodec::EncodeFrame(BYTE * buffer, unsigned &)
01167 {
01168   PINDEX i;
01169   unsigned short position = 0;
01170   BYTE encoded;
01171   switch (bitsPerSample) {
01172     case 8 :
01173       for (i = 0; i < (PINDEX)samplesPerFrame; i++)
01174         *buffer++ = (BYTE)Encode(sampleBuffer[i]);
01175       break;
01176     case 5 : // g.726-40 payload encoding....
01177       for (i = 0; i < (PINDEX)samplesPerFrame;i++)
01178       {
01179         // based on a 40 bits encoding, we have 8 words of 5 bits each
01180         encoded = (BYTE)Encode(sampleBuffer[i]);
01181         switch(position)
01182         {
01183           case 0: // 0 bits overflow
01184             *buffer = encoded;
01185             position++;
01186             break;
01187           case 1: // 2 bits overflow
01188             *buffer++ |= (encoded << 5);
01189             *buffer = (BYTE)(encoded >> 3);
01190             position++;
01191             break;
01192           case 2: 
01193             *buffer |= (encoded << 2);
01194             position++;
01195             break;
01196           case 3: // one bit left for word 4
01197             *buffer++ |= (encoded << 7);
01198             *buffer = (BYTE)(encoded >> 1);
01199             position++;
01200             break;
01201           case 4:
01202             *buffer++ |= (encoded << 4);
01203             *buffer = (BYTE)(encoded >> 4);
01204             position++;
01205             break;
01206           case 5:
01207             *buffer |= (encoded << 1);
01208             position++;
01209             break;
01210           case 6: //two bits left for the new encoded word
01211             *buffer++ |= (encoded << 6);
01212             *buffer =  (BYTE)(encoded >> 2);
01213             position++;
01214             break;
01215           case 7: // now five bits left for the last word
01216             *buffer++ |= (encoded << 3);
01217             position = 0;
01218             break;
01219         }
01220       }
01221       break;
01222 
01223     case 4 :
01224       for (i = 0; i < (PINDEX)samplesPerFrame; i++) {
01225         if ((i&1) == 0)
01226           *buffer = (BYTE)Encode(sampleBuffer[i]);
01227         else
01228           *buffer++ |= (BYTE)(Encode(sampleBuffer[i]) << 4);
01229       }
01230       break;
01231 
01232     case 3 :
01233       for (i = 0;i < (PINDEX)samplesPerFrame;i++)
01234       {
01235         encoded = (BYTE)Encode(sampleBuffer[i]);
01236         switch(position)
01237         {
01238           case 0: // 0 bits overflow
01239             *buffer = encoded;
01240             position++;
01241             break;
01242           case 1: // 2 bits overflow
01243             *buffer |= (encoded << 3);
01244             position++;
01245             break;
01246           case 2: 
01247             *buffer++ |= (encoded << 6);
01248             *buffer = (BYTE)(encoded >> 2);
01249             position++;
01250             break;
01251           case 3: // one bit left for word 4
01252             *buffer |= (encoded << 1);
01253             position++;
01254             break;
01255           case 4:
01256             *buffer |= (encoded << 4);
01257             position++;
01258             break;
01259           case 5:
01260             *buffer++ |= (encoded << 7);
01261             *buffer = (BYTE)(encoded >> 1);
01262             position++;
01263             break;
01264           case 6: //two bits left for the new encoded word
01265             *buffer |= (encoded << 2);
01266             position++;
01267             break;
01268           case 7: // now five bits left for the last word
01269             *buffer++ |= (encoded << 5);
01270             position = 0;
01271             break;
01272         }
01273       }
01274       break;
01275 
01276     case 2:
01277       for (i = 0; i < (PINDEX)samplesPerFrame; i++) 
01278       {
01279         switch(position)
01280         {
01281           case 0:
01282             *buffer = (BYTE)Encode(sampleBuffer[i]);
01283             position++;
01284             break;
01285           case 1:
01286             *buffer |= (BYTE)(Encode(sampleBuffer[i]) << 2);
01287             position++;
01288             break;
01289           case 2:
01290             *buffer |= (BYTE)(Encode(sampleBuffer[i]) << 4);
01291             position++;
01292             break;
01293           case 3:
01294             *buffer++ |= (BYTE)(Encode(sampleBuffer[i]) << 6);
01295             position = 0;
01296             break;
01297         }
01298       }
01299       break;
01300 
01301     default :
01302       PAssertAlways("Unsupported bit size");
01303       return FALSE;
01304   }
01305   
01306   return TRUE;
01307 }
01308 
01309 
01310 BOOL H323StreamedAudioCodec::DecodeFrame(const BYTE * buffer,
01311                                          unsigned length,
01312                                          unsigned & written,
01313                                          unsigned & decodedBytes)
01314 {
01315   unsigned i;
01316   
01317   short * sampleBufferPtr = sampleBuffer.GetPointer(samplesPerFrame);
01318   short * out = sampleBufferPtr;
01319   unsigned short position = 0;
01320   unsigned remaining = 0;
01321   
01322   switch (bitsPerSample) {
01323     case 8 :
01324       for (i = 0; i < length; i++)
01325         *out++ = Decode(*buffer++);
01326       break;
01327 
01328     // those case are for ADPCM G.726
01329     case 5 :
01330       for (i = 0; i < length; i++) {
01331         switch(position)
01332         {
01333           case 0:
01334             *out++ = Decode(*buffer & 31);
01335             remaining = *buffer >> 5; // get the three remaining bytes for the next word
01336             buffer++;
01337             position++;
01338             break;
01339           case 1: // we can decode more than one word in second buffer
01340             *out++ = Decode (((*buffer&3) << 3) | remaining);
01341             *out++ = Decode( (*buffer >> 2) & 31);
01342             remaining = *buffer >> 7;
01343             buffer++;
01344             position++;
01345             break;
01346           case 2:
01347             *out++ = Decode( remaining | ((*buffer&15) << 1));
01348             remaining = *buffer >> 4;
01349             buffer++;
01350             position++;
01351             break;
01352           case 3:
01353             *out++ = Decode( remaining | ((*buffer&1) << 4));
01354             *out++ = Decode( (*buffer >> 1) & 31);
01355             remaining = *buffer >> 6;
01356             buffer++;
01357             position++;
01358             break;
01359           case 4 :
01360             *out++ = Decode( remaining | ((*buffer&7) << 2));
01361             *out++ = Decode(*buffer >> 3);
01362             buffer++;
01363             position = 0;
01364             break;
01365         }
01366       }
01367       break;
01368 
01369     case 4 :
01370       for (i = 0; i < length; i++) {
01371         *out++ = Decode(*buffer & 15);
01372         *out++ = Decode(*buffer >> 4);
01373         buffer++;
01374       }
01375       break;
01376 
01377     case 3:
01378       for (i = 0; i < length; i++) {
01379         switch(position)
01380         {
01381         case 0:
01382           *out++ = Decode(*buffer & 7);
01383           *out++ = Decode((*buffer>>3)&7);
01384           remaining = *buffer >> 6;
01385           buffer++;
01386           position++;
01387           break;
01388         case 1:
01389           *out++ = Decode(remaining | ((*buffer&1) << 2));
01390           *out++ = Decode((*buffer >> 1) & 7);
01391           *out++ = Decode((*buffer >> 4)&7);
01392           remaining = *buffer >> 7;
01393           buffer++;
01394           position++;
01395           break;
01396         case 2:
01397           *out++ = Decode(remaining | ((*buffer&3) << 1));
01398           *out++ = Decode((*buffer >> 2) & 7);
01399           *out++ = Decode((*buffer >> 5) & 7);
01400           buffer++;
01401           position = 0;
01402           break;
01403         }
01404       }
01405       break;
01406 
01407     case 2:
01408       for (i = 0; i < length; i++) 
01409       {
01410         *out++ = Decode(*buffer & 3);
01411         *out++ = Decode((*buffer >> 2) & 3);
01412         *out++ = Decode((*buffer >> 4) & 3);
01413         *out++ = Decode((*buffer >> 6) & 3);
01414         buffer++;
01415       
01416       }
01417       break;
01418 
01419     default :
01420       PAssertAlways("Unsupported bit size");
01421       return FALSE;
01422   }
01423 
01424   written = length;
01425   decodedBytes = (out - sampleBufferPtr)*2;
01426   
01427   return TRUE;
01428 }
01429 
01430 
01432 
01433 H323_ALawCodec::H323_ALawCodec(Direction dir,
01434                                BOOL at56kbps,
01435                                unsigned frameSize)
01436   : H323StreamedAudioCodec(OpalG711ALaw, dir, frameSize, 8)
01437 {
01438   sevenBit = at56kbps;
01439 
01440   PTRACE(3, "Codec\tG711 ALaw " << (dir == Encoder ? "en" : "de")
01441          << "coder created for at "
01442          << (sevenBit ? "56k" : "64k") << ", " << frameSize << " samples");
01443 }
01444 
01445 
01446 
01447 int H323_ALawCodec::EncodeSample(short sample)
01448 {
01449   return linear2alaw(sample);
01450 }
01451 
01452 
01453 short H323_ALawCodec::DecodeSample(int sample)
01454 {
01455   return (short)alaw2linear((unsigned char)sample);
01456 }
01457 
01458 
01460 
01461 H323_muLawCodec::H323_muLawCodec(Direction dir,
01462                                  BOOL at56kbps,
01463                                  unsigned frameSize)
01464   : H323StreamedAudioCodec(OpalG711uLaw, dir, frameSize, 8)
01465 {
01466   sevenBit = at56kbps;
01467 
01468   PTRACE(3, "Codec\tG711 uLaw " << (dir == Encoder ? "en" : "de")
01469          << "coder created for at "
01470          << (sevenBit ? "56k" : "64k") << ", frame of " << frameSize << " samples");
01471 }
01472 
01473 
01474 int H323_muLawCodec::EncodeSample(short sample)
01475 {
01476   return linear2ulaw(sample);
01477 }
01478 
01479 
01480 short H323_muLawCodec::DecodeSample(int sample)
01481 {
01482   return (short)ulaw2linear((unsigned char)sample);
01483 }
01484 
01485 
01487 
01488 #endif // NO_H323_AUDIO_CODECS

Generated on Thu Oct 25 13:42:38 2007 for h323plus by  doxygen 1.5.2