home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / openh323.tar.gz / openh323.tar / openh323 / src / h261codec.cxx < prev    next >
C/C++ Source or Header  |  2003-04-03  |  28KB  |  859 lines

  1. /*
  2.  * h261codec.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.  * Contributor(s): Michele Piccini (michele@piccini.com)
  25.  *                 Derek Smithies (derek@indranet.co.nz)
  26.  *
  27.  * $Log: h261codec.cxx,v $
  28.  * Revision 1.56  2003/04/03 23:54:15  robertj
  29.  * Added fast update to H.261 codec, thanks Gustavo Garcφa Bernardo
  30.  *
  31.  * Revision 1.55  2003/03/20 23:45:46  dereks
  32.  * Make formatting more consistant with the openh323.org standard.
  33.  *
  34.  * Revision 1.54  2003/03/17 08:05:02  robertj
  35.  * Removed videoio classes in openh323 as now has versions in pwlib.
  36.  *
  37.  * Revision 1.53  2003/03/11 22:05:00  dereks
  38.  * Video receive will not terminate in abnormal situations
  39.  * Thanks to Damien Sandras.
  40.  *
  41.  * Revision 1.52  2002/12/29 22:35:34  dereks
  42.  * Fix so video with Windows XP works. Thanks Damien Sandras.
  43.  *
  44.  * Revision 1.51  2002/12/24 07:38:49  robertj
  45.  * Patches to fix divide by zero error, thanks Damien Sandras
  46.  *
  47.  * Revision 1.50  2002/12/16 09:11:19  robertj
  48.  * Added new video bit rate control, thanks Walter H. Whitlock
  49.  *
  50.  * Revision 1.49  2002/08/05 10:03:47  robertj
  51.  * Cosmetic changes to normalise the usage of pragma interface/implementation.
  52.  *
  53.  * Revision 1.48  2002/05/19 22:03:45  dereks
  54.  * Add fix from Sean Miceli, so correct P64Decoder is picked in calls with Netmeeting.
  55.  * Many thanks, good work!
  56.  *
  57.  * Revision 1.47  2002/04/26 04:58:34  dereks
  58.  * Add Walter Whitlock's fixes, based on Victor Ivashim's suggestions to improve
  59.  * the quality with Netmeeting. Thanks guys!!!
  60.  *
  61.  * Revision 1.46  2002/04/05 00:53:19  dereks
  62.  * Modify video frame encoding so that frame is encoded on an incremental basis.
  63.  * Thanks to Walter Whitlock - good work.
  64.  *
  65.  * Revision 1.45  2002/01/09 06:07:13  robertj
  66.  * Fixed setting of RTP timestamp values on video transmission.
  67.  *
  68.  * Revision 1.44  2002/01/09 00:21:39  robertj
  69.  * Changes to support outgoing H.245 RequstModeChange.
  70.  *
  71.  * Revision 1.43  2002/01/08 01:30:41  robertj
  72.  * Tidied up some PTRACE debug output.
  73.  *
  74.  * Revision 1.42  2002/01/03 23:05:50  dereks
  75.  * Add methods to count number of H261 packets waiting to be sent.
  76.  *
  77.  * Revision 1.41  2001/12/20 01:19:43  dereks
  78.  * modify ptrace statments.
  79.  *
  80.  * Revision 1.40  2001/12/13 03:01:23  dereks
  81.  * Modify trace statement.
  82.  *
  83.  * Revision 1.39  2001/12/04 05:13:12  robertj
  84.  * Added videa bandwidth limiting code for H.261, thanks Jose Luis Urien.
  85.  *
  86.  * Revision 1.38  2001/12/04 04:26:06  robertj
  87.  * Added code to allow change of video quality in H.261, thanks Damian Sandras
  88.  *
  89.  * Revision 1.37  2001/10/23 02:17:16  dereks
  90.  * Initial release of cu30 video codec.
  91.  *
  92.  * Revision 1.36  2001/09/26 01:59:31  robertj
  93.  * Fixed MSVC warning.
  94.  *
  95.  * Revision 1.35  2001/09/25 03:14:47  dereks
  96.  * Add constant bitrate control for the h261 video codec.
  97.  * Thanks Tiziano Morganti for the code to set bit rate. Good work!
  98.  *
  99.  * Revision 1.34  2001/09/21 02:51:29  robertj
  100.  * Added default session ID to media format description.
  101.  *
  102.  * Revision 1.33  2001/08/22 01:28:20  robertj
  103.  * Resolved confusion with YUV411P and YUV420P video formats, thanks Mark Cooke.
  104.  *
  105.  * Revision 1.32  2001/07/09 07:19:40  rogerh
  106.  * Make the encoder render a frames (for local video) only when there is a
  107.  * renderer attached
  108.  *
  109.  * Revision 1.31  2001/06/19 02:01:42  dereks
  110.  * The video encoder thread ends if the renderframe fails.
  111.  *
  112.  * Revision 1.30  2001/06/13 21:46:37  dereks
  113.  * Add 5 msec separator between consecutive packets generated from the same
  114.  * frame. Prevents lost packets, and improves reliability.
  115.  *
  116.  * Revision 1.29  2001/05/25 01:10:26  dereks
  117.  * Remove unnecessary packet receive variable.
  118.  * Alter the position of the check for change in frame size.
  119.  *
  120.  * Revision 1.28  2001/02/09 05:13:55  craigs
  121.  * Added pragma implementation to (hopefully) reduce the executable image size
  122.  * under Linux
  123.  *
  124.  * Revision 1.27  2001/01/25 07:27:16  robertj
  125.  * Major changes to add more flexible OpalMediaFormat class to normalise
  126.  *   all information about media types, especially codecs.
  127.  *
  128.  * Revision 1.26  2000/12/19 22:33:44  dereks
  129.  * Adjust so that the video channel is used for reading/writing raw video
  130.  * data, which better modularizes the video codec.
  131.  *
  132.  * Revision 1.25  2000/10/13 02:20:32  robertj
  133.  * Fixed capability clone so gets all fields including those in ancestor.
  134.  *
  135.  * Revision 1.24  2000/10/13 01:47:26  dereks
  136.  * Include command option for setting the number of transmitted video
  137.  * frames per second.   use --videotxfps n
  138.  *
  139.  * Revision 1.23  2000/09/08 06:41:38  craigs
  140.  * Added ability to set video device
  141.  * Added ability to select test input frames
  142.  *
  143.  * Revision 1.22  2000/08/28 23:47:41  dereks
  144.  * Fix bug in resizing image of received video
  145.  *
  146.  * Revision 1.21  2000/08/21 04:45:06  dereks
  147.  * Fix dangling pointer that caused segfaults for windows&unix users.
  148.  * Improved the test image which is used when video grabber won't open.
  149.  * Added code to handle setting of video Tx Quality.
  150.  * Added code to set the number of background blocks sent with every frame.
  151.  *
  152.  * Revision 1.20  2000/07/13 12:31:31  robertj
  153.  * Fixed format name output for in band switching H.261
  154.  *
  155.  * Revision 1.19  2000/07/04 13:00:36  craigs
  156.  * Fixed problem with selecting large and small video sizes
  157.  *
  158.  * Revision 1.18  2000/06/10 09:21:36  rogerh
  159.  * Make GetFormatName return H.261 QCIF or H.261 CIF
  160.  *
  161.  * Revision 1.17  2000/05/10 04:05:34  robertj
  162.  * Changed capabilities so has a function to get name of codec, instead of relying on PrintOn.
  163.  *
  164.  * Revision 1.16  2000/05/02 04:32:26  robertj
  165.  * Fixed copyright notice comment.
  166.  *
  167.  * Revision 1.15  2000/04/29 03:01:48  robertj
  168.  * Fixed bug in receive of H261 capability, setting cif & qcif variables correctly.
  169.  *
  170.  * Revision 1.14  2000/03/24 01:23:49  robertj
  171.  * Directory reorganisation.
  172.  *
  173.  * Revision 1.13  2000/03/21 03:06:49  robertj
  174.  * Changes to make RTP TX of exact numbers of frames in some codecs.
  175.  *
  176.  * Revision 1.12  2000/02/10 03:08:02  craigs
  177.  * Added ability to specify NTSC or PAL video format
  178.  *
  179.  * Revision 1.11  2000/02/04 05:11:19  craigs
  180.  * Updated for new Makefiles and for new video transmission code
  181.  *
  182.  * Revision 1.10  2000/01/13 04:03:45  robertj
  183.  * Added video transmission
  184.  *
  185.  * Revision 1.9  1999/12/23 23:02:35  robertj
  186.  * File reorganision for separating RTP from H.323 and creation of LID for VPB support.
  187.  *
  188.  * Revision 1.8  1999/11/29 08:20:47  craigs
  189.  * Updated for new codec interface
  190.  *
  191.  * Revision 1.7  1999/11/01 00:52:00  robertj
  192.  * Fixed various problems in video, especially ability to pass error return value.
  193.  *
  194.  * Revision 1.6  1999/10/08 09:59:03  robertj
  195.  * Rewrite of capability for sending multiple audio frames
  196.  *
  197.  * Revision 1.5  1999/10/08 04:58:38  robertj
  198.  * Added capability for sending multiple audio frames in single RTP packet
  199.  *
  200.  * Revision 1.4  1999/09/21 14:13:53  robertj
  201.  * Windows MSVC compatibility.
  202.  *
  203.  * Revision 1.3  1999/09/21 08:10:03  craigs
  204.  * Added support for video devices and H261 codec
  205.  *
  206.  * Revision 1.2  1999/09/18 13:24:38  craigs
  207.  * Added ability to disable jitter buffer
  208.  * Added ability to access entire RTP packet in codec Write
  209.  *
  210.  * Revision 1.1  1999/09/08 04:05:49  robertj
  211.  * Added support for video capabilities & codec, still needs the actual codec itself!
  212.  *
  213.  */
  214.  
  215. #include <ptlib.h>
  216.  
  217. #ifdef __GNUC__
  218. #pragma implementation "h261codec.h"
  219. #endif
  220.  
  221. #include "h261codec.h"
  222.  
  223. #include "h245.h"
  224. #include "rtp.h"
  225.  
  226. #include "vic/p64.h"
  227. #include "vic/p64encoder.h"
  228.  
  229.  
  230. #define new PNEW
  231. #define INC_ENCODE 1
  232.  
  233.  
  234. static OpalMediaFormat const H261_MediaFormat("H.261",
  235.                                               OpalMediaFormat::DefaultVideoSessionID,
  236.                                               RTP_DataFrame::H261,
  237.                                               FALSE,  // No jitter for video
  238.                                               240000, // bits/sec
  239.                                               2000,   // Not sure of this value!
  240.                                               0,      // No intrinsic time per frame
  241.                                               OpalMediaFormat::VideoTimeUnits);
  242.  
  243.  
  244. H323_H261Capability::H323_H261Capability(unsigned _qcifMPI,
  245.                                          unsigned _cifMPI,
  246.                                          BOOL _temporalSpatialTradeOffCapability,
  247.                                          BOOL _stillImageTransmission,
  248.                                          unsigned _maxBitRate)
  249. {
  250.   qcifMPI = _qcifMPI;
  251.   cifMPI = _cifMPI;
  252.   temporalSpatialTradeOffCapability = _temporalSpatialTradeOffCapability;
  253.   maxBitRate = _maxBitRate;
  254.   stillImageTransmission = _stillImageTransmission;
  255. }
  256.  
  257.  
  258. PObject * H323_H261Capability::Clone() const
  259. {
  260.   return new H323_H261Capability(*this);
  261. }
  262.  
  263.  
  264. PObject::Comparison H323_H261Capability::Compare(const PObject & obj) const
  265. {
  266.   Comparison result = H323Capability::Compare(obj);
  267.   if (result != EqualTo)
  268.     return result;
  269.  
  270.   PAssert(obj.IsDescendant(H323_H261Capability::Class()), PInvalidCast);
  271.   const H323_H261Capability & other = (const H323_H261Capability &)obj;
  272.  
  273.   if (((qcifMPI > 0) && (other.qcifMPI > 0)) ||
  274.       ((cifMPI  > 0) && (other.cifMPI > 0)))
  275.     return EqualTo;
  276.  
  277.   if (qcifMPI > 0)
  278.     return LessThan;
  279.  
  280.   return GreaterThan;
  281. }
  282.  
  283.  
  284. PString H323_H261Capability::GetFormatName() const
  285. {
  286.   if (qcifMPI > 0 && cifMPI > 0)
  287.     return "H.261-(Q)CIF";
  288.  
  289.   if (qcifMPI > 0)
  290.     return "H.261-QCIF";
  291.  
  292.   if (cifMPI > 0)
  293.     return "H.261-CIF";
  294.  
  295.   return "H.261";
  296. }
  297.  
  298.  
  299. unsigned H323_H261Capability::GetSubType() const
  300. {
  301.   return H245_VideoCapability::e_h261VideoCapability;
  302. }
  303.  
  304.  
  305.  
  306.  
  307. BOOL H323_H261Capability::OnSendingPDU(H245_VideoCapability & cap) const
  308. {
  309.   cap.SetTag(H245_VideoCapability::e_h261VideoCapability);
  310.  
  311.   H245_H261VideoCapability & h261 = cap;
  312.   if (qcifMPI > 0) {
  313.     h261.IncludeOptionalField(H245_H261VideoCapability::e_qcifMPI);
  314.     h261.m_qcifMPI = qcifMPI;
  315.   }
  316.   if (cifMPI > 0) {
  317.     h261.IncludeOptionalField(H245_H261VideoCapability::e_cifMPI);
  318.     h261.m_cifMPI = cifMPI;
  319.   }
  320.   h261.m_temporalSpatialTradeOffCapability = temporalSpatialTradeOffCapability;
  321.   h261.m_maxBitRate = maxBitRate;
  322.   h261.m_stillImageTransmission = stillImageTransmission;
  323.   return TRUE;
  324. }
  325.  
  326.  
  327. BOOL H323_H261Capability::OnSendingPDU(H245_VideoMode & pdu) const
  328. {
  329.   pdu.SetTag(H245_VideoMode::e_h261VideoMode);
  330.   H245_H261VideoMode & mode = pdu;
  331.   mode.m_resolution.SetTag(cifMPI > 0 ? H245_H261VideoMode_resolution::e_cif
  332.                                       : H245_H261VideoMode_resolution::e_qcif);
  333.   mode.m_bitRate = maxBitRate;
  334.   mode.m_stillImageTransmission = stillImageTransmission;
  335.   return TRUE;
  336. }
  337.  
  338.  
  339. BOOL H323_H261Capability::OnReceivedPDU(const H245_VideoCapability & cap)
  340. {
  341.   if (cap.GetTag() != H245_VideoCapability::e_h261VideoCapability)
  342.     return FALSE;
  343.  
  344.   const H245_H261VideoCapability & h261 = cap;
  345.   if (h261.HasOptionalField(H245_H261VideoCapability::e_qcifMPI))
  346.     qcifMPI = h261.m_qcifMPI;
  347.   else
  348.     qcifMPI = 0;
  349.   if (h261.HasOptionalField(H245_H261VideoCapability::e_cifMPI))
  350.     cifMPI = h261.m_cifMPI;
  351.   else
  352.     cifMPI = 0;
  353.   temporalSpatialTradeOffCapability = h261.m_temporalSpatialTradeOffCapability;
  354.   maxBitRate = h261.m_maxBitRate;
  355.   stillImageTransmission = h261.m_stillImageTransmission;
  356.   return TRUE;
  357. }
  358.  
  359.  
  360. H323Codec * H323_H261Capability::CreateCodec(H323Codec::Direction direction) const
  361. {
  362.   return new H323_H261Codec(direction, qcifMPI > 0);
  363. }
  364.  
  365.  
  366. //////////////////////////////////////////////////////////////////////////////
  367.  
  368. H323_H261Codec::H323_H261Codec(Direction dir, BOOL isqCIF)
  369.   : H323VideoCodec("H.261", dir)
  370. {
  371.   PTRACE(3, "H261\t" << (isqCIF ? "Q" : "") << "CIF "
  372.          << (dir == Encoder ? "en" : "de") << "coder created.");
  373.  
  374.   // no video decoder until we receive a packet
  375.   videoDecoder = NULL;
  376.  
  377.   // no video encoder until we receive a packet
  378.   videoEncoder = NULL;
  379.  
  380.  
  381.   // other stuff
  382.   now = 1;
  383.   rvts = NULL;
  384.   nblk = ndblk = 0;
  385.  
  386.   // initial size of the window is CIF
  387.   if (dir == Encoder) {
  388.     frameWidth  = isqCIF ? QCIF_WIDTH  : CIF_WIDTH;
  389.     frameHeight = isqCIF ? QCIF_HEIGHT : CIF_HEIGHT;
  390.   } else {
  391.     frameWidth=0;
  392.     frameHeight=0;
  393.   }
  394.  
  395.   frameNum = 0; // frame counter
  396.   timestampDelta = 0;
  397.   videoBitRateControlModes = None;
  398.  
  399.   // video quality control
  400.   videoQMin = 1;
  401.   videoQMax = 24;
  402.   videoQuality = 9; // default = 9
  403.   //SetTxQualityLevel( videoQuality ); // don't have encoder yet
  404.  
  405.   // video bit rate control
  406.   sumFrameTimeMs = 0;
  407.   sumAdjFrameTimeMs = 0;
  408.   sumFrameBytes = 0;
  409.   bitRateHighLimit = 0;
  410.   videoBitRateControlModes = None;
  411.   targetFrameTimeMs = 167;
  412.   oldTime = newTime = 0;
  413. }
  414.  
  415.  
  416. H323_H261Codec::~H323_H261Codec()
  417. {
  418.   PWaitAndSignal mutex1(videoHandlerActive);
  419.  
  420.   if (videoDecoder)
  421.   {
  422.     delete videoDecoder;
  423.     videoDecoder = NULL;
  424.   }
  425.  
  426.   if (videoEncoder){
  427.     delete videoEncoder;
  428.     videoEncoder = NULL;
  429.   }
  430.  
  431.   if (rvts){
  432.     delete rvts;
  433.   }
  434. }
  435.  
  436.  
  437. //This function grabs, displays, and compresses a video frame into
  438. //into H261 packets.
  439. //Get another frame if all packets of previous frame have been sent.
  440. //Get next packet on list and send that one.
  441. //Render the current frame if all of its packets have been sent.
  442. BOOL H323_H261Codec::Read(BYTE * buffer,
  443.                           unsigned & length,
  444.                           RTP_DataFrame & frame)
  445. {
  446.   PWaitAndSignal mutex1(videoHandlerActive);
  447.   PTRACE(6,"H261\tAcquire next packet from h261 encoder.\n");
  448.  
  449.   if ( videoEncoder == NULL )
  450.       videoEncoder = new P64Encoder(videoQuality, fillLevel);
  451.  
  452.   if( rawDataChannel == NULL ) {
  453.     length = 0;
  454.     PTRACE(1,"H261\tNo channel to connect to video grabber, close down video transmission thread.");
  455.     return FALSE;
  456.   }
  457.  
  458.   if( !rawDataChannel->IsOpen() ) {
  459.      PTRACE(1,"H261\tVideo grabber is not initialised, close down video transmission thread.");
  460.      length = 0;
  461.      return FALSE;
  462.   }
  463.  
  464.   frameWidth  = ((PVideoChannel *)rawDataChannel)->GetGrabWidth();
  465.   frameHeight = ((PVideoChannel *)rawDataChannel)->GetGrabHeight();
  466.   PTRACE(6, "H261\tVideo grab size is " << frameWidth << "x" << frameHeight);
  467.  
  468.   if( frameWidth == 0 ) {
  469.     PTRACE(1,"H261\tVideo grab width is 0 x 0, close down video transmission thread.");
  470.     length=0;
  471.     return FALSE;
  472.   }
  473.  
  474.   videoEncoder->SetSize(frameWidth, frameHeight);
  475.  
  476.   PINDEX bytesInFrame = 0;
  477.   BOOL ok = TRUE;
  478.  
  479. #define NUMAVG 8
  480.  
  481. #ifdef INC_ENCODE
  482.   if( !videoEncoder->MoreToIncEncode() ) { // get a new frame
  483. #else
  484.   if( !videoEncoder->PacketsOutStanding() ) { // }get a new frame
  485. #endif
  486.     if (0 == frameNum) { // frame 0 means no frame has been sent yet
  487.       frameStartTime = PTimer::Tick();
  488.     }
  489.     else {
  490.       int frameTimeMs, avgFrameTimeMs, adjFrameTimeMs, avgAdjFrameTimeMs, avgFrameBytes;
  491.       PTimeInterval currentTime;
  492.  
  493.       currentTime = PTimer::Tick();
  494.       frameTimeMs = (int)(currentTime - frameStartTime).GetMilliSeconds();
  495.       adjFrameTimeMs = frameTimeMs - (int)grabInterval.GetMilliSeconds(); // subtract time possibly blocked in grabbing
  496.       frameStartTime = currentTime;
  497.  
  498.       sumFrameTimeMs += frameTimeMs;
  499.       avgFrameTimeMs = sumFrameTimeMs / NUMAVG;
  500.       sumFrameTimeMs -= avgFrameTimeMs;
  501.       sumAdjFrameTimeMs += adjFrameTimeMs;
  502.       avgAdjFrameTimeMs = sumAdjFrameTimeMs / NUMAVG;
  503.       sumAdjFrameTimeMs -= avgAdjFrameTimeMs;
  504.       sumFrameBytes += frameBytes;
  505.       avgFrameBytes = sumFrameBytes / NUMAVG;
  506.       sumFrameBytes -= avgFrameBytes;
  507.  
  508.       //PTRACE(3,"H261\tframeNum                             grabInterval: "
  509.       //  << frameNum << " " << grabInterval.GetMilliSeconds());
  510.       //PTRACE(3,"H261\tframeNum    frameBits       frameTimeMs       Bps: "
  511.       //  << frameNum << " " << (frameBytes*8) << " " << frameTimeMs
  512.       //  << " " << frameBytes*8*1000/frameTimeMs );
  513.       //PTRACE(3,"H261\tframeNum avgFrameBits    avgFrameTimeMs    avgBps: "
  514.       //  << frameNum << " " << (avgFrameBytes*8) << " " << avgFrameTimeMs
  515.       //  << " " << avgFrameBytes*8*1000/avgFrameTimeMs );
  516.       //PTRACE(3,"H261\tframeNum avgFrameBits avgAdjFrameTimeMs avgAdjBps: "
  517.       //  << frameNum << " " << (avgFrameBytes*8) << " " << avgAdjFrameTimeMs
  518.       //  << " " << avgFrameBytes*8*1000/avgAdjFrameTimeMs );
  519.  
  520.       if (frameNum > NUMAVG) { // do quality adjustment after first NUMAVG frames
  521.         if( 0 != targetFrameTimeMs && (videoBitRateControlModes & DynamicVideoQuality) ) {
  522.           int error; // error signal
  523.           int aerror;
  524.           int act; // action signal
  525.           int newQuality;
  526.           int avgFrameBitRate;
  527.           int targetFrameBits;
  528.  
  529.           // keep track of average frame size and
  530.           // adjust encoder quality to get targetFrameBits bits per frame
  531.       if (avgAdjFrameTimeMs)
  532.         avgFrameBitRate = avgFrameBytes*8*1000 / avgAdjFrameTimeMs; // bits per second
  533.       else
  534.         avgFrameBitRate = avgFrameBytes*8*1000;
  535.  
  536.           targetFrameBits = avgFrameBitRate * targetFrameTimeMs / 1000;
  537.           error = (frameBytes*8) - targetFrameBits; // error signal
  538.           aerror = PABS(error);
  539.  
  540.           act = 0;
  541.           if (aerror > (targetFrameBits/8) ) {
  542.             if (aerror > (targetFrameBits/4) ) {
  543.               if (aerror > (targetFrameBits/2) ) {
  544.                 act = error>0 ? 2 : -4;
  545.               }
  546.               else {
  547.                 act = error>0 ? 1 : -2;
  548.               }
  549.             }
  550.             else {
  551.               act = error>0 ? 1 : -1;
  552.             }
  553.           }
  554.           newQuality = videoQuality + act;
  555.           newQuality = PMIN(PMAX(newQuality, videoQMin), videoQMax );
  556.           //PTRACE(3,"H261\tframeNum targetFrameBits frameBits videoQuality newQuality: "
  557.           //  << frameNum << " " << targetFrameBits << " " << (frameBytes*8) << " "
  558.           //  << videoQuality << " "  << newQuality );
  559.           videoQuality = newQuality;
  560.           videoEncoder->SetQualityLevel( videoQuality );
  561.  
  562.           //PTRACE(3,"H261\tframeNum     avgFrameBitRate     bitRateHighLimit: "
  563.           //  << frameNum << " " << avgFrameBitRate << " " << bitRateHighLimit );
  564.         }
  565.       }
  566.     }
  567.  
  568.     //NO data is waiting to be read. Go and get some with the read call.
  569.     PTRACE(3,"H261\tRead frame from the video source.");
  570.     PTimeInterval grabStartTime = PTimer::Tick();
  571.     if (rawDataChannel->Read(videoEncoder->GetFramePtr(), bytesInFrame)) {
  572.       PTRACE(3,"H261\tSuccess. Read frame from the video source in "
  573.         << (PTimer::Tick() - grabStartTime).GetMilliSeconds() << " ms.");
  574.       packetNum = 0; // reset packet counter
  575.       // If there is a Renderer attached, display the grabbed video.
  576.       if (((PVideoChannel *)rawDataChannel)->IsRenderOpen() ) {
  577.         ok = RenderFrame(); //use data from grab process.
  578.       }
  579. #ifdef INC_ENCODE
  580.       videoEncoder->PreProcessOneFrame(); //Prepare to generate H261 packets
  581. #else
  582.       videoEncoder->ProcessOneFrame(); //Generate H261 packets
  583. #endif
  584.       frameNum++;
  585.     } else {
  586.       PTRACE(1,"H261\tFailed to read data from video grabber, close down video transmission thread.");
  587.       return FALSE;   //Read failed, return false.
  588.     }
  589.     grabInterval = PTimer::Tick() - grabStartTime;
  590.  
  591.     /////////////////////////////////////////////////////////////////
  592.     /// THIS VALUE MUST BE CALCULATED AND NOT JUST SET TO 29.97Hz!!!!
  593.     /////////////////////////////////////////////////////////////////
  594.     timestampDelta = 3003;
  595.     frameBytes = 0;
  596.  
  597.   }
  598.   else {  //if(!videoEncoder->PacketsOutstanding())
  599.     if( 0 != bitRateHighLimit &&
  600.       (videoBitRateControlModes & AdaptivePacketDelay) )
  601.       ; // do nothing now, packet delay will be done later
  602.     else
  603.       PThread::Current()->Sleep(5);  // Place a 5 ms interval betwen
  604.         // packets of the same frame.
  605.     timestampDelta = 0;
  606.   }
  607.  
  608. #ifdef INC_ENCODE
  609.   videoEncoder->IncEncodeAndGetPacket(buffer,length); //encode & get next packet
  610.   frame.SetMarker(!videoEncoder->MoreToIncEncode());
  611. #else
  612.   videoEncoder->ReadOnePacket(buffer,length); //get next packet on list
  613.   frame.SetMarker(!videoEncoder->PacketsOutStanding());
  614. #endif
  615.   packetNum++;
  616.  
  617.   // Monitor and report bandwidth usage.
  618.   // If controlling bandwidth, limit the video bandwidth to
  619.   // bitRateHighLimit by introducing a variable delay between packets.
  620.   PTimeInterval currentTime;
  621.   if( 0 != bitRateHighLimit &&
  622.       (videoBitRateControlModes & AdaptivePacketDelay) ) {
  623.     PTimeInterval waitBeforeSending;
  624.  
  625.     if (newTime != 0) { // calculate delay and wait
  626.       currentTime = PTimer::Tick();
  627.       waitBeforeSending = newTime - currentTime;
  628.       if (waitBeforeSending > 0) PThread::Current()->Sleep(waitBeforeSending);
  629.       // report bit rate & control error for previous packet
  630.       currentTime = PTimer::Tick(); //re-acquire current time after wait
  631.       //PTRACE(3, "H261\tBitRateControl Packet(" << oldPacketNum
  632.       //  << ") Bits: " << oldLength*8
  633.       //  << " Interval: " << (currentTime - oldTime).GetMilliSeconds()
  634.       //  << " Rate: " << oldLength*8000/(currentTime - oldTime).GetMilliSeconds()
  635.       //  << " Error: " << (currentTime - newTime).GetMilliSeconds()
  636.       //  << " Slept: " << waitBeforeSending.GetMilliSeconds() );
  637.     }
  638.     currentTime = PTimer::Tick(); // re-acquire current time due to possible PTRACE delay
  639.     // ms = (bytes * 8) / (bps / 1000)
  640.     if (bitRateHighLimit/1000)
  641.       newTime = currentTime + length*8/(bitRateHighLimit/1000);
  642.     else
  643.       newTime = currentTime + length*8;
  644.   }
  645.   else {
  646.     // monitor & report bit rate
  647.     if (oldTime != 0) { // report bit rate for previous packet
  648.       PTimeInterval currentTime = PTimer::Tick();
  649.       //PTRACE(3, "H261\tBitRateReport  Packet(" << oldPacketNum
  650.       //  << ") Bits: " << oldLength*8
  651.       //  << " Interval: " << (currentTime - oldTime).GetMilliSeconds()
  652.       //  << " Rate: " << oldLength*8000/(currentTime - oldTime).GetMilliSeconds() );
  653.     }
  654.     currentTime = PTimer::Tick(); // re-acquire current time due to possible PTRACE delay
  655.   }
  656.   //oldPacketNum = packetNum; // used only for PTRACE
  657.   oldTime = currentTime;
  658.   oldLength = length;
  659.   frameBytes += length; // count current frame bytes
  660.   return ok;
  661. }
  662.  
  663.  
  664.  
  665. BOOL H323_H261Codec::Write(const BYTE * buffer,
  666.                            unsigned length,
  667.                            const RTP_DataFrame & frame,
  668.                            unsigned & written)
  669. {
  670.   PWaitAndSignal mutex1(videoHandlerActive);
  671.  
  672.   if( rawDataChannel == NULL ) {
  673.     //Some other task has killed our videohandler. Exit.
  674.     return FALSE;
  675.   }
  676.  
  677.   BOOL lostPreviousPacket = FALSE;
  678.   if( (++lastSequenceNumber) != frame.GetSequenceNumber() ) {
  679.     lostPreviousPacket = TRUE;
  680.     PTRACE(3,"H261\tDetected loss of one video packet. "
  681.       << lastSequenceNumber << " != "
  682.       << frame.GetSequenceNumber() << " Will recover.");
  683.     lastSequenceNumber = frame.GetSequenceNumber();
  684.     //    SendMiscCommand(H245_MiscellaneousCommand_type::e_lostPartialPicture);
  685.   }
  686.  
  687.   // always indicate we have written the entire packet
  688.   written = length;
  689.  
  690.   // H.261 header is usually at start of buffer
  691.   const unsigned char * header = buffer;
  692.   // adjust for any contributing source (what's that?)
  693.   PINDEX cnt = frame.GetContribSrcCount();
  694.   if (cnt > 0) {
  695.     header += cnt * 4;
  696.     length -= cnt * 4;
  697.   }
  698.  
  699.   // determine video codec type
  700.   if (videoDecoder == NULL) {
  701.     if ((*header & 2) && !(*header & 1)) // check value of I field in header
  702.       videoDecoder = new IntraP64Decoder();
  703.     else
  704.       videoDecoder = new FullP64Decoder();
  705.     videoDecoder->marks(rvts);
  706.   }
  707.  
  708.   videoDecoder->mark(now);
  709.   BOOL ok = videoDecoder->decode(header, length, lostPreviousPacket);
  710.   if (!ok) {
  711.     PTRACE (3, "H261\t Could not decode frame, continuing in hope.");
  712.     return TRUE;
  713.   }
  714.   
  715.   // If the incoming video stream changes size, resize the rendering device.
  716.   ok = Resize(videoDecoder->width(), videoDecoder->height());
  717.  
  718.   if (ok && frame.GetMarker()) {
  719.     videoDecoder->sync();
  720.     ndblk = videoDecoder->ndblk();
  721.     ok = RenderFrame();
  722.     videoDecoder->resetndblk();
  723.   }
  724.  
  725.   return ok;
  726. }
  727.  
  728.  
  729. /* Resize is relevant to the decoder only, as the encoder does not
  730.    change size mid transmission.
  731. */
  732. BOOL H323_H261Codec::Resize(int _width, int _height)
  733. {
  734.   //Check for a resize is carried out one two level -.
  735.   // a) size change in the receive video stream.
  736.  
  737.   if ((frameWidth != _width) || (frameHeight != _height) ) {
  738.       frameWidth  = _width;
  739.       frameHeight = _height;
  740.  
  741.       nblk = (frameWidth * frameHeight) / 64;
  742.       delete rvts;
  743.       rvts = new BYTE[nblk];
  744.       memset(rvts, 0, nblk);
  745.       if (videoDecoder != NULL) 
  746.     videoDecoder->marks(rvts);
  747.       if (rawDataChannel != NULL)
  748.     ((PVideoChannel *)rawDataChannel)->SetRenderFrameSize(_width, _height);
  749.   }
  750.  
  751.   return TRUE;
  752. }
  753.  
  754.  
  755. BOOL H323_H261Codec::Redraw()
  756. {
  757.   now = 1;
  758.   memset(rvts, 1, nblk);
  759.  
  760.   return RenderFrame();
  761. }
  762.  
  763.  
  764. /* RenderFrame does three things.
  765.    a) Set internal variables
  766.    b) Set size of the display frame. This call happens with every frame.
  767.          A very small overhead.
  768.    c) Display a frame.
  769. */
  770. BOOL H323_H261Codec::RenderFrame()
  771. {
  772.   int wraptime = now ^ 0x80;
  773.   BYTE * ts = rvts;
  774.   int k;
  775.   for (k = nblk; --k >= 0; ++ts) {
  776.     if (*ts == wraptime)
  777.       *ts = (BYTE)now;
  778.   }
  779.  
  780.   BOOL ok = TRUE;
  781.   if (rawDataChannel != NULL) {
  782.  
  783.     //Now display local image.
  784.     ((PVideoChannel *)rawDataChannel)->SetRenderFrameSize(frameWidth, frameHeight);
  785.     PTRACE(6, "H261\tSize of video rendering frame set to " << 
  786.        frameWidth << "x" << frameHeight << 
  787.        " for channel:" << ((direction == Encoder) ? "encoding" : "decoding"));
  788.  
  789.     if (direction == Encoder)
  790.         ok = rawDataChannel->Write((const void *)videoEncoder->GetFramePtr(),0);
  791.       else
  792.         ok = rawDataChannel->Write((const void *)videoDecoder->GetFramePtr(),0);
  793.   }
  794.  
  795.   now = (now + 1) & 0xff;
  796.  
  797.   return ok;
  798. }
  799.  
  800.  
  801. void H323_H261Codec::SetTxQualityLevel(int qLevel)
  802. {
  803.   videoQuality = PMIN(videoQMax, PMAX(qLevel, videoQMin));
  804.  
  805.   // If a video encoder is running and if there is no
  806.   // dynamic video quality control, update the value
  807.   // in the encoder
  808.   if (!(DynamicVideoQuality & videoBitRateControlModes) && (videoEncoder != NULL))
  809.     videoEncoder->SetQualityLevel (videoQuality);
  810.   PTRACE(3, "H261\tvideoQuality set to " << videoQuality);
  811. }
  812.  
  813. void H323_H261Codec::SetTxMinQuality(int qlevel) {
  814.   videoQMin = PMIN(videoQMax, PMAX(1, qlevel));
  815.   PTRACE(3, "H261\tvideoQMin set to " << videoQMin);
  816. }
  817.  
  818. void H323_H261Codec::SetTxMaxQuality(int qlevel) {
  819.   videoQMax = PMAX(videoQMin, PMIN(31, qlevel));
  820.   PTRACE(3, "H261\tvideoQMax set to " << videoQMax);
  821. }
  822.  
  823. void H323_H261Codec::SetBackgroundFill(int idle)
  824. {
  825.   fillLevel = PMIN(99, PMAX(idle,1));
  826.  
  827.   // If a video encoder is running and if there is no
  828.   // dynamic video quality control, update the value
  829.   // in the encoder
  830.   if (!(DynamicVideoQuality & videoBitRateControlModes) && (NULL != videoEncoder))
  831.     videoEncoder->SetBackgroundFill (idle);
  832.   PTRACE(3, "H261\tfillLevel set to " << fillLevel);
  833. }
  834.  
  835.  
  836. void H323_H261Codec::OnFastUpdatePicture()
  837. {
  838.   PTRACE(3,"H261\tFastUpdatePicture received");
  839.   PWaitAndSignal mutex1(videoHandlerActive);
  840.  
  841.   if ( videoEncoder != NULL )
  842.     videoEncoder->FastUpdatePicture();
  843. }
  844.  
  845.  
  846. void H323_H261Codec::OnLostPartialPicture()
  847. {
  848.   PTRACE(3,"H261\tLost partial picture message ignored, not implemented");
  849. }
  850.  
  851.  
  852. void H323_H261Codec::OnLostPicture()
  853. {
  854.   PTRACE(3,"H261\tLost picture message ignored, not implemented");
  855. }
  856.  
  857.  
  858. /////////////////////////////////////////////////////////////////////////////
  859.