/* ***** BEGIN LICENSE BLOCK ***** * * $Id: me_utils.cpp,v 1.19 2006/06/05 14:54:17 asuraparaju Exp $ $Name: Dirac_0_7_0 $ * * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for * the specific language governing rights and limitations under the License. * * The Original Code is BBC Research and Development code. * * The Initial Developer of the Original Code is the British Broadcasting * Corporation. * Portions created by the Initial Developer are Copyright (C) 2004. * All Rights Reserved. * * Contributor(s): Thomas Davies (Original Author), * Peter Meerwald (pmeerw@users.sourceforge.net) * Steve Bearcroft (bearcrsw@users.sourceforge.net) * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser * Public License Version 2.1 (the "LGPL"), in which case the provisions of * the GPL or the LGPL are applicable instead of those above. If you wish to * allow use of your version of this file only under the terms of the either * the GPL or LGPL and not to allow others to use your version of this file * under the MPL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by the GPL * or LGPL. If you do not delete the provisions above, a recipient may use * your version of this file under the terms of any one of the MPL, the GPL * or the LGPL. * ***** END LICENSE BLOCK ***** */ /////////////////////////////////// //-------------------------------// //utilities for motion estimation// //-------------------------------// /////////////////////////////////// #include #include #include using namespace dirac; #include void BlockDiffParams::SetBlockLimits( const OLBParams& bparams , const PicArray& m_pic_data , const int xbpos , const int ybpos) { const int loc_xp = xbpos * bparams.Xbsep() - bparams.Xoffset(); const int loc_yp = ybpos * bparams.Ybsep() - bparams.Yoffset(); m_xp=std::max( loc_xp , 0 ); m_yp=std::max( loc_yp , 0 ); m_xl = bparams.Xblen() - m_xp + loc_xp; m_yl = bparams.Yblen() - m_yp + loc_yp; //constrain block lengths to fall within the picture m_xl = ( ( m_xp + m_xl - 1) > m_pic_data.LastX() ) ? ( m_pic_data.LastX() + 1 - m_xp ): m_xl; m_yl = ( ( m_yp + m_yl - 1) > m_pic_data.LastY() ) ? ( m_pic_data.LastY() + 1 - m_yp ) : m_yl; m_xend = m_xp+m_xl; m_yend = m_yp+m_yl; } // Block difference class functions // Constructors ... BlockDiff::BlockDiff(const PicArray& ref,const PicArray& pic) : m_pic_data( pic ), m_ref_data( ref ) {} PelBlockDiff::PelBlockDiff( const PicArray& ref , const PicArray& pic ) : BlockDiff( ref , pic ) {} IntraBlockDiff::IntraBlockDiff( const PicArray& pic ) : m_pic_data( pic ) {} BiBlockDiff::BiBlockDiff( const PicArray& ref1 , const PicArray& ref2 , const PicArray& pic) : m_pic_data( pic ), m_ref_data1( ref1 ), m_ref_data2( ref2 ) {} BlockDiffUp::BlockDiffUp( const PicArray& ref , const PicArray& pic ): BlockDiff( ref , pic ) {} BlockDiffHalfPel::BlockDiffHalfPel( const PicArray& ref , const PicArray& pic ) : BlockDiffUp( ref , pic ) {} BlockDiffQuarterPel::BlockDiffQuarterPel( const PicArray& ref , const PicArray& pic ) : BlockDiffUp( ref , pic ) {} BlockDiffEighthPel::BlockDiffEighthPel( const PicArray& ref , const PicArray& pic ) : BlockDiffUp( ref , pic ) {} BiBlockHalfPel::BiBlockHalfPel( const PicArray& ref1 , const PicArray& ref2 , const PicArray& pic ): BiBlockDiff( ref1 , ref2 , pic) {} BiBlockQuarterPel::BiBlockQuarterPel( const PicArray& ref1 , const PicArray& ref2 , const PicArray& pic ): BiBlockDiff( ref1 , ref2 , pic) {} BiBlockEighthPel::BiBlockEighthPel( const PicArray& ref1 , const PicArray& ref2 , const PicArray& pic ): BiBlockDiff( ref1 , ref2 , pic) {} // Difference functions ... float PelBlockDiff::Diff( const BlockDiffParams& dparams, const MVector& mv ) { if (dparams.Xl() <= 0 || dparams.Yl() <= 0) { return 0; } CalcValueType sum( 0 ); const ImageCoords ref_start( dparams.Xp()+mv.x , dparams.Yp()+mv.y ); const ImageCoords ref_stop( dparams.Xend()+mv.x , dparams.Yend()+mv.y ); bool bounds_check( false ); if ( ref_start.x<0 || ref_stop.x >= m_ref_data.LengthX() || ref_start.y<0 || ref_stop.y >= m_ref_data.LengthY() ) bounds_check = true; if ( !bounds_check ) { #if defined(HAVE_MMX) return static_cast(simple_block_diff_mmx_4(dparams, mv, m_pic_data, m_ref_data, INT_MAX)); #else ValueType diff; for ( int j=dparams.Yp() ; j(bchk_simple_block_diff_mmx_4(dparams, mv, m_pic_data, m_ref_data, INT_MAX)); #else ValueType diff; for ( int j=dparams.Yp() ; j < dparams.Yp()+dparams.Yl() ; ++j ) { for( int i=dparams.Xp() ; i < dparams.Xp()+dparams.Xl() ; ++i ) { diff = m_pic_data[j][i] - m_ref_data[BChk(j+mv.y , m_ref_data.LengthY())][BChk(i+mv.x , m_ref_data.LengthX())]; sum += std::abs( diff ); }// i }// j #endif /* HAVE_MMX */ } return static_cast( sum ); } void PelBlockDiff::Diff( const BlockDiffParams& dparams, const MVector& mv, float& best_sum, MVector& best_mv ) { if (dparams.Xl() <= 0 || dparams.Yl() <= 0) { return; } CalcValueType sum( 0 ); const ImageCoords ref_start( dparams.Xp()+mv.x , dparams.Yp()+mv.y ); const ImageCoords ref_stop( dparams.Xend()+mv.x , dparams.Yend()+mv.y ); bool bounds_check( false ); if ( ref_start.x<0 || ref_stop.x >= m_ref_data.LengthX() || ref_start.y<0 || ref_stop.y >= m_ref_data.LengthY() ) bounds_check = true; if ( !bounds_check ) { #if defined (HAVE_MMX) sum = simple_block_diff_mmx_4(dparams, mv, m_pic_data, m_ref_data, static_cast(best_sum)); if (sum < best_sum) { best_sum = sum; best_mv = mv; } return; #else ValueType diff; ValueType *pic_curr = &m_pic_data[dparams.Yp()][dparams.Xp()]; const int pic_next( m_pic_data.LengthX() - dparams.Xl() ); // - go down a row and back along ValueType *ref_curr = &m_ref_data[ref_start.y][ref_start.x]; for( int y=dparams.Yl(); y>0; --y, pic_curr+=pic_next, ref_curr+=pic_next ) { for( int x=dparams.Xl(); x>0; --x, ++pic_curr, ++ref_curr ) { diff = (*pic_curr)-(*ref_curr); sum += std::abs( diff ); }// x if ( sum>=best_sum ) return; }// y #endif /* HAVE_MMX */ } else { #if defined (HAVE_MMX) sum = (bchk_simple_block_diff_mmx_4(dparams, mv, m_pic_data, m_ref_data, static_cast(best_sum))); if (sum < best_sum) { best_sum = sum; best_mv = mv; } return; #else ValueType diff; for ( int j=dparams.Yp() ; j=best_sum ) return; }// j #endif /* HAVE_MMX */ } best_sum = sum; best_mv = mv; } float IntraBlockDiff::Diff( const BlockDiffParams& dparams , ValueType& dc_val ) { if (dparams.Xl() <= 0 || dparams.Yl() <= 0) { dc_val = 0; return 0; } //computes the cost if block is predicted by its dc component #if defined(HAVE_MMX) CalcValueType intra_cost = simple_intra_block_diff_mmx_4 (dparams, m_pic_data, dc_val); #ifdef DIRAC_DEBUG CalcValueType int_dc( 0 ); ValueType non_mmx_dc(0); for ( int j=dparams.Yp() ; j( m_pic_data[j][i] ); int_dc /= ( dparams.Xl() * dparams.Yl() ); non_mmx_dc = static_cast( int_dc ); // Now compute the resulting SAD ValueType dc( non_mmx_dc ); CalcValueType non_mmx_intra_cost( 0 ); for (int j=dparams.Yp(); j