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 / ffh263codec.cxx < prev    next >
C/C++ Source or Header  |  2003-08-07  |  31KB  |  1,061 lines

  1. /*
  2.  * ffh263codec.cxx
  3.  *
  4.  * Non standard implementation of h263+ based on ffmpeg. (or reported as avcodec)
  5.  *
  6.  * H.323 protocol handler
  7.  *
  8.  * Open H323 Library
  9.  * 
  10.  * Copyright (c) 1998-2000 Equivalence Pty. Ltd.
  11.  *
  12.  * The contents of this file are subject to the Mozilla Public License
  13.  * Version 1.0 (the "License"); you may not use this file except in
  14.  * compliance with the License. You may obtain a copy of the License at
  15.  * http://www.mozilla.org/MPL/
  16.  *
  17.  * Software distributed under the License is distributed on an "AS IS"
  18.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  19.  * the License for the specific language governing rights and limitations
  20.  * under the License.
  21.  *
  22.  * The Original Code is Open H323 Library. 
  23.  *
  24.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  25.  *
  26.  * Portions of this code were written with the financial assistance of 
  27.  *          AliceStreet (http://www.alicestreet.com) 
  28.  *
  29.  * Contributor(s): Guilhem Tardy (gtardy@marchnetworks.com)
  30.  *
  31.  * $Log: ffh263codec.cxx,v $
  32.  * Revision 1.5  2003/08/08 01:52:14  dereksmithies
  33.  * Make use of ffmpeg library work correctly on multi CPU boxes.
  34.  *
  35.  * Revision 1.4  2003/08/04 00:03:35  dereksmithies
  36.  * Reorganise test of H323_AVCODEC switch
  37.  *
  38.  * Revision 1.3  2003/07/31 05:08:24  dereksmithies
  39.  * Switch to manual packet fragment technique. Much more reliable, especially so on windows.
  40.  *
  41.  * Revision 1.2  2003/07/29 03:33:41  dereksmithies
  42.  * add bug fix which prevents random Crashes on windows.
  43.  *
  44.  * Revision 1.1  2003/07/24 05:22:18  dereksmithies
  45.  * Moved ffmpeg h263 support to this file, and designate as non standard.
  46.  *
  47.  * Revision 1.19  2003/06/14 05:54:23  rjongbloed
  48.  * Fixed MSVC warning.
  49.  * Fixed what seemed an obvious mistake using boolean or operator (||) instead
  50.  *   of the bitwise or operator (|).
  51.  *
  52.  * Revision 1.18  2003/06/12 00:24:32  dereksmithies
  53.  * Modify so QCIF-CIF behaviour similar to that for h261codec.cxx
  54.  *
  55.  * Revision 1.17  2003/06/10 01:37:25  dereksmithies
  56.  * Changes so it should not crash under windows/release mode
  57.  *
  58.  * Revision 1.16  2003/06/06 06:32:08  rjongbloed
  59.  * Fixed MSVC warning
  60.  *
  61.  * Revision 1.15  2003/06/06 05:18:54  dereksmithies
  62.  * Fix startup delay bug. Remove all large packets from the network. Improve reliability.
  63.  *
  64.  * Revision 1.14  2003/06/03 05:01:23  rjongbloed
  65.  * Fixed some trace logging (removed usage of cerr)
  66.  *
  67.  * Revision 1.13  2003/06/03 00:49:01  dereksmithies
  68.  * Fix divide by zero error, which happens on win95 & win98 machines.
  69.  *
  70.  * Revision 1.12  2003/06/02 07:56:56  rjongbloed
  71.  * Fixed media format passed to ancestor codec class
  72.  *
  73.  * Revision 1.11  2003/05/27 04:20:59  dereksmithies
  74.  * Fix so that codec resizes correctly after capability exchange
  75.  * No longer crashes if one endpoint is CIF, other is QCIF.
  76.  *
  77.  * Revision 1.10  2003/05/16 04:42:24  rjongbloed
  78.  * Removed extraneous code, and other cosmetic changes.
  79.  * Fixed compare function for capability.
  80.  * Extra trace logging.
  81.  *
  82.  * Revision 1.9  2003/05/15 01:35:27  dereksmithies
  83.  * Frame length fix
  84.  *
  85.  * Revision 1.8  2003/05/14 13:51:51  rjongbloed
  86.  * Removed hack of using special payload type for H.263 for a method which
  87.  *   would be less prone to failure in the future.
  88.  * Removed static "initialisation" function as this should be done
  89.  *   internally and not in the application.
  90.  * Changed media format to be straight H.263 and not OpalH.263
  91.  * Moved Win32 stderr output in ffmpeg AVCODEC interception from
  92.  *   application to library.
  93.  * Fixed some warnings.
  94.  *
  95.  * Revision 1.7  2003/05/14 03:07:17  rjongbloed
  96.  * Made sure video buffer is large enough
  97.  *
  98.  * Revision 1.6  2003/05/05 11:59:25  robertj
  99.  * Changed to use autoconf style selection of options and subsystems.
  100.  *
  101.  * Revision 1.5  2003/05/02 04:21:30  craigs
  102.  * Added lots of extra H.263 support
  103.  *
  104.  * Revision 1.4  2003/04/21 21:50:22  dereks
  105.  * Implement suggestion from Guilhem Tardy. Many thanks.
  106.  *
  107.  * Revision 1.3  2003/04/16 04:26:57  dereks
  108.  * Initial release of h263 codec, which utilises the ffmpeg library.
  109.  * Thanks to Guilhem Tardy, and to AliceStreet.
  110.  *
  111.  * Revision 1.2  2002/08/05 10:03:47  robertj
  112.  * Cosmetic changes to normalise the usage of pragma interface/implementation.
  113.  *
  114.  * Revision 1.1  2002/05/19 22:31:12  dereks
  115.  * Initial release of stub file for h263 codec. Thanks Guilhem Tardy.
  116.  */
  117.  
  118. /*
  119.  *  Initial release notes from Guilhem Tardy::
  120.  *
  121.  * Added support for video capabilities & codec, still needs the actual codec itself!
  122.  * The code for varying bit rate is copied from h261codec.cxx,
  123.  * until it is moved to a separate file common to both video codecs.
  124.  *
  125.  */
  126. #include <ptlib.h>
  127. #include "h263codec.h"
  128.  
  129. #ifdef __GNUC__
  130. #pragma implementation "ffh263codec.h"
  131. #endif
  132.  
  133. #include "ffh263codec.h"
  134.  
  135. #if H323_AVCODEC
  136.  
  137. #include "h245.h"
  138. #include "rtp.h"
  139.  
  140. #define  MSVC_OPENH323 1
  141.  
  142. extern "C" {
  143. #include <avcodec.h>
  144. };
  145.  
  146.  
  147. //#if defined(_MSC_VER)
  148. //#pragma comment(lib, H323_FFMPEG_LIBRARY)
  149. //#endif
  150.  
  151. //////////////////////////////////////////////////////////////////////////////
  152. static void h263_ffmpeg_printon(char * str);
  153. static void h263_ffmpeg_printon(char * str)
  154. {
  155.   PTRACE(6, "FFMPEG\t" << str);
  156.   strlen(str);   /*Stop any compiler warning about unused variable*/
  157. }
  158.  
  159. //////////////////////////////////////////////////
  160.  
  161. class FfmpgLink : public PDynaLink
  162. {
  163.   PCLASSINFO(FfmpgLink, PDynaLink)
  164.     
  165.  public:
  166.   FfmpgLink();
  167.   ~FfmpgLink();
  168.  
  169.   AVCodec *AvcodecFindDecoderByName(const char *name);
  170.   AVCodec *AvcodecFindEncoderByName(const char *name);
  171.   AVCodecContext *AvcodecAllocContext(void);
  172.  
  173.   AVFrame *AvcodecAllocFrame(void);
  174.  
  175.   BOOL IsLoaded();
  176.  
  177.   int AvcodecClose(AVCodecContext *ctx);
  178.   int AvcodecDecodeVideo(AVCodecContext *ctx, AVFrame *picture, int *got_picture_ptr, BYTE *buf, int buf_size);
  179.   int AvcodecEncodeVideo(AVCodecContext *ctx, BYTE *buf, int buf_size, const AVFrame *pict);
  180.   int AvcodecOpen(AVCodecContext *ctx, AVCodec *codec);
  181.  
  182.   void AFavcodecRegisterAll(void);
  183.   void AvcodecGetContextDefaults(AVCodecContext *s);
  184.   void AvcodecInit(void);
  185.   void AvcodecSetPrintFn(void (*print_fn)(char *));
  186.  
  187. protected:
  188.   PMutex processLock;
  189.  
  190.   BOOL isLoadedOK;
  191.  
  192.   AVCodec *(*Favcodec_find_decoder_by_name)(const char *name);
  193.   AVCodec *(*Favcodec_find_encoder_by_name)(const char *name);
  194.   AVCodecContext *(*Favcodec_alloc_context)(void);
  195.   AVFrame *(*Favcodec_alloc_frame)(void);
  196.   int (*Favcodec_close)(AVCodecContext *ctx);
  197.   int (*Favcodec_decode_video)(AVCodecContext *ctx, AVFrame *picture, int *got_picture_ptr, BYTE *buf, int buf_size);
  198.   int (*Favcodec_encode_video)(AVCodecContext *ctx, BYTE *buf, int buf_size, const AVFrame *pict);
  199.   int (*Favcodec_open)(AVCodecContext *ctx, AVCodec *codec);
  200.  
  201.   void (*Favcodec_get_context_defaults)(AVCodecContext *s);
  202.   void (*Favcodec_init)(void);
  203.   void (*Favcodec_set_print_fn)(void (*print_fn)(char *));
  204.   void (*Favcodec_register_all)(void);
  205.      
  206.  
  207. };           
  208.  
  209. //////////////////////////////////////////////////////////////////////////////
  210.  
  211. #define new PNEW
  212.  
  213. FfmpgLink::FfmpgLink()
  214. {
  215.   isLoadedOK = FALSE;
  216.   PDynaLink::Open("libavcodec");
  217.  
  218.   if (!PDynaLink::IsLoaded())
  219.     PDynaLink::Open("libavcodec.so");
  220.   
  221.   if (!PDynaLink::IsLoaded())
  222.     PDynaLink::Open("avcodec.so");
  223.   
  224.   if (!PDynaLink::IsLoaded())
  225.     PDynaLink::Open("avcodec");
  226.   
  227.   if (!PDynaLink::IsLoaded()) {
  228.     cerr << "FFH263 Dynamic Failed to load libavcodec non standard" << endl;
  229.     cerr << "FFH263 Dynamic will show up in list of codecs, but will not operate correctly."<< endl;
  230. #if defined(P_LINUX) || defined(P_FREEBSD) || defined(P_OPENBSD) || defined(P_NETBSD) 
  231.     cerr << "put libavcodec.so in /usr/local/lib, and then rerun program" << endl;
  232. #else
  233.     cerr << "put libavcodec.dll in openh323\\lib directory, or in a standard location, then rerun program" << endl;
  234. #endif
  235.     return;
  236.   }
  237.  
  238.   if (!GetFunction("avcodec_init",                  (Function &)Favcodec_init)) {
  239.     cerr <<  "Failed to load avcodec_int" << endl;
  240.     return;
  241.   }
  242.  
  243.   if (!GetFunction("avcodec_register_all",          (Function &)Favcodec_register_all)) {
  244.     cerr <<  "Failed to load avcodec_register_all" << endl;
  245.     return;
  246.   }
  247.  
  248.   if (!GetFunction("avcodec_find_encoder_by_name",   (Function &)Favcodec_find_encoder_by_name)) {
  249.     cerr <<  "Failed to load avcodec_find_encoder_by_name" << endl;
  250.     return;
  251.   }
  252.  
  253.   if (!GetFunction("avcodec_find_decoder_by_name",   (Function &)Favcodec_find_decoder_by_name)) {
  254.     cerr <<  "Failed to load avcodec_find_decoder_by_name" << endl;
  255.     return;
  256.   }
  257.  
  258.   if (!GetFunction("avcodec_alloc_context",         (Function &)Favcodec_alloc_context)) {
  259.     cerr <<  "Failed to load avcodec_alloc_context" << endl;
  260.     return;
  261.   }
  262.  
  263.   if (!GetFunction("avcodec_alloc_frame",           (Function &)Favcodec_alloc_frame)) {
  264.     cerr <<  "Failed to load avcodec_alloc_frame" << endl;
  265.     return;
  266.   }
  267.  
  268.   if (!GetFunction("avcodec_get_context_defaults",  (Function &)Favcodec_get_context_defaults)) {
  269.     cerr <<  "Failed to load  avcodec_get_context_defaults" << endl;
  270.     return;
  271.   }
  272.  
  273.   if (!GetFunction("avcodec_open",                  (Function &)Favcodec_open)) {
  274.     cerr <<  "Failed to load avcodec_open" << endl;
  275.     return;
  276.   }
  277.  
  278.   if (!GetFunction("avcodec_close",                 (Function &)Favcodec_close)) {
  279.     cerr <<  "Failed to load avcodec_close" << endl;
  280.     return;
  281.   }
  282.  
  283.   if (!GetFunction("avcodec_encode_video",          (Function &)Favcodec_encode_video)) {
  284.     cerr <<  "Failed to load avcodec_encode_video" << endl;
  285.     return;
  286.   }
  287.  
  288.   if (!GetFunction("avcodec_decode_video",          (Function &)Favcodec_decode_video)) {
  289.     cerr <<  "Failed to load avcodec_decode_video" << endl;
  290.     return;
  291.   }
  292.  
  293.   if (!GetFunction("avcodec_set_print_fn",          (Function &)Favcodec_set_print_fn)) {
  294.     cerr <<  "Failed to load avcodec_set_print_fn" << endl;
  295.     return;
  296.   }
  297.    
  298.   /* must be called before using avcodec lib */
  299.   Favcodec_init();
  300.   
  301.   Favcodec_register_all();
  302.   
  303.   Favcodec_set_print_fn(h263_ffmpeg_printon);
  304.  
  305.   isLoadedOK = TRUE;
  306. }
  307.  
  308. FfmpgLink::~FfmpgLink()
  309. {
  310.   PDynaLink::Close();
  311. }
  312.  
  313. int FfmpgLink::AvcodecOpen(AVCodecContext *ctx, AVCodec *codec)
  314. {
  315.   PWaitAndSignal m(processLock);
  316.  
  317.   PTRACE(6, "Avcodec open for ctxt " << ::hex << ctx << " codec" << codec << ::dec);
  318.   int res = Favcodec_open(ctx, codec);
  319.   PTRACE(6, "Avcodec open result is " << res);
  320.  
  321.   return res;
  322. }
  323.  
  324. BOOL FfmpgLink::IsLoaded()
  325. {
  326.   PWaitAndSignal m(processLock);
  327.  
  328.   return isLoadedOK;
  329. }
  330.  
  331. AVCodec *FfmpgLink::AvcodecFindDecoderByName(const char *name)
  332. {
  333.   AVCodec *res = Favcodec_find_decoder_by_name(name);
  334.   PTRACE(6, "Found decoder " << *name << " at " << ::hex << res << ::dec);
  335.   return res;
  336. }
  337.  
  338. AVCodec *FfmpgLink::AvcodecFindEncoderByName(const char *name)
  339. {
  340.   AVCodec *res = Favcodec_find_encoder_by_name(name);
  341.   PTRACE(6, "Found encoder " << *name << " at " << ::hex << res << ::dec);
  342.   return res;
  343. }
  344.  
  345. AVCodecContext *FfmpgLink::AvcodecAllocContext(void)
  346. {
  347.   AVCodecContext *res = Favcodec_alloc_context();
  348.   PTRACE(6, "Allocated context at " << ::hex << res << ::dec);
  349.   return res;
  350. }
  351.  
  352. AVFrame *FfmpgLink::AvcodecAllocFrame(void)
  353. {
  354.   AVFrame *res = Favcodec_alloc_frame();
  355.   PTRACE(6, "Allocated frame at " << ::hex << res << ::dec);
  356.   return res;
  357. }
  358.  
  359. int FfmpgLink::AvcodecClose(AVCodecContext *ctx)
  360. {
  361.   PTRACE(6, "Now close context at " << ::hex << ctx << ::dec);
  362.   return Favcodec_close(ctx);
  363. }
  364.  
  365. int FfmpgLink::AvcodecDecodeVideo(AVCodecContext *ctx, AVFrame *picture, int *got_picture_ptr, BYTE *buf, int buf_size)
  366. {
  367.   PWaitAndSignal m(processLock);
  368.  
  369.   PTRACE(6, "Avcodec decode video at " << ::hex << ctx << " frame" << picture 
  370.      << " buf" << (int)buf << ::dec << "           got picture" << *got_picture_ptr 
  371.      << " buffer size is" << buf_size);
  372.   int res = Favcodec_decode_video(ctx, picture, got_picture_ptr, buf, buf_size);
  373.   PTRACE(6, "Avcodec decode video of " <<buf_size << " bytes.  result is " << res );
  374.  
  375.   return res;
  376. }
  377.  
  378. int FfmpgLink::AvcodecEncodeVideo(AVCodecContext *ctx, BYTE *buf, int buf_size, const AVFrame *pict)
  379. {
  380.   PWaitAndSignal m(processLock);
  381.  
  382.   PTRACE(6, "Avcodec encode video for ctxt " << ::hex << ctx << " picture" << pict 
  383.      << " buf" << (int)buf << ::dec << "          buffer size is" << buf_size);
  384.   int res = Favcodec_encode_video(ctx, buf, buf_size, pict);
  385.  
  386.   PTRACE(6, "Avcodec encode video into " << res << " bytes.");
  387.   return res;
  388. }
  389.  
  390. void FfmpgLink::AvcodecGetContextDefaults(AVCodecContext *s)
  391. {
  392.   PTRACE(6, "Avcodec open for ctxt " << ::hex << s << ::dec);
  393.   Favcodec_get_context_defaults(s);
  394. }
  395.  
  396. void FfmpgLink::AvcodecInit(void)
  397. {
  398.   Favcodec_init();
  399. }
  400.  
  401. void FfmpgLink::AvcodecSetPrintFn(void (*print_fn)(char *))
  402. {
  403.   Favcodec_set_print_fn(print_fn);
  404. }
  405.  
  406. void FfmpgLink::AFavcodecRegisterAll(void)
  407. {
  408.   Favcodec_register_all();
  409. }
  410.  
  411.  
  412.  
  413.  
  414.  
  415. FfmpgLink ff;
  416.  
  417.  
  418. static OpalMediaFormat const FFH263_MediaFormat("NonStandard.H.263",
  419.                                               OpalMediaFormat::DefaultVideoSessionID,
  420.                                               RTP_DataFrame::DynamicBase,
  421.                                               FALSE,  // No jitter for video
  422.                                               180000, // bits/sec
  423.                                               2000,   // Not sure of this value!
  424.                                               0,      // No intrinsic time per frame
  425.                                               OpalMediaFormat::VideoTimeUnits);
  426.  
  427.  
  428.  
  429. //////////////////////////////////////////////////////////////////////////////
  430.  
  431.  
  432.  
  433. H323_FFH263Capability::H323_FFH263Capability(unsigned _sqcifMPI,
  434.                          unsigned _qcifMPI,
  435.                          unsigned _cifMPI,
  436.                          unsigned _cif4MPI,
  437.                          unsigned _cif16MPI,
  438.                          unsigned _maxBitRate,
  439.                          unsigned _videoFrameRate)
  440.   :H323NonStandardVideoCapability("H.263 lookalike", (const BYTE *)"NonStandard.H.263", 4, 0, 4)
  441. {
  442.   sqcifMPI = _sqcifMPI;
  443.   qcifMPI = _qcifMPI;
  444.   cifMPI = _cifMPI;
  445.   cif4MPI = _cif4MPI;
  446.   cif16MPI = _cif16MPI;      
  447.  
  448.   maxBitRate = _maxBitRate;
  449.   videoFrameRate = _videoFrameRate;
  450. }
  451.  
  452.  
  453. PObject * H323_FFH263Capability::Clone() const
  454. {
  455.   return new H323_FFH263Capability(*this);
  456. }
  457.  
  458.  
  459. PString H323_FFH263Capability::GetFormatName() const
  460. {
  461.   PString ans = "NonStandard.H.263";
  462.  
  463.   if (qcifMPI > 0)
  464.     ans+= ".QCIF";
  465.   else
  466.     ans+= ".CIF";
  467.  
  468.   return ans;
  469. }
  470.  
  471.  
  472. unsigned H323_FFH263Capability::GetSubType() const
  473. {
  474.   return H245_VideoCapability::e_nonStandard;
  475. }
  476.  
  477. BOOL H323_FFH263Capability::OnSendingPDU(H245_VideoCapability & cap) const
  478. {
  479.   cap.SetTag(H245_VideoCapability::e_nonStandard);
  480.  
  481.   return TRUE;
  482. }
  483.  
  484. BOOL H323_FFH263Capability::OnSendingPDU(H245_VideoMode & pdu) const
  485. {
  486.   pdu.SetTag(H245_VideoMode::e_nonStandard);
  487.  
  488.   return TRUE;
  489. }
  490.  
  491.  
  492. BOOL H323_FFH263Capability::OnReceivedPDU(const H245_VideoCapability & cap)
  493. {
  494.   if (cap.GetTag() != H245_VideoCapability::e_nonStandard)
  495.     return FALSE;
  496.  
  497.   return TRUE;
  498. }
  499.  
  500.  
  501. H323Codec * H323_FFH263Capability::CreateCodec(H323Codec::Direction direction) const
  502. {     
  503.   return new H323_FFH263Codec(direction, sqcifMPI, qcifMPI, cifMPI, cif4MPI, cif16MPI, maxBitRate, videoFrameRate);
  504. }
  505.  
  506. //////////////////////////////////////////////////////////////////////////////
  507.  
  508. H323_FFH263Codec::H323_FFH263Codec(Direction dir,
  509.                    unsigned _sqcifMPI,
  510.                    unsigned _qcifMPI,
  511.                    unsigned _cifMPI,
  512.                    unsigned _cif4MPI,
  513.                    unsigned _cif16MPI,
  514.                    unsigned _maxBitRate,
  515.                    unsigned _videoFrameRate)
  516.   : H323VideoCodec(FFH263_MediaFormat, dir)
  517. {
  518.   PTRACE(3, "FFH263\t" << (dir == Encoder ? "En" : "De") 
  519.      << "coder created. Data rate=" << _maxBitRate
  520.      << " Frame rate=" << _videoFrameRate);
  521.  
  522.   bitsSent = 0;
  523.  
  524.   context = NULL;
  525.   picture = NULL;
  526.   
  527.   PTRACE(3, "FFH263\t" << (dir == Encoder ? "En" : "De") << "coder find"); 
  528.  
  529.   if (!ff.IsLoaded())
  530.      return;
  531.  
  532.   if (dir == Encoder){
  533.     codec = ff.AvcodecFindEncoderByName((char *)"h263p");
  534.   } else {
  535.     codec = ff.AvcodecFindDecoderByName((char *)"h263");
  536.   }
  537.  
  538.   if (codec == NULL) {   
  539.     PTRACE(1, "FFH263\tCodec not found for FFH263+ " << (dir == Encoder ? "En" : "De") << "coder");
  540.     cerr << "FFH263 Codec not found for FFH263+ " << (dir == Encoder ? "En" : "De") << "coder" << endl;
  541.     exit(0);
  542.   }
  543.  
  544.   bitRateHighLimit = _maxBitRate;
  545.   if (bitRateHighLimit == 0) {
  546.     PTRACE(3, "FFH263\tData Rate is set to 1000 Kb/sec, as supplied value (0) is invalid");
  547.     bitRateHighLimit = 1000 * 1024;
  548.   }
  549.   
  550.   framesPerSec = _videoFrameRate;
  551.   if (framesPerSec == 0) {
  552.     PTRACE(3, "FFH263\tFrame Rate is set to 25 frames/sec, as supplied value (0) is invalid");
  553.     framesPerSec = 25;
  554.   }
  555.  
  556.   int shifts = -1;
  557.   if (_sqcifMPI) { 
  558.     shifts = 0;     PTRACE(3, "FFH263\t" << (dir == Encoder ? "En" : "De") << "coder for _sqcifMPI ");
  559.   }
  560.   if (_qcifMPI) {
  561.     shifts = 1;  PTRACE(3, "FFH263\t" << (dir == Encoder ? "En" : "De") << "coder for _qcifMPI"); 
  562.   }
  563.   if (_cifMPI) { 
  564.     shifts = 2; PTRACE(3, "FFH263\t" << (dir == Encoder ? "En" : "De") << "coder for _cifMPI");
  565.   }
  566.   if (_cif4MPI) {
  567.     shifts = 3; PTRACE(3, "FFH263\t" << (dir == Encoder ? "En" : "De") << "coder for _cif4MPI");
  568.   }
  569.   if (_cif16MPI) {
  570.     shifts = 4; PTRACE(3, "FFH263\t" << (dir == Encoder ? "En" : "De") << "coder for _cif16MPI");
  571.   }
  572.  
  573.   if (shifts < 0) {
  574.     PTRACE(1, "FFH263\tERROR in definition of h263 size");
  575.     return;
  576.   }
  577.  
  578.   PTRACE(3, "FFH263\t" << (dir == Encoder ? "En" : "De") << "coder created." 
  579.      << "for a size of " << (88 << shifts) << "x" << (72 << shifts));
  580.   
  581.   Resize(88 << shifts , 72 << shifts); //Fill picture structure, open codec.
  582.   frameNum = 0;
  583. }
  584.  
  585.  
  586. H323_FFH263Codec::~H323_FFH263Codec()
  587. {
  588.   PWaitAndSignal mutex1(videoHandlerActive);
  589.  
  590.   CloseCodec();
  591. }
  592.  
  593. void H323_FFH263Codec::InitialiseCodec()
  594. {
  595.   if (!ff.IsLoaded())
  596.      return;
  597.  
  598.   context = ff.AvcodecAllocContext();
  599.   picture = ff.AvcodecAllocFrame();
  600.  
  601.   PTRACE(6, "FFH263\tCall avcodec_get_context_defaults");
  602.   ff.AvcodecGetContextDefaults(context);
  603.  
  604.   if (direction == Encoder) {
  605.     context->max_qdiff= 3; // max q difference between frames
  606.     context->rc_qsquish = 0; // limit by clipping
  607.     context->bit_rate = (bitRateHighLimit * 3) >> 2;
  608.     context->bit_rate_tolerance = bitRateHighLimit  << 3;
  609.     context->rc_min_rate = 0;
  610.     context->rc_max_rate = bitRateHighLimit;    /* resolution must be a multiple of two */
  611.  
  612.     context->qmin = 2;
  613.     PINDEX effRate = (frameWidth > 200) ? bitRateHighLimit / 2 : bitRateHighLimit;
  614.  
  615.     if (effRate > 0) {
  616.       context->qmax = 31;    
  617.     }
  618.  
  619.     if (effRate > 20000) 
  620.       context->qmax = 20;    
  621.  
  622.     if (effRate > 40000) {
  623.       context->qmax = 10;
  624.     }
  625.  
  626. #ifdef FRAME_RATE_BASE  
  627.     context->frame_rate = framesPerSec * FRAME_RATE_BASE;
  628. #else
  629.     context->frame_rate = framesPerSec * DEFAULT_FRAME_RATE_BASE;
  630. #endif
  631.  
  632.     context->rtp_mode = 0;
  633.   } else {    
  634.     //Prepare for decoding a video stream.
  635.     encFrameBuffer.SetSize(0);
  636.     currentFragment = 0;
  637.   }
  638.  
  639.   int size = frameWidth * frameHeight; 
  640.   picture->data[0] = rawFrameBuffer.GetPointer();
  641.   picture->data[1] = picture->data[0] + size;
  642.   picture->data[2] = picture->data[1] + (size / 4);
  643.   picture->linesize[0] = frameWidth;
  644.   picture->linesize[1] = frameWidth / 2;
  645.   picture->linesize[2] = frameWidth / 2;
  646. }
  647.  
  648. void H323_FFH263Codec::CloseCodec()
  649. {
  650.   if (!ff.IsLoaded())
  651.      return;
  652.  
  653.   PTRACE(6, "FFH263\tClose h263 video " <<(direction == Encoder ? "En" : "De") << "coder" );
  654.   if (context == NULL) 
  655.     return;
  656.  
  657.   ff.AvcodecClose(context);
  658. }
  659.  
  660.  
  661.  
  662. // This function is called from H323_RTPChannel::Transmit() in channels.cxx
  663. // to grab, display, and compress a video frame into FFH263 packets.
  664. //   1- get another frame if all packets of previous frame have been sent
  665. //   2- get next packet on list and send that one
  666. //   3- render the current frame if all of its packets have been sent
  667. BOOL H323_FFH263Codec::Read(BYTE * /*buffer*/, // pointer to the RTP payload
  668.               unsigned & length, // returns size of the RTP payload
  669.               RTP_DataFrame & frame)
  670. {
  671.  
  672.   if (!ff.IsLoaded())
  673.      return FALSE;
  674.  
  675.   PWaitAndSignal mutex1(videoHandlerActive);
  676.   PTRACE(6, "FFH263\tAcquire next packet from FFH263 encoder.");
  677.  
  678.   if (frameNum == 0) {
  679.     startTime = PTime();
  680.   }
  681.    
  682.   if (rawDataChannel == NULL) {
  683.     length = 0;
  684.     PTRACE(3, "FFH263\tNo channel to connect to video grabber, close down video transmission thread.");
  685.     return FALSE;
  686.   }
  687.  
  688.   if (!rawDataChannel->IsOpen()) {
  689.      length = 0;
  690.      PTRACE(3, "FFH263\tVideo grabber is not initialised, close down video transmission thread.");
  691.      return FALSE;
  692.   }
  693.   BOOL ok = TRUE;
  694.  
  695.   if (partialPackets.GetFragmentsRemaining() == 0) {
  696.     // No data is waiting to be read. Go and get some with the read call.
  697.  
  698.     PINDEX fWidth  = ((PVideoChannel *)rawDataChannel)->GetGrabWidth();
  699.     PINDEX fHeight = ((PVideoChannel *)rawDataChannel)->GetGrabHeight();
  700.     PTRACE(6, "FFH263\tVideo grab size is " << fWidth << "x" << fHeight);
  701.     if (fWidth == 0) {
  702.       PTRACE(1,"FFH263\tVideo grab width is 0 x 0, close down video transmission thread.");
  703.       length=0;
  704.       return FALSE;
  705.     }
  706.     Resize(fWidth, fHeight);
  707.  
  708.     if (!rawDataChannel->Read(rawFrameBuffer.GetPointer(), rawFrameLen)) {
  709.       PTRACE(3, "FFH263\tFailed to read data from video grabber, close down video transmission thread.");
  710.       return FALSE;   //Read failed, return false.
  711.     }
  712.     frameNum++;  //Increment the number of frames grabbed.
  713.  
  714.     // If there is a Renderer attached, display the grabbed video.
  715.     if (((PVideoChannel *)rawDataChannel)->IsRenderOpen())
  716.       ok = RenderFrame((const BYTE *)rawFrameBuffer); // use data from grab process
  717.     else
  718.       PTRACE(6, "FFH263\t No renderer open");
  719.  
  720.     unsigned char *srcPointer = encFrameBuffer.GetPointer(encFrameLen);
  721.  
  722. #if PTRACING
  723.     PTime encTime;
  724. #endif
  725.     PINDEX out_size =  ff.AvcodecEncodeVideo(context, srcPointer, encFrameLen, picture);
  726.     PTRACE(6, "FFH263\tEncoded " << out_size << " bytes from " << frameWidth << "x" << frameHeight << "  " << 
  727.        PThread::Current()->GetThreadId() << " in  " << (PTime() - encTime) << " seconds");    
  728.     partialPackets.AppendH263Packet(srcPointer, out_size);
  729.   }
  730.  
  731.   /* This is a sleazy hack to indicate that this RTP data frame contains
  732.      the non-compliant H.263 RTP payload encoding OpenH323 uses */
  733.   frame.SetExtensionType(263);
  734.  
  735.   H263Packet *packet = partialPackets.GetNextFragment();
  736.   if (packet == NULL) {
  737.     PTRACE(0, "FFH263\tEncoder internal error - there should outstanding PARTIAL packets at this point.");   
  738.     length = 0;
  739.     return TRUE; //And hope the error condition will fix itself
  740.   }
  741.   
  742.   length = packet->GetSize();
  743.   if (!frame.SetPayloadSize(length + 3)) {
  744.     PTRACE(1, "Internal error in h263 codec, cause writing too big a packet (" << length << ")");
  745.     length = 0;
  746.     return TRUE;
  747.   }
  748.  
  749.   memcpy(frame.GetPayloadPtr() + 3, packet->GetData(), length);
  750.   delete packet;
  751.   length += 3;
  752.  
  753.   *(frame.GetPayloadPtr() + 0) = (BYTE)partialPackets.GetFragmentIndex();
  754.   *(frame.GetPayloadPtr() + 1) = (BYTE)partialPackets.GetFragmentsTotal();
  755.   *(frame.GetPayloadPtr() + 2) = (BYTE)((frameWidth > 200) ? 1 : 0);  /*Large or small flag*/
  756.  
  757.   PTimeInterval timeLastPacket(1000 * bitsSent / bitRateHighLimit);
  758.   PTimeInterval deltaT = PTime() - startTime;
  759.   if (timeLastPacket > deltaT) {
  760.     PTRACE(5, "FFH263\tBit rate throttle, "
  761.        << bitsSent << " bits sent in " << deltaT
  762.        << " seconds, max=" << bitRateHighLimit
  763.        << " require time of " << timeLastPacket
  764.        << " waiting " << (timeLastPacket - deltaT).GetMilliSeconds() << " milli seconds");
  765.  
  766.    PThread::Current()->Sleep((timeLastPacket - deltaT));
  767.   } 
  768.  
  769.   startTime = PTime();
  770.   bitsSent = length << 3;
  771.  
  772.   if (partialPackets.GetFragmentsRemaining() == 0) 
  773.     frame.SetMarker(TRUE);
  774.   else 
  775.     frame.SetMarker(FALSE);
  776.  
  777.   return TRUE;
  778. }
  779.  
  780.  
  781. BOOL H323_FFH263Codec::Write(const BYTE * /*buffer*/,
  782.                            unsigned length,
  783.                            const RTP_DataFrame & frame,
  784.                            unsigned & written)
  785. {
  786.   if (!ff.IsLoaded())
  787.      return FALSE;
  788.  
  789.   PWaitAndSignal mutex1(videoHandlerActive);
  790.  
  791.   if (rawDataChannel == NULL) 
  792.     return FALSE;
  793.  
  794.   if (lastSequenceNumber == 1) {
  795.     lastSequenceNumber = frame.GetSequenceNumber();
  796.   } else if ((++lastSequenceNumber) != frame.GetSequenceNumber()) {
  797.     PTRACE(3, "FFH263\tDetected loss of one video packet. Will recover.");
  798.     currentFragment = 0;
  799.     lastSequenceNumber = frame.GetSequenceNumber();
  800.   }
  801.  
  802.   // always indicate we have written the entire packet
  803.   written = length;
  804.  
  805.   // get payload
  806.   BYTE * payload    = frame.GetPayloadPtr() + 3;
  807.   PINDEX payloadLen = frame.GetPayloadSize() - 3;
  808.  
  809.   PINDEX fragIndex  = *(frame.GetPayloadPtr() + 0);
  810.   PINDEX nFragments = *(frame.GetPayloadPtr() + 1);
  811.   PINDEX isLarge    = *(frame.GetPayloadPtr() + 2);
  812.  
  813.   if (isLarge)
  814.     Resize(352, 288);
  815.   else
  816.     Resize(176, 144);
  817.   
  818.   if (fragIndex == 1) {
  819.     currentFragment = 0;
  820.     encFrameBuffer.SetSize(00);
  821.   }
  822.   
  823.   if (fragIndex == (currentFragment + 1)) {
  824.     PINDEX curSize = encFrameBuffer.GetSize();
  825.     memcpy(encFrameBuffer.GetPointer(curSize + payloadLen) + curSize, payload, payloadLen);
  826.     currentFragment++;
  827.   } else {
  828.     currentFragment = 0;
  829.     encFrameBuffer.SetSize(00);
  830.     PTRACE(6, "FFH263\tError in fragment recovery, index " << fragIndex << " out of turn with " << currentFragment << " nFragments"<< nFragments);
  831.     return TRUE;     //*This is an error, but, just return and hope it recovers .
  832.   }
  833.  
  834.  
  835.   if ((nFragments != 1) && (currentFragment != nFragments)) 
  836.     return TRUE;  //*WE are still building the packet up from fragments.
  837.  
  838.   if (!frame.GetMarker()) 
  839.     return TRUE;
  840.  
  841. // full frame received, now process it
  842.   int got_picture;
  843.   
  844.   int actualSize = encFrameBuffer.GetSize();
  845.   memset(encFrameBuffer.GetPointer(actualSize + FF_INPUT_BUFFER_PADDING_SIZE) + actualSize, 0, FF_INPUT_BUFFER_PADDING_SIZE);
  846.   
  847.   int decodeLen = ff.AvcodecDecodeVideo(context, picture, &got_picture, encFrameBuffer.GetPointer(), actualSize);
  848.   PTRACE(6, "FFH263\tDecoded " << encFrameBuffer.GetSize() << " byte packet. Image= " 
  849.      << frameWidth << "x" << frameHeight << "  id=" <<        PThread::Current()->GetThreadId());
  850.   encFrameBuffer.SetSize(0);
  851.   lastebits = 0;
  852.   currentFragment = 0;
  853.   
  854.   if (decodeLen < 0) {
  855.     PTRACE(1, "FFH263\tError while decoding frame");
  856.     return TRUE;
  857.   }
  858.   
  859.   if (got_picture) {
  860.     /* the picture is allocated by the decoder. no need to free it */
  861.     RenderFrame(picture);
  862.     frameNum++; // increment the number of frames written
  863.   } 
  864.  
  865.   return TRUE;
  866. }
  867.  
  868.  
  869. BOOL H323_FFH263Codec::Resize(int _width, int _height)
  870. {
  871.   if (!ff.IsLoaded())
  872.     return FALSE;
  873.  
  874.   if ((frameWidth == _width) && (frameHeight == _height)) 
  875.     return TRUE;
  876.  
  877.   PTRACE(6, "FFH263\t" << (direction == Encoder ? "En" : "De") << "coder resizing to "
  878.      << _width << "x" << _height << ".");
  879.   
  880.   frameWidth = _width;
  881.   frameHeight = _height;
  882.   
  883.   rawFrameLen    = (_width * _height * 3) / 2;
  884.   rawFrameBuffer.SetSize(rawFrameLen + FF_INPUT_BUFFER_PADDING_SIZE); // input video frame
  885.   memset(rawFrameBuffer.GetPointer() + rawFrameLen, 0, FF_INPUT_BUFFER_PADDING_SIZE);
  886.   encFrameLen = rawFrameLen; // this could be set to some lower value
  887.   //encFrameBuffer.SetSize(encFrameLen); // encoded video frame
  888.   
  889.   if (context != NULL) { 
  890.     if (context->codec != NULL) {
  891.       PTRACE(6, "FFH263\t" << (direction == Encoder ? "En" : "De") << "coder closing because of resize to "
  892.        << _width << "x" << _height << ".");      
  893.       CloseCodec();
  894.     } 
  895.   }
  896.   InitialiseCodec();
  897.  
  898.   context->width  = frameWidth;
  899.   context->height = frameHeight;
  900.   
  901.   /* open it */
  902.   if (ff.AvcodecOpen(context, codec) < 0) {
  903.     fprintf(stderr, "could not open codec for FFH263P\n");
  904.     PTRACE(0, "FFH263\tVideo " <<(direction == Encoder ? "En" : "De") << "coder open FAILED");
  905.     return FALSE;
  906.   }
  907.  
  908.   lastebits = 0;
  909.   return TRUE;
  910. }
  911.  
  912.  
  913. /* RenderFrame does two things:
  914.    a) Set size of the display frame. This call happens with every frame.
  915.      A very small overhead.
  916.    b) Display a frame.
  917. */
  918.  
  919. BOOL H323_FFH263Codec::RenderFrame(const void * buffer)
  920. {
  921.   if (rawDataChannel == NULL)
  922.     return TRUE;
  923.  
  924.   //Now display local image.
  925.   ((PVideoChannel *)rawDataChannel)->SetRenderFrameSize(frameWidth, frameHeight);
  926.  
  927.   return rawDataChannel->Write(buffer, 0 /*unused parameter*/);
  928. }
  929.  
  930.  
  931. BOOL H323_FFH263Codec::RenderFrame(AVFrame *pict)
  932. {
  933.   PINDEX offset = 0;
  934.   for (PINDEX plane = 0; plane < 3; plane ++) {
  935.     unsigned char *src = pict->data[plane];
  936.     PINDEX        wrap = pict->linesize[plane];
  937.     PINDEX        ysize = (plane == 0) ? context->height : context->height >> 1;
  938.     PINDEX        xsize = (plane == 0) ? context->width  : context->width  >> 1;
  939.     for (PINDEX line = 0; line < ysize; line++) {
  940.       memcpy(rawFrameBuffer.GetPointer() + offset, src + (line * wrap), xsize);
  941.       offset += xsize;
  942.     }
  943.   }
  944.   return RenderFrame((const BYTE *)rawFrameBuffer);
  945. }
  946.  
  947.  
  948. void H323_FFH263Codec::SetTxQualityLevel(int /*qLevel*/)
  949. {
  950. #if 0
  951.   qualityLevel = PMIN(14, PMAX(qLevel,3));
  952.  
  953.   lowLimit = PMIN(10, qLevel - 2);
  954.   highLimit = qLevel + 12;
  955.  
  956.   // If there is no bandwidth limit, update the actual value as well
  957.   if (videoBitRate == 0)
  958.     actualQuality = qualityLevel;
  959. #endif
  960. }
  961.  
  962.  
  963. void H323_FFH263Codec::SetBackgroundFill(int /*idle*/)
  964. {
  965.   //  fillLevel = PMIN(99, PMAX(idle,1));
  966. }
  967.  
  968.  
  969. void H323_FFH263Codec::OnLostPartialPicture()
  970. {
  971.   PTRACE(3, "FFH263\tLost partial picture message ignored, not implemented");
  972. }
  973.  
  974.  
  975. void H323_FFH263Codec::OnLostPicture()
  976. {
  977.   PTRACE(3, "FFH263\tLost picture message ignored, not implemented");
  978. }
  979.  
  980.  
  981.  
  982.  
  983. //////////////////////////////////////////////////////////////////////
  984. H263Packet::H263Packet(void *newData, int newSize)
  985. {
  986.   size = newSize;
  987.   data = newData;
  988. }
  989.  
  990. H263Packet::~H263Packet()
  991. {
  992. }
  993.  
  994.  
  995.  
  996. //////////////////////////////////////////////////////////////////////
  997. H263FragmentList::~H263FragmentList()
  998. {
  999.   AllowDeleteObjects();
  1000.   RemoveAll();
  1001. }
  1002.  
  1003. void H263FragmentList::AppendH263Packet(H263Packet *packet)
  1004. {
  1005.   PINDEX length = packet->GetSize();
  1006.   nPackets = (length / 1400) + 1;
  1007.   
  1008.   PINDEX size = length / nPackets;
  1009.   unsigned char *data = (unsigned char *)packet->GetData();
  1010.  
  1011.   for (PINDEX i = 0; i < nPackets; i++) {
  1012.     PINDEX sendSize = (i == (nPackets - 1)) ? packet->GetSize() - (i * size) : size;
  1013.     H263Packet *p = new H263Packet(data + (i * size), sendSize);
  1014.     Append(p);
  1015.   }
  1016. }
  1017.  
  1018. void H263FragmentList::AppendH263Packet(unsigned char *data, int size)
  1019. {
  1020.   if (data == NULL)
  1021.     return;
  1022.  
  1023.   H263Packet p(data, size);
  1024.   AppendH263Packet(&p);
  1025. }
  1026.  
  1027.  
  1028. H263Packet *H263FragmentList::GetNextFragment()
  1029. {
  1030.   if (GetSize() > 0) {
  1031.     DisallowDeleteObjects();
  1032.     H263Packet *answer = (H263Packet *)GetAt(0);
  1033.     RemoveAt(0);
  1034.     return answer;
  1035.   }
  1036.  
  1037.   return NULL;
  1038. }
  1039.  
  1040.  
  1041. PINDEX  H263FragmentList::GetFragmentsRemaining()
  1042. {
  1043.   return GetSize();
  1044. }  
  1045.  
  1046. PINDEX H263FragmentList::GetFragmentIndex()
  1047. {
  1048.   return nPackets - GetSize();
  1049. }
  1050.  
  1051. PINDEX H263FragmentList::GetFragmentsTotal()
  1052. {
  1053.   return nPackets;
  1054. }
  1055.    
  1056.  
  1057. #endif // H323_AVCODEC
  1058.  
  1059.  
  1060. //////////////////////////////////////////////////////////////////////
  1061.