band_codec.cpp

00001 /* ***** BEGIN LICENSE BLOCK *****
00002 *
00003 * $Id: band_codec.cpp,v 1.5 2005/01/30 05:11:40 gabest Exp $ $Name:  $
00004 *
00005 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006 *
00007 * The contents of this file are subject to the Mozilla Public License
00008 * Version 1.1 (the "License"); you may not use this file except in compliance
00009 * with the License. You may obtain a copy of the License at
00010 * http://www.mozilla.org/MPL/
00011 *
00012 * Software distributed under the License is distributed on an "AS IS" basis,
00013 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
00014 * the specific language governing rights and limitations under the License.
00015 *
00016 * The Original Code is BBC Research and Development code.
00017 *
00018 * The Initial Developer of the Original Code is the British Broadcasting
00019 * Corporation.
00020 * Portions created by the Initial Developer are Copyright (c) 2004.
00021 * All Rights Reserved.
00022 *
00023 * Contributor(s): Thomas Davies (Original Author), Scott R Ladd
00024 *
00025 * Alternatively, the contents of this file may be used under the terms of
00026 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
00027 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
00028 * the GPL or the LGPL are applicable instead of those above. If you wish to
00029 * allow use of your version of this file only under the terms of the either
00030 * the GPL or LGPL and not to allow others to use your version of this file
00031 * under the MPL, indicate your decision by deleting the provisions above
00032 * and replace them with the notice and other provisions required by the GPL
00033 * or LGPL. If you do not delete the provisions above, a recipient may use
00034 * your version of this file under the terms of any one of the MPL, the GPL
00035 * or the LGPL.
00036 * ***** END LICENSE BLOCK ***** */
00037 
00038 #include <libdirac_common/band_codec.h>
00039 using namespace dirac;
00040 
00042 BandCodec::BandCodec(BasicOutputManager* bits_out,
00043                      size_t number_of_contexts,
00044                      const SubbandList & band_list,
00045                      int band_num):
00046     ArithCodec<PicArray>(bits_out,number_of_contexts),
00047     m_bnum(band_num),
00048     m_node(band_list(band_num)),
00049     m_xp(m_node.Xp()),
00050     m_yp(m_node.Yp()),
00051     m_xl(m_node.Xl()),
00052     m_yl(m_node.Yl()),
00053     m_vol(m_node.Xl()*m_node.Yl()),
00054     m_reset_coeff_num( std::max( 25 , std::min(m_vol/32,800) ) ),
00055     m_cut_off_point(m_node.Scale()>>1)
00056 {
00057     if (m_node.Parent()!=0) 
00058         m_pnode=band_list(m_node.Parent());
00059 }        
00060 
00062 BandCodec::BandCodec(BitInputManager* bits_in,
00063                      size_t number_of_contexts,
00064                      const SubbandList& band_list,
00065                      int band_num):
00066     ArithCodec<PicArray>(bits_in,number_of_contexts),
00067     m_bnum(band_num),
00068     m_node(band_list(band_num)),
00069     m_xp(m_node.Xp()),
00070     m_yp(m_node.Yp()),
00071     m_xl(m_node.Xl()),
00072     m_yl(m_node.Yl()),
00073     m_vol(m_node.Xl()*m_node.Yl()),
00074     m_reset_coeff_num( std::max( 25 , std::min(m_vol/32,800) ) ),
00075     m_cut_off_point(m_node.Scale()>>1)
00076 {
00077     if (m_node.Parent()!=0) m_pnode=band_list(m_node.Parent());
00078 }
00079 
00080 void BandCodec::InitContexts()
00081 {
00082     //initialises the contexts. 
00083     //If _list does not already have values, then they're set to default values. 
00084     //This way, the constructor can override default initialisation.
00085     Context tmp_ctx;
00086     
00087     for (size_t i=0; i<m_context_list.size(); ++i)
00088     {
00089         if (i>=m_context_list.size())
00090             m_context_list.push_back(tmp_ctx);
00091         else
00092         {
00093             if (m_context_list[i].Weight()==0)
00094                 m_context_list[i].SetCounts(1,1);
00095         }
00096     }
00097 }
00098 
00099 void BandCodec::ResetAll()
00100 {
00101     for (unsigned int c = 0; c < m_context_list.size(); ++c)
00102         if (m_context_list[c].Weight()>16)
00103             m_context_list[c].HalveCounts();
00104 }
00105 
00106 void BandCodec::Resize(const int context_num)
00107 {
00108     m_context_list[context_num].HalveCounts();
00109 }
00110 
00111 void BandCodec::Update( const bool symbol , const int context_num )
00112 {
00113     m_context_list[context_num].IncrCount(symbol,1);
00114     
00115     if ( m_context_list[context_num].Weight() >= 1024 )
00116         Resize( context_num );
00117 }
00118 
00119 int BandCodec::ChooseContext(const PicArray& data) const{ return NZ_BIN5plus_CTX; }
00120 
00121 //encoding function
00122 void BandCodec::DoWorkCode(PicArray& in_data)
00123 {
00124 
00125     //main coding function, using binarisation
00126     if (m_node.Parent()!=0)
00127     {
00128         m_pxp=m_pnode.Xp(); m_pyp=m_pnode.Yp();
00129         m_pxl=m_pnode.Xl(); m_pyl=m_pnode.Yl();
00130     }
00131     else
00132     {
00133         m_pxp=0; m_pyp=0;
00134         m_pxl=0; m_pyl=0;
00135     }
00136     
00137     ValueType val;
00138     m_qf=m_node.Qf(0);
00139     m_qfinv=(1<<17)/m_qf;
00140     m_offset=(3*m_qf+4)>>3;    
00141     m_cut_off_point*=m_qf;
00142 
00143     m_coeff_count=0;
00144 
00145     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)
00146     {
00147         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)
00148         {
00149             if (m_xpos==m_xp)
00150                 m_nhood_sum = (m_ypos!=m_yp) ? std::abs(in_data[m_ypos-1][m_xpos]) : 0;
00151             else
00152                 m_nhood_sum = (m_ypos!=m_yp) ? 
00153                 (std::abs(in_data[m_ypos-1][m_xpos]) + std::abs(in_data[m_ypos][m_xpos-1])) 
00154                : std::abs(in_data[m_ypos][m_xpos-1]);
00155                 
00156             m_parent_notzero = static_cast<bool> ( in_data[m_pypos][m_pxpos] );
00157             val = in_data[m_ypos][m_xpos];
00158             in_data[m_ypos][m_xpos]=0;
00159             CodeVal( in_data , val );
00160 
00161         }//m_xpos
00162     }//m_ypos    
00163 
00164 #if defined(VERBOSE_DEBUG)
00165     // Show the symbol counts
00166     cerr<<endl<<"Context counts";
00167     
00168     for (int c = 0; c < 16; ++c)
00169          cerr << endl
00170              << c
00171              << ": Zero-"
00172              << ContextList()[c].get_count0()
00173              << ", One-"
00174              << ContextList()[c].get_count1();
00175 #endif
00176 }
00177 
00178 void BandCodec::CodeVal( PicArray& in_data , const ValueType val )
00179 {
00180     int abs_val( std::abs(val) );
00181     abs_val *= m_qfinv;
00182     abs_val >>= 17;
00183 
00184     for ( int bin=1 ; bin<=abs_val ; ++bin )
00185         EncodeSymbol( 0 , ChooseContext( in_data , bin ) );
00186     
00187     EncodeSymbol( 1 , ChooseContext( in_data , abs_val+1 ) );
00188 
00189     if ( abs_val )
00190     {
00191         abs_val *= m_qf;
00192         in_data[m_ypos][m_xpos] = static_cast<ValueType>( abs_val );                
00193         
00194         if ( val>0 )
00195         {
00196             EncodeSymbol( 1 , ChooseSignContext( in_data ) );
00197             in_data[m_ypos][m_xpos] += m_offset;
00198         }
00199         else
00200         {
00201             EncodeSymbol( 0 , ChooseSignContext(in_data) );
00202             in_data[m_ypos][m_xpos]  = -in_data[m_ypos][m_xpos];
00203             in_data[m_ypos][m_xpos] -= m_offset;
00204         }
00205     }
00206     
00207     m_coeff_count++;
00208     
00209     if (m_coeff_count > m_reset_coeff_num)
00210     {
00211         m_coeff_count=0;
00212         ResetAll();
00213     }
00214 }
00215 
00216 void BandCodec::DoWorkDecode(PicArray& out_data, int num_bits)
00217 {
00218 
00219     if (m_node.Parent()!=0)
00220     {
00221         m_pxp = m_pnode.Xp();
00222         m_pyp = m_pnode.Yp();
00223         m_pxl = m_pnode.Xl();
00224         m_pyl = m_pnode.Yl();
00225     }
00226     else
00227     {
00228         m_pxp = 0;
00229         m_pyp = 0;
00230         m_pxl = 0;
00231         m_pyl = 0;
00232     }    
00233 
00234     m_qf = m_node.Qf(0);
00235     m_offset = (3 * m_qf + 4) >> 3;
00236     m_cut_off_point *= m_qf;
00237 
00238     //Work
00239     m_coeff_count=0;
00240     
00241     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)
00242     {        
00243         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)
00244         {
00245             if (m_xpos == m_xp)
00246                 m_nhood_sum=(m_ypos!=m_yp) ? std::abs(out_data[m_ypos-1][m_xpos]): 0;
00247             else
00248                 m_nhood_sum=(m_ypos!=m_yp) ? 
00249                 (std::abs(out_data[m_ypos-1][m_xpos]) + std::abs(out_data[m_ypos][m_xpos-1])) 
00250               : std::abs(out_data[m_ypos][m_xpos-1]);
00251             
00252             m_parent_notzero = static_cast<bool>( out_data[m_pypos][m_pxpos] );            
00253             DecodeVal(out_data);            
00254         }//m_xpos
00255     }//m_ypos
00256 }
00257 
00258 void BandCodec::DecodeVal(PicArray& out_data)
00259 {
00260     ValueType val = 0;
00261     bool bit;
00262     int  bin = 1;
00263     
00264     do
00265     {
00266         DecodeSymbol(bit,ChooseContext(out_data,bin));
00267         
00268         if (!bit)
00269             val++;
00270         
00271         bin++;
00272     }
00273     while (!bit);            
00274 
00275     out_data[m_ypos][m_xpos] = val;
00276     
00277     if (out_data[m_ypos][m_xpos])
00278     {
00279         out_data[m_ypos][m_xpos] *= m_qf;
00280         out_data[m_ypos][m_xpos] += m_offset;
00281         DecodeSymbol( bit , ChooseSignContext(out_data) );
00282     }
00283     
00284     if (!bit)
00285         out_data[m_ypos][m_xpos]=-out_data[m_ypos][m_xpos];
00286 
00287     m_coeff_count++;
00288     
00289     if (m_coeff_count>m_reset_coeff_num)
00290     {
00291         ResetAll();
00292         m_coeff_count=0;
00293     }
00294 }
00295 
00296 int BandCodec::ChooseContext(const PicArray& data, const int BinNumber) const
00297 {
00298     //condition on neighbouring values and parent values
00299     if (!m_parent_notzero && (m_pxp != 0 || m_pyp != 0))
00300     {
00301         if (BinNumber == 1)
00302         {
00303             if(m_nhood_sum == 0)
00304                 return Z_BIN1z_CTX;
00305             else
00306                 return Z_BIN1nz_CTX;
00307         }
00308         else if(BinNumber == 2)
00309             return Z_BIN2_CTX;
00310         else if(BinNumber == 3)
00311             return Z_BIN3_CTX;
00312         else if(BinNumber == 4)
00313             return Z_BIN4_CTX;
00314         else
00315             return Z_BIN5plus_CTX;
00316     }
00317     else
00318     {
00319         if (BinNumber == 1)
00320         {
00321             if(m_nhood_sum == 0)
00322                 return NZ_BIN1z_CTX;
00323             else if (m_nhood_sum>m_cut_off_point)
00324                 return NZ_BIN1b_CTX;
00325             else
00326                 return NZ_BIN1a_CTX;
00327         }
00328         else if(BinNumber == 2)
00329             return NZ_BIN2_CTX;
00330         else if(BinNumber == 3)
00331             return NZ_BIN3_CTX;
00332         else if(BinNumber == 4)
00333             return NZ_BIN4_CTX;
00334         else
00335             return NZ_BIN5plus_CTX;
00336     }
00337 }
00338 
00339 int BandCodec::ChooseSignContext(const PicArray& data) const
00340 {    
00341     if (m_yp == 0 && m_xp != 0)
00342     {
00343         //we're in a vertically oriented subband
00344         if (m_ypos == 0)
00345             return SIGN0_CTX;
00346         else
00347         {
00348             if (data[m_ypos-1][m_xpos]>0)
00349                 return SIGN_POS_CTX;        
00350             else if (data[m_ypos-1][m_xpos]<0)
00351                 return SIGN_NEG_CTX;
00352             else
00353                 return SIGN0_CTX;
00354         }        
00355     }
00356     else if (m_xp == 0 && m_yp != 0)
00357     {
00358         //we're in a horizontally oriented subband
00359         if (m_xpos == 0)
00360             return SIGN0_CTX;
00361         else
00362         {
00363             if ( data[m_ypos][m_xpos-1] > 0 )
00364                 return SIGN_POS_CTX;                
00365             else if ( data[m_ypos][m_xpos-1] < 0 )
00366                 return SIGN_NEG_CTX;
00367             else
00368                 return SIGN0_CTX;
00369         }
00370     }
00371     else
00372         return SIGN0_CTX;
00373 }
00374 
00376 //Now for special class for LF bands (since we don't want/can't refer to parent)//
00378 
00379 void LFBandCodec::DoWorkCode(PicArray& in_data)
00380 {
00381     //main coding function, using binarisation
00382     m_pxp = 0;
00383     m_pyp = 0;
00384     m_parent_notzero = false; //set parent to always be zero
00385     ValueType val;
00386 
00387     m_qf     = m_node.Qf(0);
00388     m_qfinv  = (1<<17)/m_qf;
00389     m_offset = (3*m_qf+4)>>3;
00390     m_cut_off_point*=m_qf;
00391 
00392     m_coeff_count = 0;
00393     
00394     for ( m_ypos=m_yp ; m_ypos<m_yp+m_yl ; ++m_ypos )
00395     {        
00396         for ( m_xpos=m_xp ; m_xpos<m_xp+m_xl ; ++m_xpos )
00397         {
00398             if ( m_xpos == m_xp )
00399                 m_nhood_sum = (m_ypos!=m_yp) ? std::abs(in_data[m_ypos-1][m_xpos]) : 0;
00400             else
00401                 m_nhood_sum = (m_ypos!=m_yp) ? 
00402                 (std::abs(in_data[m_ypos-1][m_xpos]) + std::abs(in_data[m_ypos][m_xpos-1])) 
00403                : std::abs(in_data[m_ypos][m_xpos-1]);    
00404             
00405             val = in_data[m_ypos][m_xpos];
00406             in_data[m_ypos][m_xpos] = 0;
00407             CodeVal(in_data,val);            
00408         }//m_xpos
00409     }//m_ypos    
00410 }
00411 
00412 void LFBandCodec::DoWorkDecode(PicArray& out_data, int num_bits)
00413 {
00414     m_pxp = 0;
00415     m_pyp = 0;
00416     m_parent_notzero = false;//set parent to always be zero    
00417     m_qf = m_node.Qf(0);
00418     m_offset = (3*m_qf+4)>>3;
00419     m_cut_off_point *= m_qf;
00420 
00421     //Work
00422     m_coeff_count = 0;
00423     
00424     for ( m_ypos=m_yp ; m_ypos<m_yp+m_yl ; ++m_ypos )
00425     {
00426         for ( m_xpos=0 ; m_xpos<m_xp+m_xl; ++m_xpos )
00427         {
00428             if ( m_xpos == m_xp )
00429                 m_nhood_sum=(m_ypos!=m_yp) ? std::abs(out_data[m_ypos-1][m_xpos]) : 0;
00430             else
00431                 m_nhood_sum=(m_ypos!=m_yp) ? 
00432                 (std::abs(out_data[m_ypos-1][m_xpos]) + std::abs(out_data[m_ypos][m_xpos-1])) 
00433                : std::abs(out_data[m_ypos][m_xpos-1]);
00434 
00435             DecodeVal(out_data);            
00436         }//m_xpos
00437     }//m_ypos
00438 }
00439 
00441 //Finally,special class incorporating prediction for the DC band of intra frames//
00443 
00444 void IntraDCBandCodec::DoWorkCode(PicArray& in_data)
00445 {
00446     //main coding function, using binarisation
00447     m_pxp = 0;
00448     m_pyp = 0;
00449 
00450     //set parent to always be zero
00451     m_parent_notzero = false;
00452     ValueType val;
00453     
00454     //residues after prediction, quantisation and inverse quant
00455     PicArray pred_res(m_yl , m_xl);
00456     ValueType prediction;
00457 
00458     m_qf     = m_node.Qf(0);
00459     m_qfinv  = (1<<17) / m_qf;
00460     m_offset = (3*m_qf+4) >> 3;
00461     m_cut_off_point *= m_qf;
00462 
00463     m_coeff_count=0;
00464     
00465     for (m_ypos=m_yp; m_ypos < m_yp + m_yl; ++m_ypos)
00466     {
00467         for (m_xpos = m_xp; m_xpos < m_xp + m_xl; ++m_xpos)
00468         {
00469              if (m_xpos == m_xp)
00470                 m_nhood_sum = (m_ypos!=m_yp) ? std::abs(pred_res[m_ypos-1][m_xpos]) : 0;
00471              else
00472                  m_nhood_sum = (m_ypos!=m_yp) ? 
00473                                (std::abs(pred_res[m_ypos-1][m_xpos]) + std::abs(pred_res[m_ypos][m_xpos-1])) 
00474                               : std::abs(pred_res[m_ypos][m_xpos-1]);
00475           
00476             prediction = GetPrediction(in_data);            
00477             val = in_data[m_ypos][m_xpos]-prediction;
00478             in_data[m_ypos][m_xpos] = 0;
00479             CodeVal(in_data,val);            
00480             pred_res[m_ypos][m_xpos] = in_data[m_ypos][m_xpos];
00481             in_data[m_ypos][m_xpos] += prediction;
00482         }//m_xpos
00483 
00484 #if defined(VERBOSE_DEBUG)
00485          cerr << endl
00486              << "Val at "
00487              << m_ypos
00488              << " "
00489              << m_xl-1
00490              << " : "
00491              << in_data[m_ypos][m_xl-1]
00492              << endl 
00493              << "Contexts at "
00494              << m_ypos 
00495              << " " 
00496              << m_xl-1 
00497              << " : ";
00498              
00499          for (int c=0;c<18;++c)
00500              cerr << endl
00501                  << c 
00502                  << ": Zero "
00503                  << ContextList()[c].get_count0()
00504                  << ", One "
00505                  << ContextList()[c].get_count1();    
00506 #endif
00507             
00508     }//m_ypos    
00509 }
00510 
00511 void IntraDCBandCodec::DoWorkDecode(PicArray& out_data, int num_bits)
00512 {
00513     m_pxp = 0;
00514     m_pyp = 0;
00515     m_parent_notzero = false; //set parent to always be zero
00516 
00517     //residues after prediction, quantisation and inverse quant
00518     PicArray pred_res(m_yl , m_xl); 
00519 
00520     m_qf = m_node.Qf(0);
00521     m_offset = (3*m_qf+4)>>3;
00522     m_cut_off_point *= m_qf;
00523 
00524     //Work
00525     m_coeff_count=0;
00526     
00527     for (m_ypos=m_yp;m_ypos<m_yp+m_yl;++m_ypos)
00528     {
00529         for (m_xpos=0;m_xpos<m_xp+m_xl;++m_xpos)
00530         {
00531              if (m_xpos==m_xp)
00532                  m_nhood_sum=(m_ypos!=m_yp) ? std::abs(pred_res[m_ypos - 1][m_xpos]) : 0;
00533              else
00534                  m_nhood_sum=(m_ypos!=m_yp) ? 
00535                              (std::abs(pred_res[m_ypos - 1][m_xpos]) + std::abs(pred_res[m_ypos][m_xpos - 1]))
00536                             : std::abs(pred_res[m_ypos][m_xpos-1]);
00537           
00538             DecodeVal(out_data);
00539              pred_res[m_ypos][m_xpos]=out_data[m_ypos][m_xpos];
00540             out_data[m_ypos][m_xpos]+=GetPrediction(out_data);
00541         }//m_xpos
00542     }//m_ypos
00543 }
00544 
00545 ValueType IntraDCBandCodec::GetPrediction(const PicArray& data) const
00546 {
00547     if (m_ypos!=0)
00548     {
00549         if (m_xpos!=0)
00550             return (data[m_ypos][m_xpos - 1] + data[m_ypos - 1][m_xpos - 1] + data[m_ypos - 1][m_xpos]) / 3;
00551         else
00552             return data[m_ypos - 1][0];
00553     }
00554     else
00555     {
00556         if(m_xpos!=0)
00557             return data[0][m_xpos - 1];
00558         else
00559             return 2692; // TODO: What does this mean? Literal constants like this are dangerous!
00560     }
00561 }

Generated on Tue Dec 13 14:47:12 2005 for guliverkli by  doxygen 1.4.5