- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

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