- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# me_mode_decn.cpp

    00001 /* ***** BEGIN LICENSE BLOCK *****
    00002 *
    00003 * $Id: me_mode_decn.cpp,v 1.2 2005/01/30 05:11:42 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)
    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_motionest/me_mode_decn.h>
    00039 #include <libdirac_common/frame_buffer.h>
    00040 using namespace dirac;
    00041
    00042 #include <algorithm>
    00043
    00044 using std::vector;
    00045
    00046 ModeDecider::ModeDecider( const EncoderParams& encp):
    00047     m_encparams( encp ),
    00048     m_level_factor(3),
    00049     m_mode_factor(3),
    00050     m_me_data_set(3)
    00051 {
    00052
    00053     // The following factors normalise costs for sub-MBs and MBs to those of
    00054     // blocks, so that the overlap is take into account (e.g. a sub-MB has
    00055     // length XBLEN+XBSEP and YBLEN+YBSEP). The MB costs for a 1x1
    00056     // decomposition are not directly comprable to those for other decompositions
    00057     // because of the block overlaps. These factors remove these effects, so that
    00058     // all SAD costs are normalised to the area corresponding to non-overlapping
    00059     // 16 blocks of size XBLEN*YBLEN.
    00060
    00061    m_level_factor[0] = float( 16 * m_encparams.LumaBParams(2).Xblen() * m_encparams.LumaBParams(2).Yblen() )/
    00062        float( m_encparams.LumaBParams(0).Xblen() * m_encparams.LumaBParams(0).Yblen() );
    00063
    00064    m_level_factor[1] = float( 4 * m_encparams.LumaBParams(2).Xblen() * m_encparams.LumaBParams(2).Yblen() )/
    00065        float( m_encparams.LumaBParams(1).Xblen() * m_encparams.LumaBParams(1).Yblen() );
    00066
    00067    m_level_factor[2] = 1.0f;
    00068
    00069     for (int i=0 ; i<=2 ; ++i)
    00070         m_mode_factor[i] = 160.0*std::pow(0.8 , 2-i);
    00071 }
    00072
    00073
    00074 ModeDecider::~ModeDecider()
    00075 {
    00076     if (fsort != I_frame)
    00077     {
    00078         delete m_me_data_set[0];
    00079         delete m_me_data_set[1];
    00080     }
    00081 }
    00082
    00083 void ModeDecider::DoModeDecn(const FrameBuffer& my_buffer, int frame_num, MEData& me_data)
    00084 {
    00085
    00086      // We've got 'raw' block motion vectors for up to two reference frames. Now we want
    00087      // to make a decision as to mode. In this initial implementation, this is bottom-up
    00088     // i.e. find mvs for MBs and sub-MBs and see whether it's worthwhile merging.
    00089
    00090     int ref1,ref2;
    00091
    00092     // Initialise //
    00094
    00095     fsort = my_buffer.GetFrame(frame_num).GetFparams().FSort();
    00096     if (fsort != I_frame)
    00097     {
    00098         // Extract the references
    00099         const vector<int>& refs = my_buffer.GetFrame(frame_num).GetFparams().Refs();
    00100         num_refs = refs.size();
    00101         ref1 = refs[0];
    00102
    00103         // The picture we're doing estimation from
    00104         m_pic_data = &(my_buffer.GetComponent( frame_num , Y_COMP));
    00105
    00106         // Set up the hierarchy of motion vector data objects
    00107         m_me_data_set[0] = new MEData( m_encparams.XNumMB() , m_encparams.YNumMB() ,
    00108                                        m_encparams.XNumBlocks()/4 , m_encparams.YNumBlocks()/4 );
    00109         m_me_data_set[1] = new MEData( m_encparams.XNumMB() , m_encparams.YNumMB() ,
    00110                                        m_encparams.XNumBlocks()/2 , m_encparams.YNumBlocks()/2 );
    00111
    00112         m_me_data_set[2] = &me_data;
    00113
    00114         // Set up the lambdas to use per block
    00115         m_me_data_set[0]->SetLambdaMap( 0 , me_data.LambdaMap() , 1.0/m_level_factor[0] );
    00116         m_me_data_set[1]->SetLambdaMap( 1 , me_data.LambdaMap() , 1.0/m_level_factor[1] );
    00117
    00118         // Set up the reference pictures
    00119         m_ref1_updata = &(my_buffer.GetUpComponent( ref1 , Y_COMP));
    00120
    00121         if (num_refs>1)
    00122         {
    00123             ref2 = refs[1];
    00124             m_ref2_updata = &(my_buffer.GetUpComponent( ref2 , Y_COMP));
    00125             // Create an object for computing bi-directional prediction calculations
    00126             m_bicheckdiff = new BiBChkBlockDiffUp( *m_ref1_updata ,
    00127                                                  *m_ref2_updata ,
    00128                                                  *m_pic_data );
    00129         }
    00130         else
    00131         {
    00132             ref2 = ref1;
    00133         }
    00134
    00135
    00136         // Create an object for doing intra calculations
    00137         m_intradiff = new IntraBlockDiff( *m_pic_data );
    00138
    00139         // Loop over all the macroblocks, doing the work //
    00141
    00142         for (m_ymb_loc=0 ; m_ymb_loc<m_encparams.YNumMB() ; ++m_ymb_loc )
    00143         {
    00144             for (m_xmb_loc=0 ; m_xmb_loc<m_encparams.XNumMB(); ++m_xmb_loc )
    00145             {
    00146                 DoMBDecn();
    00147             }//m_xmb_loc
    00148         }//m_ymb_loc
    00149
    00150         delete m_intradiff;
    00151         if (num_refs>1)
    00152             delete m_bicheckdiff;
    00153     }
    00154 }
    00155
    00156 void ModeDecider::DoMBDecn()
    00157 {
    00158       // Does the mode decision for the given MB, in three stages
    00159
    00160     // Start with 4x4 modes
    00161     DoLevelDecn(2);
    00162     float old_best_MB_cost = m_me_data_set[2]->MBCosts()[m_ymb_loc][m_xmb_loc];
    00163
    00164     // Next do 2x2 modes
    00165     DoLevelDecn(1);
    00166
    00167     // Do 1x1 mode if merging worked before
    00168     if ( m_me_data_set[2]->MBCosts()[m_ymb_loc][m_xmb_loc] <= old_best_MB_cost)
    00169     {
    00170         old_best_MB_cost = m_me_data_set[2]->MBCosts()[m_ymb_loc][m_xmb_loc];
    00171         DoLevelDecn(0);
    00172     }
    00173
    00174 }
    00175
    00176 void ModeDecider::DoLevelDecn( int level )
    00177 {
    00178     // Computes the best costs if we were to
    00179     // stick to a decomposition at this level
    00180
    00181     // Looks at two cases: the prediction mode is
    00182     // constant across the MB; and the pred mode
    00183     // for each constituent is different.
    00184
    00185     // The limits of the prediction units
    00186     const int xstart = m_xmb_loc <<level;
    00187     const int ystart = m_ymb_loc <<level;
    00188
    00189     const int xend = xstart + (1<<level);
    00190     const int yend = ystart + (1<<level);
    00191
    00192     //    Case 1: prediction modes are all different
    00193
    00194     float MB_cost = 0.0;
    00195     for ( int j=ystart ; j<yend ; ++j)
    00196     {
    00197         for (int i=xstart ; i<xend ; ++i)
    00198        {
    00199            if ( level<2 )
    00200                DoME( i , j , level);
    00201             MB_cost += DoUnitDecn( i , j ,level );
    00202
    00203         }// i
    00204     }// j
    00205
    00206     // if we've improved on the best cost, we should propagate data in
    00207     // the base level motion vector set
    00208     if (level == 2)
    00209     {
    00210         m_me_data_set[2]->MBSplit()[m_ymb_loc][m_xmb_loc] = 2;
    00211         m_me_data_set[2]->MBCommonMode()[m_ymb_loc][m_xmb_loc] = false;
    00212         m_me_data_set[2]->MBCosts()[m_ymb_loc][m_xmb_loc] = MB_cost;
    00213     }
    00214
    00215     if ( level<2 && MB_cost <= m_me_data_set[2]->MBCosts()[m_ymb_loc][m_xmb_loc] )
    00216     {
    00217         m_me_data_set[2]->MBCosts()[m_ymb_loc][m_xmb_loc] = MB_cost;
    00218         m_me_data_set[2]->MBSplit()[m_ymb_loc][m_xmb_loc] = level;
    00219         m_me_data_set[2]->MBCommonMode()[m_ymb_loc][m_xmb_loc] = false;
    00220
    00221         // Parameters of the base-level blocks corresponding to each
    00222         // prediction unit
    00223         int xblock_start;
    00224         int yblock_start;
    00225         int xblock_end;
    00226         int yblock_end;
    00227
    00228         for ( int j=ystart ; j<yend ; ++j )
    00229         {
    00230             yblock_start = j<<(2-level);
    00231             yblock_end = (j+1)<<(2-level);
    00232             for ( int i=xstart ; i<xend ; ++i )
    00233             {
    00234                 xblock_start = i<<(2-level);
    00235                 xblock_end = (i+1)<<(2-level);
    00236
    00237                 for ( int v=yblock_start ; v<yblock_end ; ++v )
    00238                 {
    00239                     for ( int u=xblock_start ; u<xblock_end ; ++u )
    00240                     {
    00241                         m_me_data_set[2]->Mode()[v][u] = m_me_data_set[level]->Mode()[j][i];
    00242                         m_me_data_set[2]->DC( Y_COMP )[v][u] = m_me_data_set[level]->DC( Y_COMP )[j][i];
    00243                         m_me_data_set[2]->Vectors(1)[v][u] = m_me_data_set[level]->Vectors(1)[j][i];
    00244                         if ( num_refs>1 )
    00245                             m_me_data_set[2]->Vectors(2)[v][u] = m_me_data_set[level]->Vectors(2)[j][i];
    00246
    00247                     }// u
    00248                 }// v
    00249
    00250             }// i
    00251         }// j
    00252
    00253     }
    00254
    00255     //     Case 2: prediction modes are all the same
    00256
    00257     PredMode predmode;
    00258
    00259     MB_cost = DoCommonMode( predmode , level );
    00260
    00261     if ( MB_cost <= m_me_data_set[2]->MBCosts()[m_ymb_loc][m_xmb_loc] )
    00262     {
    00263         m_me_data_set[2]->MBCosts()[m_ymb_loc][m_xmb_loc] = MB_cost;
    00264         m_me_data_set[2]->MBSplit()[m_ymb_loc][m_xmb_loc] = level;
    00265         m_me_data_set[2]->MBCommonMode()[m_ymb_loc][m_xmb_loc] = true;
    00266         // Parameters of the base-level blocks corresponding to each
    00267         // prediction unit
    00268         int xblock_start;
    00269         int yblock_start;
    00270         int xblock_end;
    00271         int yblock_end;
    00272
    00273         for ( int j=ystart ; j<yend ; ++j )
    00274         {
    00275             yblock_start = j<<(2-level);
    00276             yblock_end = (j+1)<<(2-level);
    00277             for ( int i=xstart ; i<xend ; ++i )
    00278             {
    00279                 xblock_start = i<<(2-level);
    00280                 xblock_end = (i+1)<<(2-level);
    00281                 for ( int v=yblock_start ; v<yblock_end ; ++v )
    00282                 {
    00283                     for ( int u=xblock_start ; u<xblock_end ; ++u )
    00284                     {
    00285                         m_me_data_set[2]->Vectors(1)[v][u] = m_me_data_set[level]->Vectors(1)[j][i];
    00286                         m_me_data_set[2]->Mode()[v][u] = predmode;
    00287                         m_me_data_set[2]->DC( Y_COMP )[v][u] = m_me_data_set[level]->DC( Y_COMP )[j][i];
    00288                         if ( num_refs>1 )
    00289                             m_me_data_set[2]->Vectors(2)[v][u] = m_me_data_set[level]->Vectors(2)[j][i];
    00290
    00291                     }// u
    00292                 }// v
    00293
    00294             }// i
    00295         }// j
    00296       }
    00297
    00298 }
    00299
    00300
    00301 void ModeDecider::DoME(const int xpos , const int ypos , const int level)
    00302 {
    00303     // Do motion estimation for a prediction unit using the
    00304     // four vectors derived from the next level as a guide
    00305
    00306     MEData& me_data = *(m_me_data_set[level]);
    00307     const MEData& guide_data = *(m_me_data_set[level+1]);
    00308
    00309     // The corresponding location of the guide data
    00310     const int guide_xpos = xpos<<1;
    00311     const int guide_ypos = ypos<<1;
    00312
    00313     // The location of the lowest level vectors
    00314     const int xblock = xpos << ( 2 - level);
    00315     const int yblock = ypos << ( 2 - level);
    00316
    00317     // The list of potential candidate vectors
    00318     CandidateList cand_list;
    00319
    00320     // The lambda to use for motion estimation
    00321     const float lambda = me_data.LambdaMap()[ypos][xpos];
    00322
    00323     // The predicting motion vector
    00324     MVector mv_pred;
    00325
    00326     for ( int j=0 ; j<2 ; ++j )
    00327         for (int i=0 ; i<2 ; ++i )
    00328             AddNewVlist( cand_list , guide_data.Vectors(1)[guide_ypos+j][guide_xpos+i] , 1 , 1 );
    00329
    00330     if (xblock>0 && yblock>0)
    00331         mv_pred = MvMedian( m_me_data_set[2]->Vectors(1)[yblock][xblock-1] ,
    00332                             m_me_data_set[2]->Vectors(1)[yblock-1][xblock-1],
    00333                               m_me_data_set[2]->Vectors(1)[yblock-1][xblock]);
    00334     else if (xblock==0 && yblock>0)
    00335         mv_pred = MvMean( m_me_data_set[2]->Vectors(1)[yblock-1][xblock],
    00336                           m_me_data_set[2]->Vectors(1)[yblock-1][xblock+1]);
    00337     else if (xblock>0 && yblock==0)
    00338         mv_pred = MvMean( m_me_data_set[2]->Vectors(1)[yblock][xblock-1],
    00339                           m_me_data_set[2]->Vectors(1)[yblock+1][xblock-1]);
    00340     else{
    00341         mv_pred.x = 0;
    00342         mv_pred.y = 0;
    00343     }
    00344
    00345     BlockMatcher my_bmatch1( *m_pic_data , *m_ref1_updata , m_encparams.LumaBParams(level) ,
    00346                                                      me_data.Vectors(1) , me_data.PredCosts(1) );
    00347     me_data.PredCosts(1)[ypos][xpos].total = 100000000.0f;
    00348     my_bmatch1.FindBestMatchSubp( xpos , ypos , cand_list, mv_pred, lambda );
    00349
    00350     if (num_refs>1)
    00351     {//do the same for the other reference
    00352
    00353         cand_list.clear();
    00354
    00355         for ( int j=0 ; j<2 ; ++j )
    00356         {
    00357             for (int i=0 ; i<2 ; ++i )
    00358             {
    00359                 AddNewVlist( cand_list , guide_data.Vectors(2)[guide_ypos+j][guide_xpos+i] , 1 , 1 );
    00360             }// i
    00361         }// j
    00362
    00363         if (xblock>0 && yblock>0)
    00364             mv_pred = MvMedian( m_me_data_set[2]->Vectors(2)[yblock][xblock-1] ,
    00365                                              m_me_data_set[2]->Vectors(2)[yblock-1][xblock-1],
    00366                                                m_me_data_set[2]->Vectors(2)[yblock-1][xblock]);
    00367         else if (xblock==0 && yblock>0)
    00368             mv_pred = MvMean( m_me_data_set[2]->Vectors(2)[yblock-1][xblock],
    00369                                            m_me_data_set[2]->Vectors(2)[yblock-1][xblock+1]);
    00370         else if (xblock>0 && yblock==0)
    00371             mv_pred = MvMean( m_me_data_set[2]->Vectors(2)[yblock][xblock-1],
    00372                                            m_me_data_set[2]->Vectors(2)[yblock+1][xblock-1]);
    00373         else{
    00374              mv_pred.x = 0;
    00375              mv_pred.y = 0;
    00376         }
    00377
    00378         BlockMatcher my_bmatch2( *m_pic_data , *m_ref2_updata , m_encparams.LumaBParams(level) ,
    00379                                                      me_data.Vectors(2) , me_data.PredCosts(2) );
    00380         me_data.PredCosts(2)[ypos][xpos].total = 100000000.0f;
    00381         my_bmatch2.FindBestMatchSubp( xpos , ypos , cand_list, mv_pred, lambda );
    00382
    00383      }
    00384 }
    00385
    00386
    00387
    00388 float ModeDecider::DoUnitDecn(const int xpos , const int ypos , const int level )
    00389 {
    00390     // For a given prediction unit (MB, subMB or block) find the best
    00391     // mode, given that the REF1 and REF2 motion estimation has
    00392     // already been done.
    00393
    00394     MEData& me_data = *( m_me_data_set[level] );
    00395
    00396     // Coords of the top-leftmost block belonging to this unit
    00397     const int xblock = xpos<<(2-level);
    00398     const int yblock = ypos<<(2-level);
    00399
    00400     const float loc_lambda = me_data.LambdaMap()[ypos][xpos];
    00401
    00402     float unit_cost;
    00403     float mode_cost;
    00404     float min_unit_cost;
    00405
    00406     BlockDiffParams dparams;
    00407
    00408     dparams.SetBlockLimits( m_encparams.LumaBParams( level ) , *m_pic_data, xpos , ypos);
    00409
    00410      // First check REF1 costs //
    00411     /**************************/
    00412
    00413     mode_cost = ModeCost( xblock , yblock , REF1_ONLY)*m_mode_factor[level];
    00414     me_data.Mode()[ypos][xpos] = REF1_ONLY;
    00415     me_data.PredCosts(1)[ypos][xpos].total *= m_level_factor[level];
    00416     min_unit_cost = me_data.PredCosts(1)[ypos][xpos].total + mode_cost;
    00417
    00418     // Calculate the cost if we were to code the block as intra //
    00419     /************************************************************/
    00420
    00421     mode_cost = ModeCost( xblock , yblock , INTRA) * m_mode_factor[level];
    00422     me_data.IntraCosts()[ypos][xpos] = m_intradiff->Diff( dparams , me_data.DC( Y_COMP )[ypos][xpos] );
    00423     me_data.IntraCosts()[ypos][xpos] += loc_lambda *
    00424                                        GetDCVar( me_data.DC( Y_COMP )[ypos][xpos] , GetDCPred( xblock , yblock ) );
    00425     me_data.IntraCosts()[ypos][xpos] *= m_level_factor[level];
    00426     unit_cost = me_data.IntraCosts()[ypos][xpos] +  mode_cost;
    00427
    00428     if ( unit_cost<min_unit_cost )
    00429     {
    00430         me_data.Mode()[ypos][xpos] = INTRA;
    00431         min_unit_cost = unit_cost;
    00432     }
    00433
    00434     if (num_refs>1)
    00435     {
    00436        // Next check REF2 costs //
    00437        /*************************/
    00438
    00439         mode_cost = ModeCost( xblock , yblock , REF2_ONLY)*m_mode_factor[level];
    00440         me_data.PredCosts(2)[ypos][xpos].total *= m_level_factor[level];
    00441         unit_cost = me_data.PredCosts(2)[ypos][xpos].total + mode_cost;
    00442         if ( unit_cost<min_unit_cost )
    00443         {
    00444             me_data.Mode()[ypos][xpos] = REF2_ONLY;
    00445             min_unit_cost = unit_cost;
    00446         }
    00447
    00448         // Finally, calculate the cost if we were to use bi-predictions //
    00449         /****************************************************************/
    00450 /*
    00451         mode_cost = ModeCost( xpos , ypos , REF1AND2 )*m_mode_factor[level];
    00452
    00453         me_data.BiPredCosts()[ypos][xpos].mvcost =
    00454                                        me_data.PredCosts(1)[ypos][xpos].mvcost+
    00455                                        me_data.PredCosts(2)[ypos][xpos].mvcost;
    00456
    00457         me_data.BiPredCosts()[ypos][xpos].SAD = m_bicheckdiff->Diff(dparams ,
    00458                                                   me_data.Vectors(1)[ypos][xpos] ,
    00459                                                   me_data.Vectors(2)[ypos][xpos] );
    00460
    00461         me_data.BiPredCosts()[ypos][xpos].SetTotal( loc_lambda );
    00462
    00463         me_data.BiPredCosts()[ypos][xpos].total *= m_level_factor[level];
    00464         unit_cost = me_data.BiPredCosts()[ypos][xpos].total + mode_cost;
    00465
    00466         if ( unit_cost<min_unit_cost )
    00467         {
    00468             me_data.Mode()[ypos][xpos] = REF1AND2;
    00469             min_unit_cost = unit_cost;
    00470         }
    00471 */
    00472     }
    00473
    00474     return min_unit_cost;
    00475 }
    00476
    00477 float ModeDecider::DoCommonMode( PredMode& predmode , const int level)
    00478 {
    00479     // For a given level, examine the costs in the constituent
    00480     // prediction units of the MB at that level and decide
    00481     // whether there should be a common prediction mode or not.
    00482
    00483     const MEData& me_data = *( m_me_data_set[level] );
    00484
    00485     // The total cost for the MB for each possible prediction mode
    00486     OneDArray<float> MB_cost(4);
    00487     for ( int i=0 ; i<4 ; ++i)
    00488         MB_cost[i] = ModeCost( m_xmb_loc<<2 , m_ymb_loc , PredMode(i) )*m_mode_factor[0];
    00489
    00490     // The limits of the prediction units
    00491     const int xstart = m_xmb_loc <<level;
    00492     const int ystart = m_ymb_loc <<level;
    00493
    00494     const int xend = xstart + (1<<level);
    00495     const int yend = ystart + (1<<level);
    00496
    00497     for (int j=ystart ; j<yend ; ++j)
    00498     {
    00499         for (int i=xstart ; i<xend ; ++i)
    00500         {
    00501             MB_cost[INTRA] += me_data.IntraCosts()[j][i];
    00502             MB_cost[REF1_ONLY] += me_data.PredCosts(1)[j][i].total;
    00503             if ( num_refs>1 )
    00504             {
    00505                 MB_cost[REF2_ONLY] += me_data.PredCosts(2)[j][i].total;
    00506 //                MB_cost[REF1AND2] += me_data.BiPredCosts()[j][i].total;
    00507             }
    00508         }// i
    00509     }// i
    00510
    00511
    00512     // Find the minimum
    00513     predmode = INTRA;
    00514     if ( MB_cost[REF1_ONLY]<MB_cost[predmode] )
    00515         predmode = REF1_ONLY;
    00516
    00517     if ( num_refs>1)
    00518     {
    00519         if ( MB_cost[REF2_ONLY]<MB_cost[predmode] )
    00520             predmode = REF2_ONLY;
    00521 //         if ( MB_cost[REF1AND2]<MB_cost[predmode] )
    00522 //             predmode = REF1AND2;
    00523     }
    00524
    00525     return MB_cost[predmode];
    00526 }
    00527
    00528 ValueType ModeDecider::GetDCPred( int xblock , int yblock )
    00529 {
    00530     ValueType dc_pred = 128;
    00531
    00532     if ( xblock>0 && m_me_data_set[2]->Mode()[yblock][xblock-1] == INTRA )
    00533     {
    00534         dc_pred = m_me_data_set[2]->DC( Y_COMP )[yblock][xblock-1];
    00535         if ( yblock>0 && m_me_data_set[2]->Mode()[yblock-1][xblock] == INTRA )
    00536         {
    00537             dc_pred += m_me_data_set[2]->DC( Y_COMP )[yblock-1][xblock];
    00538             dc_pred >>= 1;
    00539         }
    00540     }
    00541
    00542     return dc_pred;
    00543 }
    00544
    00545 float ModeDecider::ModeCost(const int xindex , const int yindex ,
    00546                  const PredMode predmode )
    00547 {
    00548     // Computes the variation of the given mode, predmode, from its immediate neighbours
    00549     // Currently, includes branches to cope with blocks on the edge of the picture.
    00550     int i ,j;
    00551     float diff;
    00552     float var = 0.0;
    00553
    00554     i = xindex-1;
    00555     j = yindex;
    00556     if ( i>=0)
    00557     {
    00558         diff = static_cast<float>( m_me_data_set[2]->Mode()[j][i] - predmode );
    00559         var = std::abs( diff );
    00560     }
    00561
    00562     i = xindex-1;
    00563     j = yindex-1;
    00564     if ( i>=0 && j>=0)
    00565     {
    00566         diff = static_cast<float>( m_me_data_set[2]->Mode()[j][i] - predmode);
    00567         var += std::abs( diff );
    00568     }
    00569
    00570     i = xindex;
    00571     j = yindex-1;
    00572     if ( j>=0 )
    00573     {
    00574         diff = static_cast<float>( m_me_data_set[2]->Mode()[j][i] - predmode );
    00575         var += std::abs( diff );
    00576     }
    00577
    00578     return var*m_me_data_set[2]->LambdaMap()[yindex][xindex];
    00579 }
    00580
    00581 float ModeDecider::GetDCVar( const ValueType dc_val , const ValueType dc_pred)
    00582 {
    00583     return 8.0*std::abs( static_cast<float>( dc_val - dc_pred ) );
    00584 }