tm5rc.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:14k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (c) 1997 NextLevel Systems of Delaware, Inc.  All rights reserved.
  3.  * 
  4.  * This software module  was developed by  Bob Eifrig (at NextLevel
  5.  * Systems of Delaware, Inc.), Xuemin Chen (at NextLevel Systems of
  6.  * Delaware, Inc.), and Ajay Luthra (at NextLevel Systems of Delaware,
  7.  * Inc.), in the course of development of the MPEG-4 Video Standard
  8.  * (ISO/IEC 14496-2).   This software module is an implementation of a
  9.  * part of one or more tools as specified by the MPEG-4 Video Standard.
  10.  * 
  11.  * NextLevel Systems of Delaware, Inc. grants the right, under its
  12.  * copyright in this software module, to use this software module and to
  13.  * make modifications to it for use in products which conform to the
  14.  * MPEG-4 Video Standard.  No license is granted for any use in
  15.  * connection with products which do not conform to the MPEG-4 Video
  16.  * Standard.
  17.  * 
  18.  * Those intending to use this software module are advised that such use
  19.  * may infringe existing and unissued patents.  Please note that in
  20.  * order to practice the MPEG-4 Video Standard, a license may be
  21.  * required to certain patents held by NextLevel Systems of Delaware,
  22.  * Inc., its parent or affiliates ("NextLevel").   The provision of this
  23.  * software module conveys no license, express or implied, under any
  24.  * patent rights of NextLevel or of any third party.  This software
  25.  * module is subject to change without notice.  NextLevel assumes no
  26.  * responsibility for any errors that may appear in this software
  27.  * module.  NEXTLEVEL DISCLAIMS ALL WARRANTIES, EXPRESS AND IMPLIED,
  28.  * INCLUDING, BUT NOT LIMITED TO ANY WARRANTY THAT COMPLIANCE WITH OR
  29.  * PRACTICE OF THE SPECIFICATIONS OR USE OF THIS SOFTWARE MODULE WILL
  30.  * NOT INFRINGE THE INTELLECTUAL PROPERTY RIGHTS OF NEXTLEVEL OR ANY
  31.  * THIRD PARTY, AND ANY IMPLIED WARRANTIES OF MERCHANTABILITY AND
  32.  * FITNESS FOR A PARTICULAR PURPOSE.
  33.  * 
  34.  * NextLevel retains the full right to use this software module for its
  35.  * own purposes, to assign or transfer this software module to others,
  36.  * to prevent others from using this software module in connection with
  37.  * products which do not conform to the MPEG-4 Video Standard, and to
  38.  * prevent others from infringing NextLevel's patents.
  39.  * 
  40.  * As an express condition of the above license grant, users are
  41.  * required to include this copyright notice in all copies or derivative
  42.  * works of this software module.
  43.  */
  44. /* MPEG-2 Video TM-5 rate control 
  45.    For the purpose of comparing
  46.    MPEG-4 VM with MPEG-2 TM-5
  47.    27.03.97 By X. Chen in G.I.
  48.  * 23.01.99 David Ruhoff: (double) cast to dj calc per Sarnoff labs
  49.  * 16.03.99 David Ruhoff: conversion to microsoft-vfdis-v10-990124
  50.  */
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <iostream.h>
  54. #include <math.h>
  55. #include "header.h"
  56. #include "typeapi.h"
  57. //#include "codehead.h"
  58. //#include "entropy/bitstrm.hpp"
  59. #include "entropy/entropy.hpp"
  60. #include "entropy/huffman.hpp"
  61. #include "mode.hpp"
  62. //#include "global.hpp"
  63. #include "vopses.hpp"
  64. #include "vopseenc.hpp"
  65. #include "tm5rc.hpp"
  66. void TM5rc::tm5rc_init_seq( char       *pchQname,
  67. UInt       rc_type_arg, 
  68. AlphaUsage fAUsage, 
  69. UInt       uiWidth, 
  70. UInt       uiHeight, 
  71. UInt       uiBitRate,
  72. Double     dFrameRate
  73.    )
  74. {
  75.   if (fAUsage != RECTANGLE) {
  76.       fprintf(stderr, "TM5 rate control requires a rectangular VOPn");
  77.       exit(1);
  78.   }
  79.   rc_type = rc_type_arg;
  80.   switch (rc_type) {
  81.   case RC_TM5:
  82.       break;
  83.   case RC_TM5+1:
  84.       assert(pchQname);
  85.       assert(*pchQname);
  86.       if ((Qfile = fopen(pchQname, "r")) == NULL) {
  87.           fprintf(stderr, "Cannot open %sn", pchQname);
  88.           exit(1);
  89.       }
  90.       break;
  91.   case RC_TM5+2:
  92.       assert(pchQname);
  93.       assert(*pchQname);
  94.       if ((Qfile = fopen(pchQname, "w")) == NULL) {
  95.           fprintf(stderr, "Cannot open %sn", pchQname);
  96.           exit(1);
  97.       }
  98.       break;
  99.   default:
  100.       fprintf(stderr, "Invalid rate control code: %dn", rc_type);
  101.       exit(1);
  102.   }
  103.   mb_width = (uiWidth + MB_SIZE - 1) / MB_SIZE;
  104.   mb_height = (uiHeight + MB_SIZE - 1) / MB_SIZE;
  105.   bitrate = uiBitRate;
  106.   pic_rate = dFrameRate;
  107.   /* memory leak -- need to free when done */
  108.   mbact = new double [mb_width * mb_height];
  109.   /* reaction parameter (constant) */
  110.   /* if (r_tm5==0)  */
  111.       r_tm5 = (int)floor(2.0*bitrate/pic_rate + 0.5);
  112.   /* average activity */
  113.   if (avg_act==0.0)  avg_act = 400.0;
  114.   /* remaining # of bits in GOP */
  115.   R_tm5 = 0;
  116.   /* global complexity measure */
  117.   if (Xi==0) Xi = (int)floor(160.0*bitrate/115.0 + 0.5);
  118.   if (Xp==0) Xp = (int)floor( 60.0*bitrate/115.0 + 0.5);
  119.   if (Xb==0) Xb = (int)floor( 42.0*bitrate/115.0 + 0.5);
  120.   /* virtual buffer fullness */
  121.   if (d0i==0) d0i = (int)floor(10.0*r_tm5/31.0 + 0.5); // ***** NOT CORRECT FOR NBIT *****
  122.   if (d0p==0) d0p = (int)floor(10.0*r_tm5/31.0 + 0.5);
  123.   if (d0b==0) d0b = (int)floor(1.4*10.0*r_tm5/31.0 + 0.5);
  124.   cout.sync_with_stdio();
  125.   fprintf(stdout,"rate control: sequence initializationn");
  126.   fprintf(stdout," initial global complexity measures (I,P,B): Xi=%d, Xp=%d, Xb=%dn",
  127.     Xi, Xp, Xb);
  128.   fprintf(stdout," reaction parameter: r_tm5=%dn", r_tm5);
  129.   fprintf(stdout," initial virtual buffer fullness (I,P,B): d0i=%d, d0p=%d, d0b=%dn",
  130.     d0i, d0p, d0b);
  131.   fprintf(stdout," initial average activity: avg_act=%.1fnn", avg_act);
  132. }
  133. void TM5rc::tm5rc_init_GOP(int np,int nb)
  134. {
  135.   if ((Ni + Np + Nb) != 0) {
  136.       fprintf(stderr, "TM5: Short GOP, expected %d/%d/%d more I/P/B-picsn",
  137.           Ni, Np, Nb);
  138.       exit(1);
  139.   }
  140.   R_tm5 += (int) floor((1 + np + nb) * bitrate / pic_rate + 0.5);
  141.   Np = np;
  142.   Nb = nb;
  143.   Ni = 1;
  144.   cout.sync_with_stdio();
  145.   fprintf(stdout,"nrate control: new group of pictures (GOP)n");
  146.   fprintf(stdout," target number of bits for GOP: R_tm5=%dn",R_tm5);
  147.   fprintf(stdout," number of P pictures in GOP: Np=%dn",Np);
  148.   fprintf(stdout," number of B pictures in GOP: Nb=%dnn",Nb);
  149. }
  150. /* Note: we need to substitute K for the 1.4 and 1.0 constants -- this can
  151.    be modified to fit image content */
  152. /* Step 1: compute target bits for current picture being coded */
  153. void TM5rc::tm5rc_init_pict(VOPpredType vopPredType,
  154.                             const PixelC* ppxlcOrigY,
  155.                             Int row_size,
  156.                             Int iNumMBX,
  157.                             Int iNumMBY)
  158. {
  159.   Double Tmin;
  160.   Int type;
  161.   switch (rc_type) {
  162.   
  163.   case RC_TM5+1:
  164.       type = -1;
  165.       if ((fscanf(Qfile, "%d", &type) != 1) || (type != vopPredType)) {
  166.           fprintf(stderr, "Wrong pictue type: got %d, expected %dn",
  167.               type, vopPredType);
  168.           exit(1);
  169.       }
  170.       return;
  171.   case RC_TM5+2:
  172.       fprintf(Qfile, "%d ", vopPredType);
  173.       break;
  174.   }
  175.   switch (vopPredType)
  176.   {
  177.   default:
  178.     fprintf(stderr, "Invalid vopPredType code: %dn", vopPredType);
  179.     exit(1);  
  180.   case IVOP:
  181.     T_tm5 = (int) floor(R_tm5/(1.0+Np*Xp/(Xi*1.0)+Nb*Xb/(Xi*1.4)) + 0.5);
  182.     d_tm5 = d0i;
  183.     break;
  184.   case PVOP:
  185.     T_tm5 = (int) floor(R_tm5/(Np+Nb*1.0*Xb/(1.4*Xp)) + 0.5);
  186.     d_tm5 = d0p;
  187.     break;
  188.   case BVOP:
  189.     T_tm5 = (int) floor(R_tm5/(Nb+Np*1.4*Xp/(1.0*Xb)) + 0.5);
  190.     d_tm5 = d0b;
  191.     break;
  192.   }
  193.   Tmin = (int) floor(bitrate/(8.0*pic_rate) + 0.5);
  194.   if (T_tm5<Tmin)
  195.     T_tm5 = (int)Tmin;
  196.   Q_tm5 = 0;
  197.   tm5_calc_actj(ppxlcOrigY, row_size, iNumMBX, iNumMBY);
  198.   actsum = 0.0;
  199.   cout.sync_with_stdio();
  200.   fprintf(stdout,"rate control: start of picturen");
  201.   fprintf(stdout," target number of bits: T_tm5=%dn",T_tm5);
  202.   fflush(stdout);
  203. //printf("ppxlcOrigY=%p row_size=%d iNumMBX=%d iNumMBY=%dn", 
  204. // ppxlcOrigY, row_size, iNumMBX, iNumMBY);
  205. }
  206. void TM5rc::tm5_calc_actj(const PixelC* ppxlcOrigY,
  207.                           Int row_size,
  208.                           Int iNumMBX,
  209.                           Int iNumMBY)
  210. {
  211.   assert (MB_SIZE == 2*BLOCK_SIZE);
  212.   Double actj, var;
  213.   Int    k = 0;
  214.   Int    iMBY, iMBX;
  215.   for (iMBY=0; iMBY<iNumMBY; iMBY++) {
  216.     const PixelC* ppxlcOrigMBY = ppxlcOrigY;
  217.     for (iMBX=0; iMBX<iNumMBX; iMBX++) {
  218.       /* take minimum spatial activity measure of luminance blocks */
  219.       actj = tm5_var_sblk(ppxlcOrigMBY,                                row_size);
  220.       var  = tm5_var_sblk(ppxlcOrigMBY+BLOCK_SIZE,                     row_size);
  221.       if (var<actj) actj = var;
  222.       var  = tm5_var_sblk(ppxlcOrigMBY+BLOCK_SIZE*row_size,            row_size);
  223.       if (var<actj) actj = var;
  224.       var  = tm5_var_sblk(ppxlcOrigMBY+BLOCK_SIZE*row_size+BLOCK_SIZE, row_size);
  225.       if (var<actj) actj = var;
  226.     
  227.       actj += 1.0;
  228.       mbact[k++] = actj;
  229.       
  230.       ppxlcOrigMBY += MB_SIZE;
  231.     }
  232.     ppxlcOrigY += row_size*MB_SIZE;
  233.   }
  234. }
  235. /* compute variance of 8x8 block */
  236. Double TM5rc::tm5_var_sblk(const PixelC *p, Int lx)
  237. {
  238.   int i, j;
  239.   unsigned int v, s, s2;
  240.   assert (BLOCK_SIZE == 8);
  241.   s = s2 = 0;
  242.   for (j=0; j<8; j++)
  243.   {
  244.     for (i=0; i<8; i++)
  245.     {
  246.       v = *p++;
  247.       s+= v;
  248.       s2+= v*v;
  249.     }
  250.     p+= lx - 8;
  251.   }
  252.   return s2/64.0 - (s/64.0)*(s/64.0);
  253. }
  254. /* compute initial quantization stepsize (at the beginning of picture) */
  255. Int TM5rc::tm5rc_start_mb()
  256. {
  257.     Int mquant;
  258.     if (rc_type == RC_TM5+1) {
  259.         if (fscanf(Qfile, "%d", &mquant) != 1) {
  260.             fprintf(stderr, "Q file read errorn");
  261.             exit(1);
  262.         }
  263.         return mquant;
  264.     }
  265.     mquant = (int) floor(d_tm5*31.0/r_tm5 + 0.5); // ***** NOT CORRECT FOR NBIT ************
  266.     
  267.     /* clip mquant to legal range */
  268.     if (mquant<1)
  269.       mquant = 1;
  270.     if (mquant>31)  // ***** NOT CORRECT FOR NBIT ************
  271.       mquant = 31;
  272.     prev_mquant = mquant = mquant;
  273.     if (rc_type == RC_TM5+2) {
  274.         fprintf(Qfile, "%2dn", mquant);
  275.         linectr = 0;
  276.     }
  277. cout.sync_with_stdio(); printf(" tm5rc_start_mb mquant=%dn",mquant);
  278. //fprintf(stdout,"tjtsizetmquanttd_tm5tT_tm5tdjtQjtactjtN_actjn");
  279.     return mquant;
  280. }
  281. /* Step 2: measure virtual buffer - estimated buffer discrepancy */
  282. Int TM5rc::tm5rc_calc_mquant(Int j, UInt size)
  283. {
  284.   int mquant;
  285.   double dj, Qj, actj, N_actj;
  286.   if (rc_type == RC_TM5+1) {
  287.       if (fscanf(Qfile, "%d", &mquant) != 1) {
  288.          fprintf(stderr, "Q file read errorn");
  289.          exit(1);
  290.       }
  291.       return mquant;
  292.   }
  293.   /* measure virtual buffer discrepancy from uniform distribution model */
  294.   dj = (double)((double)d_tm5 + (double)size - (double)j*((double)T_tm5/((double)mb_width*(double)mb_height)));
  295. /*
  296. fprintf(stdout,"dj=%.5f: d_tm5=%.3f, size=%d, j=%d, T_tm5=%.3f, width=%d  height=%dn",
  297.    (float)dj, (float)d_tm5, (int)size, (int)j, (float)T_tm5, (int)mb_width, (int)mb_height);
  298. */
  299.   /* scale against dynamic range of mquant and the bits/picture count */
  300.   Qj = dj*31.0/r_tm5; // ***** NOT CORRECT FOR NBIT ************
  301.   actj = mbact[j];
  302.   actsum += actj;
  303.   /* compute normalized activity */
  304.   N_actj = (2.0*actj+avg_act)/(actj+2.0*avg_act);
  305.     /* modulate mquant with combined buffer and local activity measures */
  306.     mquant = (int) floor(Qj*N_actj + 0.5);
  307.    
  308.     /* clip mquant to legal range */
  309.     if (mquant<1)
  310.       mquant = 1;
  311.     if (mquant>31) // ***** NOT CORRECT FOR NBIT ************
  312.       mquant = 31;
  313.     mquant = mquant;
  314.  
  315.   Q_tm5 += mquant; /* for calculation of average mquant */
  316.   if (rc_type == RC_TM5+2) {
  317.       fprintf(Qfile, "%2d ", mquant);
  318.       if (++(linectr) >= mb_width) {
  319.           fprintf(Qfile, "n");
  320.           linectr = 0;
  321.       }
  322.   }
  323. //fprintf(stdout,"t%dt%dt%dt%dt%dt%gt%gt%gt%gn",
  324. //   j, size, mquant, d_tm5, T_tm5, dj, Qj, actj, N_actj);
  325.   return mquant;
  326. }
  327. void TM5rc::tm5rc_update_pict(VOPpredType vopPredType, Int iVOPtotalBits)
  328. {
  329.   double X;
  330.   if (rc_type == RC_TM5+1) {
  331.     switch (vopPredType) {
  332.     case IVOP: Ni--; break;
  333.     case PVOP: Np--; break;
  334.     case BVOP: Nb--; break;
  335.     default: break;
  336.     }
  337.     return;
  338.   }
  339.                         /* total # of bits in picture */
  340.   R_tm5 -= iVOPtotalBits; /* remaining # of bits in GOV */
  341.   X = (int) floor(iVOPtotalBits*((0.5*(double)(Q_tm5))/
  342.       (mb_width*mb_height)) + 0.5);
  343.   d_tm5 += iVOPtotalBits - T_tm5;
  344.   avg_act = actsum/(mb_width*mb_height);
  345.   switch (vopPredType)
  346.   {
  347.   case IVOP:
  348.     Xi = (int)X;
  349.     d0i = d_tm5;
  350.     if (--(Ni) < 0) {
  351.         fprintf(stderr, "TM5: too many I-pics in GOPn");
  352.         exit(1);
  353.     }
  354.     break;
  355.   case PVOP:
  356.     Xp = (int)X;
  357.     d0p = d_tm5;
  358.     if (--(Np) < 0) {
  359.         fprintf(stderr, "TM5: too many P-pics in GOPn");
  360.         exit(1);
  361.     }
  362.     break;
  363.   case BVOP:
  364.     Xb = (int)X;
  365.     d0b = d_tm5;
  366.     if (--(Nb) < 0) {
  367.         fprintf(stderr, "TM5: too many B-pics in GOPn");
  368.         exit(1);
  369.     }
  370.     break;
  371.   default:
  372.     fprintf(stderr, "Invalid vopPredType code: %dn", vopPredType);
  373.     exit(1);  
  374.   }
  375.   cout.sync_with_stdio();
  376.   fprintf(stdout,"rate control: end of picturen");
  377.   fprintf(stdout," actual number of bits=%dn",iVOPtotalBits);
  378.   fprintf(stdout," average quantization parameter Q_tm5=%.1fn",
  379.     (double)Q_tm5/(mb_width*mb_height));
  380.   fprintf(stdout," remaining number of bits in GOP: R_tm5=%dn",R_tm5);
  381.   fprintf(stdout," global complexity measures (I,P,B): Xi=%d, Xp=%d, Xb=%dn",
  382.     Xi, Xp, Xb);
  383.   fprintf(stdout," virtual buffer fullness (I,P,B): d0i=%d, d0p=%d, d0b=%dn",
  384.     d0i, d0p, d0b);
  385.   fprintf(stdout," remaining number of P pictures in GOP: Np=%dn",Np);
  386.   fprintf(stdout," remaining number of B pictures in GOP: Nb=%dn",Nb);
  387.   fprintf(stdout," average activity: avg_act=%.1fn", avg_act);
  388.   fflush(stdout);
  389. }