motion_estimate.cpp

00001 /* ***** BEGIN LICENSE BLOCK *****
00002 *
00003 * $Id: motion_estimate.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 
00039 #include <libdirac_common/frame_buffer.h>
00040 #include <libdirac_motionest/motion_estimate.h>
00041 #include <libdirac_motionest/pixel_match.h>
00042 #include <libdirac_motionest/me_subpel.h>
00043 #include <libdirac_motionest/me_mode_decn.h>
00044 using namespace dirac;
00045 
00046 #include <cmath>
00047 #include <vector>
00048 
00049 MotionEstimator::MotionEstimator( const EncoderParams& encp ):
00050     m_encparams( encp )
00051 {}
00052 
00053 bool MotionEstimator::DoME(const FrameBuffer& my_buffer, int frame_num, MEData& me_data)
00054 {
00055 
00056     const FrameParams& fparams = my_buffer.GetFrame(frame_num).GetFparams();
00057 
00058    // Step 1. 
00059    //Initial search gives vectors for each reference accurate to 1 pixel
00060 
00061     PixelMatcher pix_match( m_encparams );
00062     pix_match.DoSearch( my_buffer , frame_num , me_data);
00063 
00064     // Step 2. 
00065     // Pixel accurate vectors are then refined to 1/8 of a pixel
00066 
00067     SubpelRefine pelrefine( m_encparams );
00068     pelrefine.DoSubpel( my_buffer , frame_num , me_data );
00069 
00070 
00071     // Step3.
00072     // We now have to decide how each macroblock should be split 
00073     // and which references should be used, and so on.
00074 
00075     ModeDecider my_mode_dec( m_encparams );
00076     my_mode_dec.DoModeDecn( my_buffer , frame_num , me_data );
00077 
00078     // Finally, although not strictly part of motion estimation,
00079     // we have to assign DC values for chroma components for
00080     // blocks we're decided are intra.
00081 
00082     if (fparams.CFormat() != Yonly)
00083         SetChromaDC( my_buffer , frame_num , me_data );
00084 
00085     return IsACut( me_data );
00086 
00087 }
00088 
00089 ValueType MotionEstimator::GetChromaBlockDC(const PicArray& pic_data,
00090                                             int xunit , int yunit , int split)
00091 {
00092     BlockDiffParams dparams;
00093     dparams.SetBlockLimits( m_encparams.ChromaBParams( split ) , 
00094                             pic_data, xunit , yunit);
00095 
00096     ValueType dc;
00097 
00098     IntraBlockDiff intradiff( pic_data );
00099 
00100     intradiff.Diff( dparams , dc );
00101 
00102     return dc;
00103 }
00104 
00105 void MotionEstimator::SetChromaDC( const PicArray& pic_data , MvData& mv_data , CompSort csort )
00106 {
00107 
00108     // Lower limit of block coords in MB
00109     int xtl,ytl;
00110     // Upper limit of block coords in MB
00111     int xbr,ybr;
00112 
00113     // Ditto, for subMBs    
00114     int xsubMBtl,ysubMBtl;
00115     int xsubMBbr,ysubMBbr;
00116 
00117     TwoDArray<ValueType>& dcarray = mv_data.DC( csort );
00118 
00119     ValueType dc = 0;
00120 
00121     // Coords of the prediction units (at appropriate level)
00122     int xunit, yunit;
00123 
00124     // The delimiters of the blocks contained in the prediction unit
00125     int xstart, ystart;
00126     int xend, yend;
00127 
00128     int level;
00129 
00130     for ( int ymb=0 ; ymb<mv_data.MBSplit().LengthY() ; ++ymb )
00131     {
00132         for ( int xmb=0 ; xmb<mv_data.MBSplit().LengthX() ; ++xmb )
00133         {
00134 
00135             level = mv_data.MBSplit()[ymb][xmb];
00136 
00137             xtl = xmb<<2;
00138             ytl = ymb<<2;            
00139             xbr = xtl+4;
00140             ybr = ytl+4;
00141 
00142             xsubMBtl = xmb<<1;
00143             ysubMBtl = ymb<<1;
00144             xsubMBbr = xsubMBtl+2;
00145             ysubMBbr = ysubMBtl+2;
00146 
00147 
00148             for (int j = 0 ; j<(1<<level) ;++j)
00149             {
00150                  for (int i = 0 ; i<(1<<level) ;++i)
00151                  {
00152                      xunit = ( xmb<<level ) + i;
00153                      yunit = ( ymb<<level ) + j;
00154 
00155                      xstart = xunit<<( 2-level );
00156                      ystart = yunit<<( 2-level );
00157 
00158                      xend = xstart + ( 1<<( 2-level ) );
00159                      yend = ystart + ( 1<<( 2-level ) );
00160 
00161                      if ( mv_data.Mode()[ystart][xstart] == INTRA )
00162                          // Get the DC value for the unit
00163                          dc = GetChromaBlockDC( pic_data , xunit , yunit , level );
00164 
00165                      // Copy it into the corresponding blocks
00166                      for ( int q=ystart ; q< yend ; ++q )
00167                          for ( int p=xstart ; p< xend ; ++p )
00168                              dcarray[q][p] = dc;
00169 
00170                  }// i
00171              }// j
00172 
00173         }// xmb
00174     }// ymb
00175 }
00176 
00177 void MotionEstimator::SetChromaDC( const FrameBuffer& my_buffer , int frame_num , MvData& mv_data)
00178 {
00179 
00180     SetChromaDC( my_buffer.GetComponent( frame_num , U_COMP) , mv_data , U_COMP );
00181     SetChromaDC( my_buffer.GetComponent( frame_num , V_COMP) , mv_data , V_COMP );
00182 
00183 }
00184 
00185 bool MotionEstimator::IsACut( const MEData& me_data ) const
00186 {
00187     // Count the number of intra blocks
00188     const TwoDArray<PredMode>& modes = me_data.Mode();
00189 
00190     int count_intra = 0;
00191     for ( int j=0 ; j<modes.LengthY() ; ++j )
00192     {
00193         for ( int i=0 ; i<modes.LengthX() ; ++i )
00194         {
00195             if ( modes[j][i] == INTRA )
00196                 count_intra++;
00197         }
00198     }// j
00199     
00200     double intra_percent = 100.0*static_cast<double>( count_intra ) / 
00201                            static_cast<double>( modes.LengthX() * modes.LengthY() );
00202 
00203     if ( m_encparams.Verbose() )
00204         std::cerr<<std::endl<<intra_percent<<"% of blocks are intra   ";
00205 
00206     // Check the size of SAD errors across reference 1    
00207     const TwoDArray<MvCostData>& pcosts = me_data.PredCosts( 1 );
00208 
00209     // averege SAD across all relevant blocks
00210     long double sad_average = 0.0;
00211     // average SAD in a given block
00212     long double block_average; 
00213     // the block parameters
00214     const OLBParams& bparams = m_encparams.LumaBParams( 2 ); 
00215     //the count of the relevant blocks
00216     int block_count = 0;
00217 
00218     for ( int j=0 ; j<pcosts.LengthY() ; ++j )
00219     {
00220         for ( int i=0 ; i<pcosts.LengthX() ; ++i )
00221         {
00222 
00223             if ( modes[j][i] == REF1_ONLY || modes[j][i] == REF1AND2 )
00224             {
00225                 block_average = pcosts[j][i].SAD /
00226                                 static_cast<long double>( bparams.Xblen() * bparams.Yblen() * 4 );
00227                 sad_average += block_average;
00228                 block_count++;
00229             }
00230 
00231         }// i
00232     }// j
00233 
00234     if ( block_count != 0)
00235         sad_average /= static_cast<long double>( block_count );
00236    
00237     if ( (sad_average > 30.0) || (intra_percent > 50.0) )
00238         return true;
00239     else
00240         return false;
00241   
00242 }

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