libr263.cpp
上传用户:panstart
上传日期:2022-04-12
资源大小:199k
文件大小:8k
源码类别:

IP电话/视频会议

开发平台:

C++ Builder

  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. //
  4. //    Project     : VideoNet version 1.1.
  5. //    Description : Peer to Peer Video Conferencing over the LAN.
  6. //   Author      : Nagareshwar Y Talekar ( nsry2002@yahoo.co.in)
  7. //    Date        : 15-6-2004.
  8. //
  9. //    I have converted origional fast h.263 encoder library from C to C++ 
  10. //   so that it can be integrated into any windows application easily.
  11. //   I have removed some of unnecessary codes/files from the
  12. //   fast h263 library.Also moved definitions and declarations
  13. //   in their proper .h and .cpp files.
  14. //
  15. //    File description : 
  16. //    Name    : libr263.cpp
  17. //    Details : Entry point to encoder....
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. /*************************************************
  21.  * libr263: fast H.263 encoder library
  22.  *
  23.  * Copyright (C) 1996, Roalt Aalmoes, Twente University
  24.  * SPA multimedia group
  25.  *
  26.  * Based on Telenor TMN 1.6 encoder (Copyright (C) 1995, Telenor R&D)
  27.  * created by Karl Lillevold 
  28.  *
  29.  * Author encoder: Roalt Aalmoes, <aalmoes@huygens.nl>
  30.  * 
  31.  * Date: 31-07-96
  32.  **************************************************/
  33. #include "libr263.h"
  34. int InitH263Encoder(CParam *params)
  35. {
  36.   Global::pic = (Pict *)malloc(sizeof(Pict));
  37.   
  38.   if(!Global::pic) 
  39.   {
  40.   return -1;
  41.   }
  42.   Global::pic->unrestricted_mv_mode = DEF_UMV_MODE;
  43.   Global::pic->use_gobsync = DEF_INSERT_SYNC;
  44.   Global::pic->PB = 0;
  45.   Global::pic->TR = 0;
  46.   Global::pic->QP_mean = 0.0;
  47.   if(params->format == CPARAM_QCIF) {
  48.     Global::pels = QCIF_YWIDTH;
  49.     Global::lines = QCIF_YHEIGHT;
  50.     Global::cpels = QCIF_YWIDTH/2;
  51.     Global::pic->source_format = SF_QCIF;
  52.   } else if (params->format == CPARAM_CIF) {
  53.     Global::pels = CIF_YWIDTH;
  54.     Global::lines = CIF_YHEIGHT;
  55.     Global::cpels = CIF_YWIDTH/2;
  56.     Global::pic->source_format = SF_CIF;
  57.   } else if (params->format == CPARAM_SQCIF) {
  58.     Global::pels = SQCIF_YWIDTH;
  59.     Global::lines = SQCIF_YHEIGHT;
  60.     Global::cpels = SQCIF_YWIDTH/2;
  61.     Global::pic->source_format = SF_SQCIF;
  62.   } else if (params->format == CPARAM_4CIF) {
  63.     Global::pels = CIF4_YWIDTH;
  64.     Global::lines = CIF4_YHEIGHT;
  65.     Global::cpels = CIF4_YWIDTH/2;
  66.     Global::pic->source_format = SF_4CIF;  
  67.   } else if (params->format == CPARAM_16CIF) {
  68.     Global::pels = CIF16_YWIDTH;
  69.     Global::lines = CIF16_YHEIGHT;
  70.     Global::cpels = CIF16_YWIDTH/2;
  71.     Global::pic->source_format = SF_16CIF;
  72.   } else {
  73.     Global::pels = params->pels;
  74.     Global::lines = params->lines;
  75.     Global::cpels = params->pels / 2;
  76.     Global::pic->source_format = 0; /* ILLEGAL H.263! Use it only for testing */
  77.   }
  78.   
  79.   Global::mbr = Global::lines / MB_SIZE;
  80.   Global::mbc = Global::pels / MB_SIZE;
  81.   Global::uskip = Global::lines*Global::pels;
  82.   Global::vskip = Global::uskip + Global::lines*Global::pels/4;
  83.   Global::sizeof_frame = (Global::vskip + Global::lines*Global::pels/4)*sizeof(int);
  84.   Global::headerlength = DEF_HEADERLENGTH;
  85.   /* Initalize VLC_tables */
  86.   InitHuff();
  87.   mwinit();
  88.   /* Init motion detection */
  89.   init_motion_detection();
  90. #ifdef VERYFASTIDCT
  91.   init_idct(); /* Do this in case of VERYFASTIDCT */
  92. #elif STANDARDIDCT
  93.   init_idctref(); /* Do this in case of standard IDCT */
  94. #endif
  95. /* Do nothing for FASTIDCT */
  96.   /* Set internal variables */
  97.   Global::advanced = DEF_ADV_MODE;
  98.   Global::mv_outside_frame = DEF_UMV_MODE || DEF_ADV_MODE;
  99.   Global::long_vectors = DEF_UMV_MODE;
  100.   Global::pb_frames = DEF_PBF_MODE;
  101.   Global::search_p_frames = DEF_SPIRAL_SEARCH;
  102.   Global::trace = DEF_WRITE_TRACE;
  103.   params->half_pixel_searchwindow = CPARAM_DEFAULT_SEARCHWINDOW; 
  104.   params->inter = CPARAM_DEFAULT_INTER;
  105.   params->search_method = CPARAM_DEFAULT_SEARCH_METHOD;
  106.   params->advanced_method = CPARAM_DEFAULT_ADVANCED_METHOD;
  107.   params->Q_inter = CPARAM_DEFAULT_INTER_Q;
  108.   params->Q_intra = CPARAM_DEFAULT_INTRA_Q;
  109.   params->interpolated_lum = (unsigned int*)malloc(Global::pels*Global::lines*4*sizeof(int));
  110.   if(!params->interpolated_lum)
  111.     return -1;
  112.   params->recon =(unsigned int*) malloc(Global::sizeof_frame);
  113.   if(!params->recon) {
  114.     free(params->interpolated_lum);
  115.     free(Global::pic);
  116.     return -1;
  117.   }
  118.   return 0;
  119. }
  120. void SkipH263Frames(int frames_to_skip)
  121. {
  122.   Global::pic->TR += frames_to_skip % 256;
  123. }
  124. int CompressFrame(CParam *params, Bits *bits)
  125. {
  126.   if(!params->inter) {
  127.     CodeIntraH263(params, bits);
  128.   } else {
  129.     CodeInterH263(params, bits);
  130.   }
  131.   bits->header += zeroflush();  /* pictures shall be byte aligned */
  132.   Global::pic->TR += 1 % 256; /* one means 30 fps */
  133.   return 0;
  134. }
  135. void ExitH263Encoder(CParam *params)
  136. {
  137.   mwcloseinit();
  138.   free(params->interpolated_lum);
  139.   free(params->recon);
  140.   free(Global::pic);
  141.   return;
  142. }
  143. /* Motion Detection part */
  144. static int global_mb_threshold;
  145. static int global_pixel_threshold;
  146. /* This array is computed for QCIF
  147.   movement_detection[] = {0, 354, 528, 177,
  148.                           3, 353, 531, 178,
  149.           352, 179, 530, 1,
  150.           355, 176, 2, 529 };
  151.   */
  152. /* This array determines the order in a pixel is checked per 4x4 block */
  153. /* {x, y} within [0..3] */
  154. static unsigned int movement_coords[16][2] = { {0,0}, {2,2},{0,3},{1,1},
  155.                        {3,0},{1,2},{3,3},{2,1},
  156.                {0,2},{3,1},{2,3},{1,0},
  157.                {3,2},{0,1},{2,0},{1,3} };
  158. static int movement_detection[16][4];
  159. void init_motion_detection()
  160. {
  161.   unsigned int counter, pos;
  162.   for(counter = 0; counter < 16; counter++) {
  163.     pos = movement_coords[counter][0] + movement_coords[counter][1]*Global::pels;
  164.     movement_detection[counter][0] = pos;
  165.     movement_detection[counter][1] = pos + 4;
  166.     movement_detection[counter][2] = pos + Global::pels*4;
  167.     movement_detection[counter][3] = pos + Global::pels*4 + 4;
  168.   }
  169.   return;
  170. }
  171. //__inline__ static int Check8x8(unsigned int *orig, unsigned int *recon, int pos)
  172. static int Check8x8(unsigned int *orig, unsigned int *recon, int pos)
  173. {
  174.   int value, index;
  175.   register int thres = global_pixel_threshold;
  176.   value = 0;
  177.   /* Mark pixel changed when lum value differs more than "thres" */
  178.   index = movement_detection[pos][0];
  179.   value += abs(*(orig + index) - *(recon+index)) > thres;
  180.   index = movement_detection[pos][1];
  181.   value += abs(*(orig + index) - *(recon+index)) > thres;
  182.   index = movement_detection[pos][2];
  183.   value += abs(*(orig + index) - *(recon+index)) > thres;
  184.   index = movement_detection[pos][3];
  185.   value += abs(*(orig + index) - *(recon+index)) > thres;
  186.   return value;
  187. }
  188. static int HasMoved(int call_time,  void *real,
  189.      void *recon, int x, int y)
  190. {
  191.   int offset1;
  192.   unsigned int *MB_orig;
  193.   unsigned int *MB_recon;
  194.   int position;
  195.   int value = 0;
  196.   offset1 = (y*Global::pels+x)*MB_SIZE;
  197.   position = call_time;
  198.   /* Integration of 8x8 and 4x4 check might improve performance, 
  199.      but is not done here */
  200.   MB_orig = (unsigned int *) real + offset1;
  201.   MB_recon = (unsigned int *) recon + offset1;
  202.   value += Check8x8(MB_orig, MB_recon, position);
  203.   MB_orig += 8; MB_recon += 8;
  204.   value += Check8x8(MB_orig, MB_recon, position); 
  205.   MB_orig += 8*Global::pels - 8; MB_recon += 8*Global::pels - 8;
  206.   value += Check8x8(MB_orig, MB_recon, position);
  207.   MB_orig += 8; MB_recon += 8;
  208.   value += Check8x8(MB_orig, MB_recon, position);
  209.   return value > global_mb_threshold;
  210.   /* Mark MB changed if more than "global_mb_threshold" pixels are changed */
  211. }
  212. int FindMotion(CParam *params, int mb_threshold, int pixel_threshold)
  213. {
  214.   static int call_time = 0;
  215.   int j,i;
  216.   int counter = 0;
  217.   global_mb_threshold = mb_threshold;
  218.   global_pixel_threshold = pixel_threshold;
  219.   for(j = 0; j < Global::mbr; j++) {
  220.     for(i = 0; i < Global::mbc; i++) {
  221.       *(params->EncodeThisBlock + j*Global::mbc + i) = 
  222. HasMoved(call_time, params->data, params->recon, i,j);
  223.       counter += *(params->EncodeThisBlock +j*Global::mbc + i);
  224.     }
  225.   }
  226.   call_time = (call_time + 1) % 16;
  227.  
  228.   return counter;
  229. }