band_codec.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:17k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. *
  3. * $Id: band_codec.cpp,v 1.5 2005/01/30 05:11:40 gabest Exp $ $Name:  $
  4. *
  5. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  6. *
  7. * The contents of this file are subject to the Mozilla Public License
  8. * Version 1.1 (the "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. * http://www.mozilla.org/MPL/
  11. *
  12. * Software distributed under the License is distributed on an "AS IS" basis,
  13. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  14. * the specific language governing rights and limitations under the License.
  15. *
  16. * The Original Code is BBC Research and Development code.
  17. *
  18. * The Initial Developer of the Original Code is the British Broadcasting
  19. * Corporation.
  20. * Portions created by the Initial Developer are Copyright (c) 2004.
  21. * All Rights Reserved.
  22. *
  23. * Contributor(s): Thomas Davies (Original Author), Scott R Ladd
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
  27. * Public License Version 2.1 (the "LGPL"), in which case the provisions of
  28. * the GPL or the LGPL are applicable instead of those above. If you wish to
  29. * allow use of your version of this file only under the terms of the either
  30. * the GPL or LGPL and not to allow others to use your version of this file
  31. * under the MPL, indicate your decision by deleting the provisions above
  32. * and replace them with the notice and other provisions required by the GPL
  33. * or LGPL. If you do not delete the provisions above, a recipient may use
  34. * your version of this file under the terms of any one of the MPL, the GPL
  35. * or the LGPL.
  36. * ***** END LICENSE BLOCK ***** */
  37. #include <libdirac_common/band_codec.h>
  38. using namespace dirac;
  39. //! Constructor for encoding.
  40. BandCodec::BandCodec(BasicOutputManager* bits_out,
  41.                      size_t number_of_contexts,
  42.                      const SubbandList & band_list,
  43.                      int band_num):
  44.     ArithCodec<PicArray>(bits_out,number_of_contexts),
  45.     m_bnum(band_num),
  46.     m_node(band_list(band_num)),
  47.     m_xp(m_node.Xp()),
  48.     m_yp(m_node.Yp()),
  49.     m_xl(m_node.Xl()),
  50.     m_yl(m_node.Yl()),
  51.     m_vol(m_node.Xl()*m_node.Yl()),
  52.     m_reset_coeff_num( std::max( 25 , std::min(m_vol/32,800) ) ),
  53.     m_cut_off_point(m_node.Scale()>>1)
  54. {
  55.     if (m_node.Parent()!=0) 
  56.         m_pnode=band_list(m_node.Parent());
  57. }        
  58. //! Constructor for decoding.
  59. BandCodec::BandCodec(BitInputManager* bits_in,
  60.                      size_t number_of_contexts,
  61.                      const SubbandList& band_list,
  62.                      int band_num):
  63.     ArithCodec<PicArray>(bits_in,number_of_contexts),
  64.     m_bnum(band_num),
  65.     m_node(band_list(band_num)),
  66.     m_xp(m_node.Xp()),
  67.     m_yp(m_node.Yp()),
  68.     m_xl(m_node.Xl()),
  69.     m_yl(m_node.Yl()),
  70.     m_vol(m_node.Xl()*m_node.Yl()),
  71.     m_reset_coeff_num( std::max( 25 , std::min(m_vol/32,800) ) ),
  72.     m_cut_off_point(m_node.Scale()>>1)
  73. {
  74.     if (m_node.Parent()!=0) m_pnode=band_list(m_node.Parent());
  75. }
  76. void BandCodec::InitContexts()
  77. {
  78.     //initialises the contexts. 
  79.     //If _list does not already have values, then they're set to default values. 
  80.     //This way, the constructor can override default initialisation.
  81.     Context tmp_ctx;
  82.     
  83.     for (size_t i=0; i<m_context_list.size(); ++i)
  84.     {
  85.         if (i>=m_context_list.size())
  86.             m_context_list.push_back(tmp_ctx);
  87.         else
  88.         {
  89.             if (m_context_list[i].Weight()==0)
  90.                 m_context_list[i].SetCounts(1,1);
  91.         }
  92.     }
  93. }
  94. void BandCodec::ResetAll()
  95. {
  96.     for (unsigned int c = 0; c < m_context_list.size(); ++c)
  97.         if (m_context_list[c].Weight()>16)
  98.             m_context_list[c].HalveCounts();
  99. }
  100. void BandCodec::Resize(const int context_num)
  101. {
  102.     m_context_list[context_num].HalveCounts();
  103. }
  104. void BandCodec::Update( const bool symbol , const int context_num )
  105. {
  106.     m_context_list[context_num].IncrCount(symbol,1);
  107.     
  108.     if ( m_context_list[context_num].Weight() >= 1024 )
  109.         Resize( context_num );
  110. }
  111. int BandCodec::ChooseContext(const PicArray& data) const{ return NZ_BIN5plus_CTX; }
  112. //encoding function
  113. void BandCodec::DoWorkCode(PicArray& in_data)
  114. {
  115.     //main coding function, using binarisation
  116.     if (m_node.Parent()!=0)
  117.     {
  118.         m_pxp=m_pnode.Xp(); m_pyp=m_pnode.Yp();
  119.         m_pxl=m_pnode.Xl(); m_pyl=m_pnode.Yl();
  120.     }
  121.     else
  122.     {
  123.         m_pxp=0; m_pyp=0;
  124.         m_pxl=0; m_pyl=0;
  125.     }
  126.     
  127.     ValueType val;
  128.     m_qf=m_node.Qf(0);
  129.     m_qfinv=(1<<17)/m_qf;
  130.     m_offset=(3*m_qf+4)>>3;    
  131.     m_cut_off_point*=m_qf;
  132.     m_coeff_count=0;
  133.     for (m_ypos=m_yp,m_pypos=m_pyp;m_ypos<m_yp+m_yl;++m_ypos,m_pypos=((m_ypos-m_yp)>>1)+m_pyp)
  134.     {
  135.         for (m_xpos=m_xp,m_pxpos=m_pxp;m_xpos<m_xp+m_xl;++m_xpos,m_pxpos=((m_xpos-m_xp)>>1)+m_pxp)
  136.         {
  137.             if (m_xpos==m_xp)
  138.                 m_nhood_sum = (m_ypos!=m_yp) ? std::abs(in_data[m_ypos-1][m_xpos]) : 0;
  139.             else
  140.                 m_nhood_sum = (m_ypos!=m_yp) ? 
  141.                 (std::abs(in_data[m_ypos-1][m_xpos]) + std::abs(in_data[m_ypos][m_xpos-1])) 
  142.                : std::abs(in_data[m_ypos][m_xpos-1]);
  143.                 
  144.             m_parent_notzero = static_cast<bool> ( in_data[m_pypos][m_pxpos] );
  145.             val = in_data[m_ypos][m_xpos];
  146.             in_data[m_ypos][m_xpos]=0;
  147.             CodeVal( in_data , val );
  148.         }//m_xpos
  149.     }//m_ypos    
  150. #if defined(VERBOSE_DEBUG)
  151.     // Show the symbol counts
  152.     cerr<<endl<<"Context counts";
  153.     
  154.     for (int c = 0; c < 16; ++c)
  155.          cerr << endl
  156.              << c
  157.              << ": Zero-"
  158.              << ContextList()[c].get_count0()
  159.              << ", One-"
  160.              << ContextList()[c].get_count1();
  161. #endif
  162. }
  163. void BandCodec::CodeVal( PicArray& in_data , const ValueType val )
  164. {
  165.     int abs_val( std::abs(val) );
  166.     abs_val *= m_qfinv;
  167.     abs_val >>= 17;
  168.     for ( int bin=1 ; bin<=abs_val ; ++bin )
  169.         EncodeSymbol( 0 , ChooseContext( in_data , bin ) );
  170.     
  171.     EncodeSymbol( 1 , ChooseContext( in_data , abs_val+1 ) );
  172.     if ( abs_val )
  173.     {
  174.         abs_val *= m_qf;
  175.         in_data[m_ypos][m_xpos] = static_cast<ValueType>( abs_val );                
  176.         
  177.         if ( val>0 )
  178.         {
  179.             EncodeSymbol( 1 , ChooseSignContext( in_data ) );
  180.             in_data[m_ypos][m_xpos] += m_offset;
  181.         }
  182.         else
  183.         {
  184.             EncodeSymbol( 0 , ChooseSignContext(in_data) );
  185.             in_data[m_ypos][m_xpos]  = -in_data[m_ypos][m_xpos];
  186.             in_data[m_ypos][m_xpos] -= m_offset;
  187.         }
  188.     }
  189.     
  190.     m_coeff_count++;
  191.     
  192.     if (m_coeff_count > m_reset_coeff_num)
  193.     {
  194.         m_coeff_count=0;
  195.         ResetAll();
  196.     }
  197. }
  198. void BandCodec::DoWorkDecode(PicArray& out_data, int num_bits)
  199. {
  200.     if (m_node.Parent()!=0)
  201.     {
  202.         m_pxp = m_pnode.Xp();
  203.         m_pyp = m_pnode.Yp();
  204.         m_pxl = m_pnode.Xl();
  205.         m_pyl = m_pnode.Yl();
  206.     }
  207.     else
  208.     {
  209.         m_pxp = 0;
  210.         m_pyp = 0;
  211.         m_pxl = 0;
  212.         m_pyl = 0;
  213.     }    
  214.     m_qf = m_node.Qf(0);
  215.     m_offset = (3 * m_qf + 4) >> 3;
  216.     m_cut_off_point *= m_qf;
  217.     //Work
  218.     m_coeff_count=0;
  219.     
  220.     for (m_ypos=m_yp,m_pypos=m_pyp;m_ypos<m_yp+m_yl;++m_ypos,m_pypos=((m_ypos-m_yp)>>1)+m_pyp)
  221.     {        
  222.         for (m_xpos = m_xp, m_pxpos = m_pxp; m_xpos < m_xp+m_xl; ++m_xpos, m_pxpos=((m_xpos-m_xp)>>1)+m_pxp)
  223.         {
  224.             if (m_xpos == m_xp)
  225.                 m_nhood_sum=(m_ypos!=m_yp) ? std::abs(out_data[m_ypos-1][m_xpos]): 0;
  226.             else
  227.                 m_nhood_sum=(m_ypos!=m_yp) ? 
  228.                 (std::abs(out_data[m_ypos-1][m_xpos]) + std::abs(out_data[m_ypos][m_xpos-1])) 
  229.               : std::abs(out_data[m_ypos][m_xpos-1]);
  230.             
  231.             m_parent_notzero = static_cast<bool>( out_data[m_pypos][m_pxpos] );            
  232.             DecodeVal(out_data);            
  233.         }//m_xpos
  234.     }//m_ypos
  235. }
  236. void BandCodec::DecodeVal(PicArray& out_data)
  237. {
  238.     ValueType val = 0;
  239.     bool bit;
  240.     int  bin = 1;
  241.     
  242.     do
  243.     {
  244.         DecodeSymbol(bit,ChooseContext(out_data,bin));
  245.         
  246.         if (!bit)
  247.             val++;
  248.         
  249.         bin++;
  250.     }
  251.     while (!bit);            
  252.     out_data[m_ypos][m_xpos] = val;
  253.     
  254.     if (out_data[m_ypos][m_xpos])
  255.     {
  256.         out_data[m_ypos][m_xpos] *= m_qf;
  257.         out_data[m_ypos][m_xpos] += m_offset;
  258.         DecodeSymbol( bit , ChooseSignContext(out_data) );
  259.     }
  260.     
  261.     if (!bit)
  262.         out_data[m_ypos][m_xpos]=-out_data[m_ypos][m_xpos];
  263.     m_coeff_count++;
  264.     
  265.     if (m_coeff_count>m_reset_coeff_num)
  266.     {
  267.         ResetAll();
  268.         m_coeff_count=0;
  269.     }
  270. }
  271. int BandCodec::ChooseContext(const PicArray& data, const int BinNumber) const
  272. {
  273.     //condition on neighbouring values and parent values
  274.     if (!m_parent_notzero && (m_pxp != 0 || m_pyp != 0))
  275.     {
  276.         if (BinNumber == 1)
  277.         {
  278.             if(m_nhood_sum == 0)
  279.                 return Z_BIN1z_CTX;
  280.             else
  281.                 return Z_BIN1nz_CTX;
  282.         }
  283.         else if(BinNumber == 2)
  284.             return Z_BIN2_CTX;
  285.         else if(BinNumber == 3)
  286.             return Z_BIN3_CTX;
  287.         else if(BinNumber == 4)
  288.             return Z_BIN4_CTX;
  289.         else
  290.             return Z_BIN5plus_CTX;
  291.     }
  292.     else
  293.     {
  294.         if (BinNumber == 1)
  295.         {
  296.             if(m_nhood_sum == 0)
  297.                 return NZ_BIN1z_CTX;
  298.             else if (m_nhood_sum>m_cut_off_point)
  299.                 return NZ_BIN1b_CTX;
  300.             else
  301.                 return NZ_BIN1a_CTX;
  302.         }
  303.         else if(BinNumber == 2)
  304.             return NZ_BIN2_CTX;
  305.         else if(BinNumber == 3)
  306.             return NZ_BIN3_CTX;
  307.         else if(BinNumber == 4)
  308.             return NZ_BIN4_CTX;
  309.         else
  310.             return NZ_BIN5plus_CTX;
  311.     }
  312. }
  313. int BandCodec::ChooseSignContext(const PicArray& data) const
  314. {    
  315.     if (m_yp == 0 && m_xp != 0)
  316.     {
  317.         //we're in a vertically oriented subband
  318.         if (m_ypos == 0)
  319.             return SIGN0_CTX;
  320.         else
  321.         {
  322.             if (data[m_ypos-1][m_xpos]>0)
  323.                 return SIGN_POS_CTX;        
  324.             else if (data[m_ypos-1][m_xpos]<0)
  325.                 return SIGN_NEG_CTX;
  326.             else
  327.                 return SIGN0_CTX;
  328.         }        
  329.     }
  330.     else if (m_xp == 0 && m_yp != 0)
  331.     {
  332.         //we're in a horizontally oriented subband
  333.         if (m_xpos == 0)
  334.             return SIGN0_CTX;
  335.         else
  336.         {
  337.             if ( data[m_ypos][m_xpos-1] > 0 )
  338.                 return SIGN_POS_CTX;                
  339.             else if ( data[m_ypos][m_xpos-1] < 0 )
  340.                 return SIGN_NEG_CTX;
  341.             else
  342.                 return SIGN0_CTX;
  343.         }
  344.     }
  345.     else
  346.         return SIGN0_CTX;
  347. }
  348. //////////////////////////////////////////////////////////////////////////////////
  349. //Now for special class for LF bands (since we don't want/can't refer to parent)//
  350. //////////////////////////////////////////////////////////////////////////////////
  351. void LFBandCodec::DoWorkCode(PicArray& in_data)
  352. {
  353.     //main coding function, using binarisation
  354.     m_pxp = 0;
  355.     m_pyp = 0;
  356.     m_parent_notzero = false; //set parent to always be zero
  357.     ValueType val;
  358.     m_qf     = m_node.Qf(0);
  359.     m_qfinv  = (1<<17)/m_qf;
  360.     m_offset = (3*m_qf+4)>>3;
  361.     m_cut_off_point*=m_qf;
  362.     m_coeff_count = 0;
  363.     
  364.     for ( m_ypos=m_yp ; m_ypos<m_yp+m_yl ; ++m_ypos )
  365.     {        
  366.         for ( m_xpos=m_xp ; m_xpos<m_xp+m_xl ; ++m_xpos )
  367.         {
  368.             if ( m_xpos == m_xp )
  369.                 m_nhood_sum = (m_ypos!=m_yp) ? std::abs(in_data[m_ypos-1][m_xpos]) : 0;
  370.             else
  371.                 m_nhood_sum = (m_ypos!=m_yp) ? 
  372.                 (std::abs(in_data[m_ypos-1][m_xpos]) + std::abs(in_data[m_ypos][m_xpos-1])) 
  373.                : std::abs(in_data[m_ypos][m_xpos-1]);    
  374.             
  375.             val = in_data[m_ypos][m_xpos];
  376.             in_data[m_ypos][m_xpos] = 0;
  377.             CodeVal(in_data,val);            
  378.         }//m_xpos
  379.     }//m_ypos    
  380. }
  381. void LFBandCodec::DoWorkDecode(PicArray& out_data, int num_bits)
  382. {
  383.     m_pxp = 0;
  384.     m_pyp = 0;
  385.     m_parent_notzero = false;//set parent to always be zero    
  386.     m_qf = m_node.Qf(0);
  387.     m_offset = (3*m_qf+4)>>3;
  388.     m_cut_off_point *= m_qf;
  389.     //Work
  390.     m_coeff_count = 0;
  391.     
  392.     for ( m_ypos=m_yp ; m_ypos<m_yp+m_yl ; ++m_ypos )
  393.     {
  394.         for ( m_xpos=0 ; m_xpos<m_xp+m_xl; ++m_xpos )
  395.         {
  396.             if ( m_xpos == m_xp )
  397.                 m_nhood_sum=(m_ypos!=m_yp) ? std::abs(out_data[m_ypos-1][m_xpos]) : 0;
  398.             else
  399.                 m_nhood_sum=(m_ypos!=m_yp) ? 
  400.                 (std::abs(out_data[m_ypos-1][m_xpos]) + std::abs(out_data[m_ypos][m_xpos-1])) 
  401.                : std::abs(out_data[m_ypos][m_xpos-1]);
  402.             DecodeVal(out_data);            
  403.         }//m_xpos
  404.     }//m_ypos
  405. }
  406. //////////////////////////////////////////////////////////////////////////////////
  407. //Finally,special class incorporating prediction for the DC band of intra frames//
  408. //////////////////////////////////////////////////////////////////////////////////
  409. void IntraDCBandCodec::DoWorkCode(PicArray& in_data)
  410. {
  411.     //main coding function, using binarisation
  412.     m_pxp = 0;
  413.     m_pyp = 0;
  414.     //set parent to always be zero
  415.     m_parent_notzero = false;
  416.     ValueType val;
  417.     
  418.     //residues after prediction, quantisation and inverse quant
  419.     PicArray pred_res(m_yl , m_xl);
  420.     ValueType prediction;
  421.     m_qf     = m_node.Qf(0);
  422.     m_qfinv  = (1<<17) / m_qf;
  423.     m_offset = (3*m_qf+4) >> 3;
  424.     m_cut_off_point *= m_qf;
  425.     m_coeff_count=0;
  426.     
  427.     for (m_ypos=m_yp; m_ypos < m_yp + m_yl; ++m_ypos)
  428.     {
  429.         for (m_xpos = m_xp; m_xpos < m_xp + m_xl; ++m_xpos)
  430.         {
  431.              if (m_xpos == m_xp)
  432.                 m_nhood_sum = (m_ypos!=m_yp) ? std::abs(pred_res[m_ypos-1][m_xpos]) : 0;
  433.              else
  434.                  m_nhood_sum = (m_ypos!=m_yp) ? 
  435.                                (std::abs(pred_res[m_ypos-1][m_xpos]) + std::abs(pred_res[m_ypos][m_xpos-1])) 
  436.                               : std::abs(pred_res[m_ypos][m_xpos-1]);
  437.           
  438.             prediction = GetPrediction(in_data);            
  439.             val = in_data[m_ypos][m_xpos]-prediction;
  440.             in_data[m_ypos][m_xpos] = 0;
  441.             CodeVal(in_data,val);            
  442.             pred_res[m_ypos][m_xpos] = in_data[m_ypos][m_xpos];
  443.             in_data[m_ypos][m_xpos] += prediction;
  444.         }//m_xpos
  445. #if defined(VERBOSE_DEBUG)
  446.          cerr << endl
  447.              << "Val at "
  448.              << m_ypos
  449.              << " "
  450.              << m_xl-1
  451.              << " : "
  452.              << in_data[m_ypos][m_xl-1]
  453.              << endl 
  454.              << "Contexts at "
  455.              << m_ypos 
  456.              << " " 
  457.              << m_xl-1 
  458.              << " : ";
  459.              
  460.          for (int c=0;c<18;++c)
  461.              cerr << endl
  462.                  << c 
  463.                  << ": Zero "
  464.                  << ContextList()[c].get_count0()
  465.                  << ", One "
  466.                  << ContextList()[c].get_count1();    
  467. #endif
  468.             
  469.     }//m_ypos    
  470. }
  471. void IntraDCBandCodec::DoWorkDecode(PicArray& out_data, int num_bits)
  472. {
  473.     m_pxp = 0;
  474.     m_pyp = 0;
  475.     m_parent_notzero = false; //set parent to always be zero
  476.     //residues after prediction, quantisation and inverse quant
  477.     PicArray pred_res(m_yl , m_xl); 
  478.     m_qf = m_node.Qf(0);
  479.     m_offset = (3*m_qf+4)>>3;
  480.     m_cut_off_point *= m_qf;
  481.     //Work
  482.     m_coeff_count=0;
  483.     
  484.     for (m_ypos=m_yp;m_ypos<m_yp+m_yl;++m_ypos)
  485.     {
  486.         for (m_xpos=0;m_xpos<m_xp+m_xl;++m_xpos)
  487.         {
  488.              if (m_xpos==m_xp)
  489.                  m_nhood_sum=(m_ypos!=m_yp) ? std::abs(pred_res[m_ypos - 1][m_xpos]) : 0;
  490.              else
  491.                  m_nhood_sum=(m_ypos!=m_yp) ? 
  492.                              (std::abs(pred_res[m_ypos - 1][m_xpos]) + std::abs(pred_res[m_ypos][m_xpos - 1]))
  493.                             : std::abs(pred_res[m_ypos][m_xpos-1]);
  494.           
  495.             DecodeVal(out_data);
  496.              pred_res[m_ypos][m_xpos]=out_data[m_ypos][m_xpos];
  497.             out_data[m_ypos][m_xpos]+=GetPrediction(out_data);
  498.         }//m_xpos
  499.     }//m_ypos
  500. }
  501. ValueType IntraDCBandCodec::GetPrediction(const PicArray& data) const
  502. {
  503.     if (m_ypos!=0)
  504.     {
  505.         if (m_xpos!=0)
  506.             return (data[m_ypos][m_xpos - 1] + data[m_ypos - 1][m_xpos - 1] + data[m_ypos - 1][m_xpos]) / 3;
  507.         else
  508.             return data[m_ypos - 1][0];
  509.     }
  510.     else
  511.     {
  512.         if(m_xpos!=0)
  513.             return data[0][m_xpos - 1];
  514.         else
  515.             return 2692; // TODO: What does this mean? Literal constants like this are dangerous!
  516.     }
  517. }