motion_estimate.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:8k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. *
  3. * $Id: motion_estimate.cpp,v 1.2 2005/01/30 05:11:42 gabest Exp $ $Name:  $
  4. *
  5. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  6. *
  7. * The contents of this file are subject to the Mozilla Public License
  8. * Version 1.1 (the "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. * http://www.mozilla.org/MPL/
  11. *
  12. * Software distributed under the License is distributed on an "AS IS" basis,
  13. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
  14. * the specific language governing rights and limitations under the License.
  15. *
  16. * The Original Code is BBC Research and Development code.
  17. *
  18. * The Initial Developer of the Original Code is the British Broadcasting
  19. * Corporation.
  20. * Portions created by the Initial Developer are Copyright (C) 2004.
  21. * All Rights Reserved.
  22. *
  23. * Contributor(s): Thomas Davies (Original Author)
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
  27. * Public License Version 2.1 (the "LGPL"), in which case the provisions of
  28. * the GPL or the LGPL are applicable instead of those above. If you wish to
  29. * allow use of your version of this file only under the terms of the either
  30. * the GPL or LGPL and not to allow others to use your version of this file
  31. * under the MPL, indicate your decision by deleting the provisions above
  32. * and replace them with the notice and other provisions required by the GPL
  33. * or LGPL. If you do not delete the provisions above, a recipient may use
  34. * your version of this file under the terms of any one of the MPL, the GPL
  35. * or the LGPL.
  36. * ***** END LICENSE BLOCK ***** */
  37. #include <libdirac_common/frame_buffer.h>
  38. #include <libdirac_motionest/motion_estimate.h>
  39. #include <libdirac_motionest/pixel_match.h>
  40. #include <libdirac_motionest/me_subpel.h>
  41. #include <libdirac_motionest/me_mode_decn.h>
  42. using namespace dirac;
  43. #include <cmath>
  44. #include <vector>
  45. MotionEstimator::MotionEstimator( const EncoderParams& encp ):
  46.     m_encparams( encp )
  47. {}
  48. bool MotionEstimator::DoME(const FrameBuffer& my_buffer, int frame_num, MEData& me_data)
  49. {
  50.     const FrameParams& fparams = my_buffer.GetFrame(frame_num).GetFparams();
  51.    // Step 1. 
  52.    //Initial search gives vectors for each reference accurate to 1 pixel
  53.     PixelMatcher pix_match( m_encparams );
  54.     pix_match.DoSearch( my_buffer , frame_num , me_data);
  55.     // Step 2. 
  56.     // Pixel accurate vectors are then refined to 1/8 of a pixel
  57.     SubpelRefine pelrefine( m_encparams );
  58.     pelrefine.DoSubpel( my_buffer , frame_num , me_data );
  59.     // Step3.
  60.     // We now have to decide how each macroblock should be split 
  61.     // and which references should be used, and so on.
  62.     ModeDecider my_mode_dec( m_encparams );
  63.     my_mode_dec.DoModeDecn( my_buffer , frame_num , me_data );
  64.     // Finally, although not strictly part of motion estimation,
  65.     // we have to assign DC values for chroma components for
  66.     // blocks we're decided are intra.
  67.     if (fparams.CFormat() != Yonly)
  68.         SetChromaDC( my_buffer , frame_num , me_data );
  69.     return IsACut( me_data );
  70. }
  71. ValueType MotionEstimator::GetChromaBlockDC(const PicArray& pic_data,
  72.                                             int xunit , int yunit , int split)
  73. {
  74.     BlockDiffParams dparams;
  75.     dparams.SetBlockLimits( m_encparams.ChromaBParams( split ) , 
  76.                             pic_data, xunit , yunit);
  77.     ValueType dc;
  78.     IntraBlockDiff intradiff( pic_data );
  79.     intradiff.Diff( dparams , dc );
  80.     return dc;
  81. }
  82. void MotionEstimator::SetChromaDC( const PicArray& pic_data , MvData& mv_data , CompSort csort )
  83. {
  84.     // Lower limit of block coords in MB
  85.     int xtl,ytl;
  86.     // Upper limit of block coords in MB
  87.     int xbr,ybr;
  88.     // Ditto, for subMBs    
  89.     int xsubMBtl,ysubMBtl;
  90.     int xsubMBbr,ysubMBbr;
  91.     TwoDArray<ValueType>& dcarray = mv_data.DC( csort );
  92.     ValueType dc = 0;
  93.     // Coords of the prediction units (at appropriate level)
  94.     int xunit, yunit;
  95.     // The delimiters of the blocks contained in the prediction unit
  96.     int xstart, ystart;
  97.     int xend, yend;
  98.     int level;
  99.     for ( int ymb=0 ; ymb<mv_data.MBSplit().LengthY() ; ++ymb )
  100.     {
  101.         for ( int xmb=0 ; xmb<mv_data.MBSplit().LengthX() ; ++xmb )
  102.         {
  103.             level = mv_data.MBSplit()[ymb][xmb];
  104.             xtl = xmb<<2;
  105.             ytl = ymb<<2;            
  106.             xbr = xtl+4;
  107.             ybr = ytl+4;
  108.             xsubMBtl = xmb<<1;
  109.             ysubMBtl = ymb<<1;
  110.             xsubMBbr = xsubMBtl+2;
  111.             ysubMBbr = ysubMBtl+2;
  112.             for (int j = 0 ; j<(1<<level) ;++j)
  113.             {
  114.                  for (int i = 0 ; i<(1<<level) ;++i)
  115.                  {
  116.                      xunit = ( xmb<<level ) + i;
  117.                      yunit = ( ymb<<level ) + j;
  118.                      xstart = xunit<<( 2-level );
  119.                      ystart = yunit<<( 2-level );
  120.                      xend = xstart + ( 1<<( 2-level ) );
  121.                      yend = ystart + ( 1<<( 2-level ) );
  122.                      if ( mv_data.Mode()[ystart][xstart] == INTRA )
  123.                          // Get the DC value for the unit
  124.                          dc = GetChromaBlockDC( pic_data , xunit , yunit , level );
  125.                      // Copy it into the corresponding blocks
  126.                      for ( int q=ystart ; q< yend ; ++q )
  127.                          for ( int p=xstart ; p< xend ; ++p )
  128.                              dcarray[q][p] = dc;
  129.                  }// i
  130.              }// j
  131.         }// xmb
  132.     }// ymb
  133. }
  134. void MotionEstimator::SetChromaDC( const FrameBuffer& my_buffer , int frame_num , MvData& mv_data)
  135. {
  136.     SetChromaDC( my_buffer.GetComponent( frame_num , U_COMP) , mv_data , U_COMP );
  137.     SetChromaDC( my_buffer.GetComponent( frame_num , V_COMP) , mv_data , V_COMP );
  138. }
  139. bool MotionEstimator::IsACut( const MEData& me_data ) const
  140. {
  141.     // Count the number of intra blocks
  142.     const TwoDArray<PredMode>& modes = me_data.Mode();
  143.     int count_intra = 0;
  144.     for ( int j=0 ; j<modes.LengthY() ; ++j )
  145.     {
  146.         for ( int i=0 ; i<modes.LengthX() ; ++i )
  147.         {
  148.             if ( modes[j][i] == INTRA )
  149.                 count_intra++;
  150.         }
  151.     }// j
  152.     
  153.     double intra_percent = 100.0*static_cast<double>( count_intra ) / 
  154.                            static_cast<double>( modes.LengthX() * modes.LengthY() );
  155.     if ( m_encparams.Verbose() )
  156.         std::cerr<<std::endl<<intra_percent<<"% of blocks are intra   ";
  157.     // Check the size of SAD errors across reference 1    
  158.     const TwoDArray<MvCostData>& pcosts = me_data.PredCosts( 1 );
  159.     // averege SAD across all relevant blocks
  160.     long double sad_average = 0.0;
  161.     // average SAD in a given block
  162.     long double block_average; 
  163.     // the block parameters
  164.     const OLBParams& bparams = m_encparams.LumaBParams( 2 ); 
  165.     //the count of the relevant blocks
  166.     int block_count = 0;
  167.     for ( int j=0 ; j<pcosts.LengthY() ; ++j )
  168.     {
  169.         for ( int i=0 ; i<pcosts.LengthX() ; ++i )
  170.         {
  171.             if ( modes[j][i] == REF1_ONLY || modes[j][i] == REF1AND2 )
  172.             {
  173.                 block_average = pcosts[j][i].SAD /
  174.                                 static_cast<long double>( bparams.Xblen() * bparams.Yblen() * 4 );
  175.                 sad_average += block_average;
  176.                 block_count++;
  177.             }
  178.         }// i
  179.     }// j
  180.     if ( block_count != 0)
  181.         sad_average /= static_cast<long double>( block_count );
  182.    
  183.     if ( (sad_average > 30.0) || (intra_percent > 50.0) )
  184.         return true;
  185.     else
  186.         return false;
  187.   
  188. }