- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# 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 }