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 / h263codec.cxx < prev    next >
C/C++ Source or Header  |  2003-08-03  |  28KB  |  919 lines

  1. /*
  2.  * h263codec.cxx
  3.  *
  4.  * H.323 protocol handler
  5.  *
  6.  * Open H323 Library
  7.  * 
  8.  * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Open H323 Library. 
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions of this code were written with the financial assistance of 
  25.  *          AliceStreet (http://www.alicestreet.com) 
  26.  *
  27.  * Contributor(s): Guilhem Tardy (gtardy@marchnetworks.com)
  28.  *
  29.  * $Log: h263codec.cxx,v $
  30.  * Revision 1.23  2003/08/04 00:03:41  dereksmithies
  31.  * Reorganise test of H323_VICH263 switch
  32.  *
  33.  * Revision 1.22  2003/08/01 02:01:42  csoutheren
  34.  * Changed to disable when VIC 263 not installed
  35.  *
  36.  * Revision 1.21  2003/07/29 03:57:00  dereksmithies
  37.  * Remove weird boxes on startup.
  38.  *
  39.  * Revision 1.20  2003/07/24 08:09:18  dereksmithies
  40.  * Update to use vich263 codec, instead of ffmpeg
  41.  *
  42.  * Revision 1.19  2003/06/14 05:54:23  rjongbloed
  43.  * Fixed MSVC warning.
  44.  * Fixed what seemed an obvious mistake using boolean or operator (||) instead
  45.  *   of the bitwise or operator (|).
  46.  *
  47.  * Revision 1.18  2003/06/12 00:24:32  dereksmithies
  48.  * Modify so QCIF-CIF behaviour similar to that for h261codec.cxx
  49.  *
  50.  * Revision 1.17  2003/06/10 01:37:25  dereksmithies
  51.  * Changes so it should not crash under windows/release mode
  52.  *
  53.  * Revision 1.16  2003/06/06 06:32:08  rjongbloed
  54.  * Fixed MSVC warning
  55.  *
  56.  * Revision 1.15  2003/06/06 05:18:54  dereksmithies
  57.  * Fix startup delay bug. Remove all large packets from the network. Improve reliability.
  58.  *
  59.  * Revision 1.14  2003/06/03 05:01:23  rjongbloed
  60.  * Fixed some trace logging (removed usage of cerr)
  61.  *
  62.  * Revision 1.13  2003/06/03 00:49:01  dereksmithies
  63.  * Fix divide by zero error, which happens on win95 & win98 machines.
  64.  *
  65.  * Revision 1.12  2003/06/02 07:56:56  rjongbloed
  66.  * Fixed media format passed to ancestor codec class
  67.  *
  68.  * Revision 1.11  2003/05/27 04:20:59  dereksmithies
  69.  * Fix so that codec resizes correctly after capability exchange
  70.  * No longer crashes if one endpoint is CIF, other is QCIF.
  71.  *
  72.  * Revision 1.10  2003/05/16 04:42:24  rjongbloed
  73.  * Removed extraneous code, and other cosmetic changes.
  74.  * Fixed compare function for capability.
  75.  * Extra trace logging.
  76.  *
  77.  * Revision 1.9  2003/05/15 01:35:27  dereksmithies
  78.  * Frame length fix
  79.  *
  80.  * Revision 1.8  2003/05/14 13:51:51  rjongbloed
  81.  * Removed hack of using special payload type for H.263 for a method which
  82.  *   would be less prone to failure in the future.
  83.  * Removed static "initialisation" function as this should be done
  84.  *   internally and not in the application.
  85.  * Changed media format to be straight H.263 and not OpalH.263
  86.  * Moved Win32 stderr output in ffmpeg AVCODEC interception from
  87.  *   application to library.
  88.  * Fixed some warnings.
  89.  *
  90.  * Revision 1.7  2003/05/14 03:07:17  rjongbloed
  91.  * Made sure video buffer is large enough
  92.  *
  93.  * Revision 1.6  2003/05/05 11:59:25  robertj
  94.  * Changed to use autoconf style selection of options and subsystems.
  95.  *
  96.  * Revision 1.5  2003/05/02 04:21:30  craigs
  97.  * Added lots of extra H.263 support
  98.  *
  99.  * Revision 1.4  2003/04/21 21:50:22  dereks
  100.  * Implement suggestion from Guilhem Tardy. Many thanks.
  101.  *
  102.  * Revision 1.3  2003/04/16 04:26:57  dereks
  103.  * Initial release of h263 codec, which utilises the ffmpeg library.
  104.  * Thanks to Guilhem Tardy, and to AliceStreet.
  105.  *
  106.  * Revision 1.2  2002/08/05 10:03:47  robertj
  107.  * Cosmetic changes to normalise the usage of pragma interface/implementation.
  108.  *
  109.  * Revision 1.1  2002/05/19 22:31:12  dereks
  110.  * Initial release of stub file for h263 codec. Thanks Guilhem Tardy.
  111.  */
  112.  
  113. /*
  114.  *  Initial release notes from Guilhem Tardy::
  115.  *
  116.  * Added support for video capabilities & codec, still needs the actual codec itself!
  117.  * The code for varying bit rate is copied from h261codec.cxx,
  118.  * until it is moved to a separate file common to both video codecs.
  119.  *
  120.  */
  121. #include <ptlib.h>
  122.  
  123. #ifdef __GNUC__
  124. #pragma implementation "h263codec.h"
  125. #endif
  126.  
  127. #include "h263codec.h"
  128. #if defined(H323_VICH263)
  129.  
  130.  
  131. #include "h245.h"
  132. #include "rtp.h"
  133.  
  134. #if defined(_MSC_VER)
  135. #pragma comment(lib, H323_VICH263_LIBRARY)
  136. #endif
  137.  
  138.  
  139. #include <encoder-h263.h>
  140. #include <decoder-h263.h>
  141.  
  142. /* #define INC_ENCODE 1 */
  143.  
  144. //////////////////////////////////////////////////////////////////////////////
  145.  
  146. static void h263_vic_printon(char * str);
  147. static void h263_vic_printon(char * str)
  148. {
  149.   PTRACE(6, "Vic H263\t" << str);
  150.   strlen(str);   /*Stop any compiler warning about unused variable*/
  151. }
  152.  
  153.  
  154. class VicH263Link : public PObject
  155. {
  156.   PCLASSINFO(VicH263Link, PObject)
  157.     
  158.     public:
  159.   VicH263Link();
  160. };
  161.  
  162. VicH263Link::VicH263Link()
  163. {
  164.   vich263_set_print_fn(h263_vic_printon);
  165. }
  166.  
  167.  
  168. ///////////////////////////////////////////////////////////////////////////////////////
  169.  
  170. #define new PNEW
  171.  
  172.  
  173. static OpalMediaFormat const H263_MediaFormat("H.263",
  174.                                               OpalMediaFormat::DefaultVideoSessionID,
  175.                                               RTP_DataFrame::H263,
  176.                                               FALSE,  // No jitter for video
  177.                                               180000, // bits/sec
  178.                                               2000,   // Not sure of this value!
  179.                                               0,      // No intrinsic time per frame
  180.                                               OpalMediaFormat::VideoTimeUnits);
  181.  
  182.  
  183. //////////////////////////////////////////////////////////////////////////////
  184.  
  185. H323_H263Capability::H323_H263Capability(unsigned _sqcifMPI,
  186.                      unsigned _qcifMPI,
  187.                      unsigned _cifMPI,
  188.                      unsigned _cif4MPI,
  189.                      unsigned _cif16MPI,
  190.                      unsigned _maxBitRate,
  191.                      unsigned _videoFrameRate,
  192.                      BOOL _unrestrictedVector,
  193.                      BOOL _arithmeticCoding,
  194.                      BOOL _advancedPrediction,
  195.                      BOOL _pbFrames,
  196.                      BOOL _temporalSpatialTradeOff,
  197.                      unsigned _hrd_B,
  198.                      unsigned _bppMaxKb,
  199.                      unsigned _slowSqcifMPI,
  200.                      unsigned _slowQcifMPI,
  201.                      unsigned _slowCifMPI,
  202.                      unsigned _slowCif4MPI,
  203.                      unsigned _slowCif16MPI,
  204.                      BOOL _errorCompensation)
  205. {
  206.   sqcifMPI = (_sqcifMPI>0?_sqcifMPI:-(int)_slowSqcifMPI);
  207.   qcifMPI = (_qcifMPI>0?_qcifMPI:-(int)_slowQcifMPI);
  208.   cifMPI = (_cifMPI>0?_cifMPI:-(int)_slowCifMPI);
  209.   cif4MPI = (_cif4MPI>0?_cif4MPI:-(int)_slowCif4MPI);
  210.   cif16MPI = (_cif16MPI>0?_cif16MPI:-(int)_slowCif16MPI);
  211.  
  212.   maxBitRate = _maxBitRate;
  213.   videoFrameRate = _videoFrameRate;
  214.  
  215.   temporalSpatialTradeOff = _temporalSpatialTradeOff;
  216.   pbFrames = _pbFrames;
  217.   advancedPrediction = _advancedPrediction;
  218.   arithmeticCoding = _arithmeticCoding;
  219.   unrestrictedVector = _unrestrictedVector;
  220.  
  221.   hrd_B = _hrd_B;
  222.   bppMaxKb = _bppMaxKb;
  223.  
  224.   errorCompensation = _errorCompensation;
  225. }
  226.  
  227.  
  228. PObject * H323_H263Capability::Clone() const
  229. {
  230.   return new H323_H263Capability(*this);
  231. }
  232.  
  233.  
  234. PObject::Comparison H323_H263Capability::Compare(const PObject & obj) const
  235. {
  236.   Comparison result = H323Capability::Compare(obj);
  237.   if (result != EqualTo) 
  238.     return result;
  239.  
  240.   PAssert(obj.IsDescendant(H323_H263Capability::Class()), PInvalidCast);
  241.   const H323_H263Capability & other = (const H323_H263Capability &)obj;
  242.  
  243. /*
  244.   if ((sqcifMPI > other.sqcifMPI) ||
  245.       (qcifMPI > other.qcifMPI) ||
  246.       (cifMPI > other.cifMPI) ||
  247.       (cif4MPI > other.cif4MPI) ||
  248.       (cif16MPI > other.cif16MPI))
  249.     return GreaterThan;
  250.  
  251.   if ((cif16MPI < other.cif16MPI) ||
  252.       (cif4MPI < other.cif4MPI) ||
  253.       (cifMPI < other.cifMPI) ||
  254.       (qcifMPI < other.qcifMPI))
  255.     return LessThan;
  256. */
  257.  
  258.   if (
  259. ((sqcifMPI > 0) && (other.sqcifMPI > 0)) ||
  260. ((qcifMPI > 0) && (other.qcifMPI > 0)) ||
  261. ((cifMPI > 0) && (other.cifMPI > 0)) ||
  262. ((cif4MPI > 0) && (other.cif4MPI > 0)) ||
  263. ((cif16MPI > 0) && (other.cif16MPI > 0))
  264. )
  265.     return EqualTo;
  266.  
  267.   if (qcifMPI > 0)
  268.     return LessThan;
  269.  
  270.   return GreaterThan;
  271.  
  272.  
  273.   return EqualTo;
  274. }
  275.  
  276.  
  277. PString H323_H263Capability::GetFormatName() const
  278. {
  279.   PString ret = H263_MediaFormat;
  280.  
  281.   if (sqcifMPI)
  282.     ret += "-SQCIF";
  283.  
  284.   if (qcifMPI)
  285.     ret += "-QCIF";
  286.  
  287.   if (cifMPI)
  288.     ret += "-CIF";
  289.  
  290.   if (cif4MPI)
  291.     ret += "-CIF4";
  292.  
  293.   if (cif16MPI)
  294.     ret += "-CIF16";
  295.  
  296.   return ret;
  297. }
  298.  
  299.  
  300. unsigned H323_H263Capability::GetSubType() const
  301. {
  302.   return H245_VideoCapability::e_h263VideoCapability;
  303. }
  304.  
  305.  
  306. BOOL H323_H263Capability::OnSendingPDU(H245_VideoCapability & cap) const
  307. {
  308.   cap.SetTag(H245_VideoCapability::e_h263VideoCapability);
  309.  
  310.   H245_H263VideoCapability & h263 = cap;
  311.   if (sqcifMPI > 0) {
  312.     h263.IncludeOptionalField(H245_H263VideoCapability::e_sqcifMPI);
  313.     h263.m_sqcifMPI = sqcifMPI;
  314.   }
  315.   if (qcifMPI > 0) {
  316.     h263.IncludeOptionalField(H245_H263VideoCapability::e_qcifMPI);
  317.     h263.m_qcifMPI = qcifMPI;
  318.   }
  319.   if (cifMPI > 0) {
  320.     h263.IncludeOptionalField(H245_H263VideoCapability::e_cifMPI);
  321.     h263.m_cifMPI = cifMPI;
  322.   }
  323.   if (cif4MPI > 0) {
  324.     h263.IncludeOptionalField(H245_H263VideoCapability::e_cif4MPI);
  325.     h263.m_cif4MPI = cif4MPI;
  326.   }
  327.   if (cif16MPI > 0) {
  328.     h263.IncludeOptionalField(H245_H263VideoCapability::e_cif16MPI);
  329.     h263.m_cif16MPI = cif16MPI;
  330.   }
  331.   h263.m_temporalSpatialTradeOffCapability = temporalSpatialTradeOff;
  332.   h263.m_maxBitRate = maxBitRate;
  333.   if (sqcifMPI < 0) {
  334.     h263.IncludeOptionalField(H245_H263VideoCapability::e_slowSqcifMPI);
  335.     h263.m_slowSqcifMPI = -sqcifMPI;
  336.   }
  337.   if (qcifMPI < 0) {
  338.     h263.IncludeOptionalField(H245_H263VideoCapability::e_slowQcifMPI);
  339.     h263.m_slowQcifMPI = -qcifMPI;
  340.   }
  341.   if (cifMPI < 0) {
  342.     h263.IncludeOptionalField(H245_H263VideoCapability::e_slowCifMPI);
  343.     h263.m_slowCifMPI = -cifMPI;
  344.   }
  345.   if (cif4MPI < 0) {
  346.     h263.IncludeOptionalField(H245_H263VideoCapability::e_slowCif4MPI);
  347.     h263.m_slowCif4MPI = -cif4MPI;
  348.   }
  349.   if (cif16MPI < 0) {
  350.     h263.IncludeOptionalField(H245_H263VideoCapability::e_slowCif16MPI);
  351.     h263.m_slowCif16MPI = -cif16MPI;
  352.   }
  353.  
  354.   return TRUE;
  355. }
  356.  
  357.  
  358. BOOL H323_H263Capability::OnSendingPDU(H245_VideoMode & pdu) const
  359. {
  360.   pdu.SetTag(H245_VideoMode::e_h263VideoMode);
  361.   H245_H263VideoMode & mode = pdu;
  362.   mode.m_resolution.SetTag(cif16MPI ? H245_H263VideoMode_resolution::e_cif16
  363.               :(cif4MPI ? H245_H263VideoMode_resolution::e_cif4
  364.                :(cifMPI ? H245_H263VideoMode_resolution::e_cif
  365.                 :(qcifMPI ? H245_H263VideoMode_resolution::e_qcif
  366.                  : H245_H263VideoMode_resolution::e_sqcif))));
  367.   mode.m_bitRate = maxBitRate;
  368.   mode.m_unrestrictedVector = unrestrictedVector;
  369.   mode.m_arithmeticCoding = arithmeticCoding;
  370.   mode.m_advancedPrediction = advancedPrediction;
  371.   mode.m_pbFrames = pbFrames;
  372.   mode.m_errorCompensation = errorCompensation;
  373.  
  374.   return TRUE;
  375. }
  376.  
  377.  
  378. BOOL H323_H263Capability::OnReceivedPDU(const H245_VideoCapability & cap)
  379. {
  380.   if (cap.GetTag() != H245_VideoCapability::e_h263VideoCapability)
  381.     return FALSE;
  382.  
  383.   const H245_H263VideoCapability & h263 = cap;
  384.   if (h263.HasOptionalField(H245_H263VideoCapability::e_sqcifMPI))
  385.     sqcifMPI = h263.m_sqcifMPI;
  386.   else if (h263.HasOptionalField(H245_H263VideoCapability::e_slowSqcifMPI))
  387.     sqcifMPI = -(int)h263.m_slowSqcifMPI;
  388.   else
  389.     sqcifMPI = 0;
  390.   if (h263.HasOptionalField(H245_H263VideoCapability::e_qcifMPI))
  391.     qcifMPI = h263.m_qcifMPI;
  392.   else if (h263.HasOptionalField(H245_H263VideoCapability::e_slowQcifMPI))
  393.     qcifMPI = -(int)h263.m_slowQcifMPI;
  394.   else
  395.     qcifMPI = 0;
  396.   if (h263.HasOptionalField(H245_H263VideoCapability::e_cifMPI))
  397.     cifMPI = h263.m_cifMPI;
  398.   else if (h263.HasOptionalField(H245_H263VideoCapability::e_slowCifMPI))
  399.     cifMPI = -(int)h263.m_slowCifMPI;
  400.   else
  401.     cifMPI = 0;
  402.   if (h263.HasOptionalField(H245_H263VideoCapability::e_cif4MPI))
  403.     cif4MPI = h263.m_cif4MPI;
  404.   else if (h263.HasOptionalField(H245_H263VideoCapability::e_slowCif4MPI))
  405.     cif4MPI = -(int)h263.m_slowCif4MPI;
  406.   else
  407.     cif4MPI = 0;
  408.   if (h263.HasOptionalField(H245_H263VideoCapability::e_cif16MPI))
  409.     cif16MPI = h263.m_cif16MPI;
  410.   else if (h263.HasOptionalField(H245_H263VideoCapability::e_slowCif16MPI))
  411.     cif16MPI = -(int)h263.m_slowCif16MPI;
  412.   else
  413.     cif16MPI = 0;
  414.   maxBitRate = h263.m_maxBitRate;
  415.   unrestrictedVector = h263.m_unrestrictedVector;
  416.   arithmeticCoding = h263.m_arithmeticCoding;
  417.   advancedPrediction = h263.m_advancedPrediction;
  418.   pbFrames = h263.m_pbFrames;
  419.   temporalSpatialTradeOff = h263.m_temporalSpatialTradeOffCapability;
  420.   hrd_B = h263.m_hrd_B;
  421.   bppMaxKb = h263.m_bppMaxKb;
  422.   errorCompensation = h263.m_errorCompensation;
  423.  
  424.   return TRUE;
  425. }
  426.  
  427.  
  428. H323Codec * H323_H263Capability::CreateCodec(H323Codec::Direction direction) const
  429. {     
  430.   return new H323_H263Codec(direction, sqcifMPI, qcifMPI, cifMPI, cif4MPI, cif16MPI, maxBitRate, videoFrameRate);
  431. }
  432.  
  433. //////////////////////////////////////////////////////////////////////////////
  434.  
  435.  
  436. H323_H263Codec::H323_H263Codec(Direction dir,
  437.                    unsigned _sqcifMPI,
  438.                    unsigned _qcifMPI,
  439.                    unsigned _cifMPI,
  440.                    unsigned _cif4MPI,
  441.                    unsigned _cif16MPI,
  442.                    unsigned _maxBitRate,
  443.                    unsigned _videoFrameRate)
  444.   : H323VideoCodec(H263_MediaFormat, dir)
  445. {
  446.   PTRACE(3, "H263\t" << (dir == Encoder ? "En" : "De") 
  447.      << "coder created. Data rate=" << _maxBitRate
  448.      << " Frame rate=" << _videoFrameRate);
  449.  
  450.  
  451.   bitRateHighLimit = _maxBitRate;
  452.   if (bitRateHighLimit == 0) {
  453.     PTRACE(3, "H263\tData Rate is set to 1000 Kb/sec, as supplied value (0) is invalid");
  454.     bitRateHighLimit = 1000 * 1024;
  455.   }
  456.   
  457.   framesPerSec = _videoFrameRate;
  458.   if (framesPerSec == 0) {
  459.     PTRACE(3, "H263\tFrame Rate is set to 25 frames/sec, as supplied value (0) is invalid");
  460.     framesPerSec = 25;
  461.   }
  462.  
  463.   int shifts = -1;
  464.   if (_sqcifMPI) { 
  465.     shifts = 0;     PTRACE(3, "H263\t" << (dir == Encoder ? "En" : "De") << "coder for _sqcifMPI ");
  466.   }
  467.   if (_qcifMPI) {
  468.     shifts = 1;  PTRACE(3, "H263\t" << (dir == Encoder ? "En" : "De") << "coder for _qcifMPI"); 
  469.   }
  470.   if (_cifMPI) { 
  471.     shifts = 2; PTRACE(3, "H263\t" << (dir == Encoder ? "En" : "De") << "coder for _cifMPI");
  472.   }
  473.   if (_cif4MPI) {
  474.     shifts = 3; PTRACE(3, "H263\t" << (dir == Encoder ? "En" : "De") << "coder for _cif4MPI");
  475.   }
  476.   if (_cif16MPI) {
  477.     shifts = 4; PTRACE(3, "H263\t" << (dir == Encoder ? "En" : "De") << "coder for _cif16MPI");
  478.   }
  479.  
  480.   if (shifts < 0) {
  481.     PTRACE(1, "H263\tERROR in definition of h263 size");
  482.     return;
  483.   }
  484.  
  485.   PTRACE(3, "H263\t" << (dir == Encoder ? "En" : "De") << "coder created." 
  486.      << "for a size of " << (88 << shifts) << "x" << (72 << shifts));
  487.   
  488.   Resize(88 << shifts , 72 << shifts); //Fill picture structure, open codec.
  489.   frameNum = 0;
  490.  
  491.   InitialiseCodec();
  492. }
  493.  
  494.  
  495. H323_H263Codec::~H323_H263Codec()
  496. {
  497.   PWaitAndSignal mutex1(videoHandlerActive);
  498.  
  499.   CloseCodec();
  500.  
  501.   if (videoDecoder) {
  502.     delete videoDecoder;
  503.     videoDecoder = NULL;
  504.   }
  505.  
  506.   if (videoEncoder){
  507.     delete videoEncoder;
  508.     videoEncoder = NULL;
  509.   }
  510. }
  511.  
  512. void H323_H263Codec::InitialiseCodec()
  513. {
  514.    // no video decoder until we receive a packet
  515.    videoDecoder = NULL;
  516.  
  517.    // no video encoder until we receive a packet
  518.    videoEncoder = NULL;
  519. }
  520.  
  521. void H323_H263Codec::CloseCodec()
  522. {
  523.   PTRACE(6, "H263\tClose h263 video " <<(direction == Encoder ? "En" : "De") << "coder");
  524. }
  525.  
  526.  
  527.  
  528.  
  529. /* Notes:
  530. Quality was primarily for NetMeeting?
  531. fillLevel simply set the greyscale of the background
  532. */
  533.  
  534.  
  535. //This function grabs, displays, and compresses a video frame into
  536. //into H263 packets.
  537. //Get another frame if all packets of previous frame have been sent.
  538. //Get next packet on list and send that one.
  539. //Render the current frame if all of its packets have been sent.
  540. BOOL H323_H263Codec::Read(BYTE * buffer,
  541.                           unsigned & length,
  542.                           RTP_DataFrame & frame)
  543. {
  544.   PWaitAndSignal mutex1(videoHandlerActive);
  545.   PTRACE(6,"H263\tAcquire next packet from h263 encoder.\n");
  546.  
  547.   if (videoEncoder == NULL) {
  548.       videoEncoder = new H263Encoder(videoQuality, fillLevel);
  549.   }
  550.  
  551.   if (rawDataChannel == NULL) {
  552.     length = 0;
  553.     PTRACE(1,"H263\tNo channel to connect to video grabber, close down video transmission thread.");
  554.     return FALSE;
  555.   }
  556.  
  557.   if (!rawDataChannel->IsOpen()) {
  558.      PTRACE(1,"H263\tVideo grabber is not initialised, close down video transmission thread.");
  559.      length = 0;
  560.      return FALSE;
  561.   }
  562.  
  563.   frameWidth  = ((PVideoChannel *)rawDataChannel)->GetGrabWidth();
  564.   frameHeight = ((PVideoChannel *)rawDataChannel)->GetGrabHeight();
  565.   PTRACE(6, "H263\tVideo grab size is " << frameWidth << "x" << frameHeight);
  566.  
  567.   if (frameWidth == 0) {
  568.     PTRACE(1,"H263\tVideo grab width is 0 x 0, close down video transmission thread.");
  569.     length=0;
  570.     return FALSE;
  571.   }
  572.  
  573.   videoEncoder->SetSize(frameWidth, frameHeight);
  574.  
  575.   PINDEX bytesInFrame = 0;
  576.   BOOL ok = TRUE;
  577.  
  578. #define NUMAVG 8
  579.  
  580. #ifdef INC_ENCODE
  581.   if (!videoEncoder->MoreToIncEncode()) { // get a new frame
  582. #else
  583.   if (!videoEncoder->PacketsOutStanding()) { // }get a new frame
  584. #endif
  585.     if (0 == frameNum) { // frame 0 means no frame has been sent yet
  586.       frameStartTime = PTimer::Tick();
  587.     }
  588.     else {
  589.       int frameTimeMs, avgFrameTimeMs, adjFrameTimeMs, avgAdjFrameTimeMs, avgFrameBytes;
  590.       PTimeInterval currentTime;
  591.  
  592.       currentTime = PTimer::Tick();
  593.       frameTimeMs = (int)(currentTime - frameStartTime).GetMilliSeconds();
  594.       adjFrameTimeMs = frameTimeMs - (int)grabInterval.GetMilliSeconds(); // subtract time possibly blocked in grabbing
  595.       frameStartTime = currentTime;
  596.  
  597.       sumFrameTimeMs += frameTimeMs;
  598.       avgFrameTimeMs = sumFrameTimeMs / NUMAVG;
  599.       sumFrameTimeMs -= avgFrameTimeMs;
  600.       sumAdjFrameTimeMs += adjFrameTimeMs;
  601.       avgAdjFrameTimeMs = sumAdjFrameTimeMs / NUMAVG;
  602.       sumAdjFrameTimeMs -= avgAdjFrameTimeMs;
  603.       sumFrameBytes += frameBytes;
  604.       avgFrameBytes = sumFrameBytes / NUMAVG;
  605.       sumFrameBytes -= avgFrameBytes;
  606.  
  607.       //PTRACE(3,"H263\tframeNum                             grabInterval: "
  608.       //  << frameNum << " " << grabInterval.GetMilliSeconds());
  609.       //PTRACE(3,"H263\tframeNum    frameBits       frameTimeMs       Bps: "
  610.       //  << frameNum << " " << (frameBytes*8) << " " << frameTimeMs
  611.       //  << " " << frameBytes*8*1000/frameTimeMs);
  612.       //PTRACE(3,"H263\tframeNum avgFrameBits    avgFrameTimeMs    avgBps: "
  613.       //  << frameNum << " " << (avgFrameBytes*8) << " " << avgFrameTimeMs
  614.       //  << " " << avgFrameBytes*8*1000/avgFrameTimeMs);
  615.       //PTRACE(3,"H263\tframeNum avgFrameBits avgAdjFrameTimeMs avgAdjBps: "
  616.       //  << frameNum << " " << (avgFrameBytes*8) << " " << avgAdjFrameTimeMs
  617.       //  << " " << avgFrameBytes*8*1000/avgAdjFrameTimeMs);
  618.  
  619.       if (frameNum > NUMAVG) { // do quality adjustment after first NUMAVG frames
  620.         if (0 != targetFrameTimeMs && (videoBitRateControlModes & DynamicVideoQuality)) {
  621.           int error; // error signal
  622.           int aerror;
  623.           int act; // action signal
  624.           int newQuality;
  625.           int avgFrameBitRate;
  626.           int targetFrameBits;
  627.  
  628.           // keep track of average frame size and
  629.           // adjust encoder quality to get targetFrameBits bits per frame
  630.       if (avgAdjFrameTimeMs)
  631.         avgFrameBitRate = avgFrameBytes*8*1000 / avgAdjFrameTimeMs; // bits per second
  632.       else
  633.         avgFrameBitRate = avgFrameBytes*8*1000;
  634.  
  635.           targetFrameBits = avgFrameBitRate * targetFrameTimeMs / 1000;
  636.           error = (frameBytes*8) - targetFrameBits; // error signal
  637.           aerror = PABS(error);
  638.  
  639.           act = 0;
  640.           if (aerror > (targetFrameBits/8)) {
  641.             if (aerror > (targetFrameBits/4)) {
  642.               if (aerror > (targetFrameBits/2)) {
  643.                 act = error>0 ? 2 : -4;
  644.               }
  645.               else {
  646.                 act = error>0 ? 1 : -2;
  647.               }
  648.             }
  649.             else {
  650.               act = error>0 ? 1 : -1;
  651.             }
  652.           }
  653.           newQuality = videoQuality + act;
  654.           newQuality = PMIN(PMAX(newQuality, videoQMin), videoQMax);
  655.           //PTRACE(3,"H263\tframeNum targetFrameBits frameBits videoQuality newQuality: "
  656.           //  << frameNum << " " << targetFrameBits << " " << (frameBytes*8) << " "
  657.           //  << videoQuality << " "  << newQuality);
  658.           videoQuality = newQuality;
  659.  
  660.           videoEncoder->SetQualityLevel(videoQuality);
  661.  
  662.           //PTRACE(3,"H263\tframeNum     avgFrameBitRate     bitRateHighLimit: "
  663.           //  << frameNum << " " << avgFrameBitRate << " " << bitRateHighLimit);
  664.         }
  665.       }
  666.     }
  667.  
  668.     //NO data is waiting to be read. Go and get some with the read call.
  669.     PTRACE(3,"H263\tRead frame from the video source.");
  670.     PTimeInterval grabStartTime = PTimer::Tick();
  671.     if (rawDataChannel->Read(videoEncoder->GetFramePtr(), bytesInFrame)) {
  672.       PTRACE(3,"H263\tSuccess. Read frame from the video source in "
  673.          << (PTimer::Tick() - grabStartTime).GetMilliSeconds() << " ms.");
  674.  
  675.       if (frameNum == 0) {
  676.     memset(videoEncoder->GetFramePtr(), 64, (frameWidth * frameHeight * 3) >> 1);     
  677.       }
  678.  
  679.       packetNum = 0; // reset packet counter
  680.       
  681.       // If there is a Renderer attached, display the grabbed video.
  682.       if (((PVideoChannel *)rawDataChannel)->IsRenderOpen()) {
  683.     ok = RenderFrame(); //use data from grab process.
  684.     }
  685.       
  686. #ifdef INC_ENCODE
  687.       videoEncoder->PreProcessOneFrame(); //Prepare to generate H263 packets
  688. #else
  689.       videoEncoder->ProcessOneFrame(); //Generate H263 packets
  690. #endif
  691.       frameNum++;
  692.     } else {
  693.       PTRACE(1,"H263\tFailed to read data from video grabber, close down video transmission thread.");
  694.       return FALSE;   //Read failed, return false.
  695.     }
  696.     grabInterval = PTimer::Tick() - grabStartTime;
  697.  
  698.     /////////////////////////////////////////////////////////////////
  699.     /// THIS VALUE MUST BE CALCULATED AND NOT JUST SET TO 29.97Hz!!!!
  700.     /////////////////////////////////////////////////////////////////
  701.     timestampDelta = 3003;
  702.     frameBytes = 0;
  703.  
  704.   }
  705.  
  706. #ifdef INC_ENCODE
  707.   videoEncoder->IncEncodeAndGetPacket(buffer,length); //encode & get next packet
  708.   frame.SetMarker(!videoEncoder->MoreToIncEncode());
  709. #else
  710.   videoEncoder->ReadOnePacket(buffer,length); //get next packet on list
  711.   frame.SetMarker(!videoEncoder->PacketsOutStanding());
  712. #endif
  713.   packetNum++;
  714.  
  715.   // Monitor and report bandwidth usage.
  716.   // If controlling bandwidth, limit the video bandwidth to
  717.   // bitRateHighLimit by introducing a variable delay between packets.
  718.   PTimeInterval currentTime;
  719.   if (0 != bitRateHighLimit &&
  720.       (videoBitRateControlModes & AdaptivePacketDelay)) {
  721.     PTimeInterval waitBeforeSending;
  722.  
  723.     if (newTime != 0) { // calculate delay and wait
  724.       currentTime = PTimer::Tick();
  725.       waitBeforeSending = newTime - currentTime;
  726.       if (waitBeforeSending > 0) PThread::Current()->Sleep(waitBeforeSending);
  727.       // report bit rate & control error for previous packet
  728.       currentTime = PTimer::Tick(); //re-acquire current time after wait
  729.       //PTRACE(3, "H263\tBitRateControl Packet(" << oldPacketNum
  730.       //  << ") Bits: " << oldLength*8
  731.       //  << " Interval: " << (currentTime - oldTime).GetMilliSeconds()
  732.       //  << " Rate: " << oldLength*8000/(currentTime - oldTime).GetMilliSeconds()
  733.       //  << " Error: " << (currentTime - newTime).GetMilliSeconds()
  734.       //  << " Slept: " << waitBeforeSending.GetMilliSeconds());
  735.     }
  736.     currentTime = PTimer::Tick(); // re-acquire current time due to possible PTRACE delay
  737.     // ms = (bytes * 8) / (bps / 1000)
  738.     if (bitRateHighLimit/1000)
  739.       newTime = currentTime + length*8/(bitRateHighLimit/1000);
  740.     else
  741.       newTime = currentTime + length*8;
  742.   }
  743.   else {
  744.     // monitor & report bit rate
  745.     if (oldTime != 0) { // report bit rate for previous packet
  746.       PTimeInterval currentTime = PTimer::Tick();
  747.       //PTRACE(3, "H263\tBitRateReport  Packet(" << oldPacketNum
  748.       //  << ") Bits: " << oldLength*8
  749.       //  << " Interval: " << (currentTime - oldTime).GetMilliSeconds()
  750.       //  << " Rate: " << oldLength*8000/(currentTime - oldTime).GetMilliSeconds());
  751.     }
  752.     currentTime = PTimer::Tick(); // re-acquire current time due to possible PTRACE delay
  753.   }
  754.   //oldPacketNum = packetNum; // used only for PTRACE
  755.   oldTime = currentTime;
  756.   oldLength = length;
  757.   frameBytes += length; // count current frame bytes
  758.   return ok;
  759. }
  760.  
  761.  
  762.  
  763.  
  764. BOOL H323_H263Codec::Write(const BYTE * buffer,
  765.                            unsigned length,
  766.                            const RTP_DataFrame & frame,
  767.                            unsigned & written)
  768. {
  769.   PWaitAndSignal mutex1(videoHandlerActive);
  770.  
  771.   if (rawDataChannel == NULL) {
  772.     //Some other task has killed our videohandler. Exit.
  773.     return FALSE;
  774.   }
  775.  
  776.   BOOL lostPreviousPacket = FALSE;
  777.   if ((++lastSequenceNumber) != frame.GetSequenceNumber()) {
  778.     lostPreviousPacket = TRUE;
  779.     PTRACE(3,"H263\tDetected loss of one video packet. "
  780.       << lastSequenceNumber << " != "
  781.       << frame.GetSequenceNumber() << " Will recover.");
  782.     lastSequenceNumber = frame.GetSequenceNumber();
  783.     //    SendMiscCommand(H245_MiscellaneousCommand_type::e_lostPartialPicture);
  784.   }
  785.  
  786.   // always indicate we have written the entire packet
  787.   written = length;
  788.  
  789.   // H.263 header is usually at start of buffer
  790.   const unsigned char * header = buffer;
  791.   // adjust for any contributing source (see SSRC in RFC1889)
  792.   PINDEX cnt = frame.GetContribSrcCount();
  793.   if (cnt > 0) {
  794.     header += cnt * 4;
  795.     length -= cnt * 4;
  796.   }
  797.  
  798.   // determine video codec type
  799.   if (videoDecoder == NULL) {
  800. /*
  801.     if ((*header & 2) && !(*header & 1)) // check value of I field in header
  802.         AWM: Intra vs. Full?
  803. */
  804.       videoDecoder = new H263Decoder();
  805.       videoDecoder->marks(rvts);
  806.   }
  807.  
  808.   videoDecoder->mark(now);
  809.   BOOL ok = videoDecoder->decode(header, length, (char)lostPreviousPacket,
  810.       (char)frame.GetMarker(), frame.GetSequenceNumber());
  811.   if (!ok) {
  812.     PTRACE (3, "H263\t Could not decode frame, continuing in hope.");
  813.     return TRUE;
  814.   }
  815.   
  816.   // If the incoming video stream changes size, resize the rendering device.
  817.   ok = Resize(videoDecoder->width(), videoDecoder->height());
  818.  
  819.   if (ok && frame.GetMarker()) {
  820.     videoDecoder->sync();
  821.     ndblk = videoDecoder->ndblk();
  822.     ok = RenderFrame();
  823.     videoDecoder->resetndblk();
  824.   }
  825.  
  826.   return ok;
  827. }
  828.  
  829.  
  830.  
  831.  
  832. BOOL H323_H263Codec::Resize(int _width, int _height)
  833. {
  834.   if ((frameWidth == _width) && (frameHeight == _height)) 
  835.     return TRUE;
  836.  
  837.   PTRACE(6, "H263\t" << (direction == Encoder ? "En" : "De") << "coder resizing to "
  838.      << _width << "x" << _height << ".");
  839.  
  840.  
  841.   frameWidth = _width;
  842.   frameHeight = _height;
  843.  
  844.   return TRUE;
  845. }
  846.  
  847.  
  848. /* RenderFrame does two things:
  849.    a) Set size of the display frame. This call happens with every frame.
  850.      A very small overhead.
  851.    b) Display a frame.
  852. */
  853.  
  854. BOOL H323_H263Codec::RenderFrame(const void * buffer)
  855. {
  856.   if (rawDataChannel == NULL)
  857.     return TRUE;
  858.  
  859.   //Now display local image.
  860.   ((PVideoChannel *)rawDataChannel)->SetRenderFrameSize(frameWidth, frameHeight);
  861.  
  862.   if (buffer == NULL)
  863.     return TRUE;
  864.  
  865.   return rawDataChannel->Write(buffer, 0 /*unused parameter*/);
  866. }
  867.  
  868. /* AWM: Look-alike to H.261 implementation */
  869. BOOL H323_H263Codec::RenderFrame()
  870. {
  871.   void *srcData;
  872.   
  873.   if (direction == Encoder)
  874.     srcData = videoEncoder->GetFramePtr();
  875.   else
  876.     srcData = videoDecoder->GetFramePtr();
  877.  
  878.   return  RenderFrame(srcData);
  879. }
  880.  
  881.  
  882.  
  883.  
  884. void H323_H263Codec::SetTxQualityLevel(int qLevel)
  885. {
  886.   int qualityLevel = PMIN(14, PMAX(qLevel,3));
  887.  
  888.   int lowLimit = PMIN(10, qualityLevel - 2);
  889.   int highLimit = qualityLevel + 12;
  890.  
  891.   videoQuality = qLevel;
  892.   videoQMin = lowLimit;       
  893.   videoQMax = highLimit;
  894. }
  895.  
  896.  
  897. void H323_H263Codec::SetBackgroundFill(int idle)
  898. {
  899.     fillLevel = PMIN(99, PMAX(idle,1));
  900. }
  901.  
  902.  
  903. void H323_H263Codec::OnLostPartialPicture()
  904. {
  905.   PTRACE(3, "H263\tLost partial picture message ignored, not implemented");
  906. }
  907.  
  908.  
  909. void H323_H263Codec::OnLostPicture()
  910. {
  911.   PTRACE(3, "H263\tLost picture message ignored, not implemented");
  912. }
  913.  
  914.  
  915. //////////////////////////////////////////////////////////////////////
  916.  
  917. #endif // H323_VICH263
  918.  
  919.