1 /* ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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.
16 * The Original Code is BBC Research and Development code.
18 * The Initial Developer of the Original Code is the British Broadcasting
20 * Portions created by the Initial Developer are Copyright (C) 2004.
21 * All Rights Reserved.
23 * Contributor(s): Thomas Davies (Original Author),
26 * Alternatively, the contents of this file may be used under the terms of
27 * the GNU General Public License Version 2 (the "GPL"), or the GNU Lesser
28 * Public License Version 2.1 (the "LGPL"), in which case the provisions of
29 * the GPL or the LGPL are applicable instead of those above. If you wish to
30 * allow use of your version of this file only under the terms of the either
31 * the GPL or LGPL and not to allow others to use your version of this file
32 * under the MPL, indicate your decision by deleting the provisions above
33 * and replace them with the notice and other provisions required by the GPL
34 * or LGPL. If you do not delete the provisions above, a recipient may use
35 * your version of this file under the terms of any one of the MPL, the GPL
37 * ***** END LICENSE BLOCK ***** */
39 #include <libdirac_motionest/me_mode_decn.h>
40 #include <libdirac_encoder/enc_queue.h>
41 using namespace dirac
;
47 ModeDecider::ModeDecider( const EncoderParams
& encp
):
57 ModeDecider::~ModeDecider()
59 if (m_psort
.IsInter())
61 delete m_me_data_set
[0];
62 delete m_me_data_set
[1];
66 void ModeDecider::DoModeDecn( EncQueue
& my_buffer
, int pic_num
)
69 m_predparams
= &(my_buffer
.GetPicture(pic_num
).GetMEData().GetPicPredParams() );
71 // The following factors normalise costs for sub-SBs and SBs to those of
72 // blocks, so that the overlap is take into account (e.g. a sub-SB has
73 // length XBLEN+XBSEP and YBLEN+YBSEP). The SB costs for a 1x1
74 // decomposition are not directly comprable to those for other decompositions
75 // because of the block overlaps. These factors remove these effects, so that
76 // all SAD costs are normalised to the area corresponding to non-overlapping
77 // 16 blocks of size XBLEN*YBLEN.
79 m_level_factor
[0] = float( 16 * m_predparams
->LumaBParams(2).Xblen() * m_predparams
->LumaBParams(2).Yblen() )/
80 float( m_predparams
->LumaBParams(0).Xblen() * m_predparams
->LumaBParams(0).Yblen() );
82 m_level_factor
[1] = float( 4 * m_predparams
->LumaBParams(2).Xblen() * m_predparams
->LumaBParams(2).Yblen() )/
83 float( m_predparams
->LumaBParams(1).Xblen() * m_predparams
->LumaBParams(1).Yblen() );
85 m_level_factor
[2] = 1.0f
;
87 for (int i
=0 ; i
<=2 ; ++i
)
88 m_mode_factor
[i
] = 80.0*std::pow(0.8 , 2-i
);
90 // We've got 'raw' block motion vectors for up to two reference pictures. Now we want
91 // to make a decision as to mode. In this initial implementation, this is bottom-up
92 // i.e. find mvs for SBs and sub-SBs and see whether it's worthwhile merging.
99 m_psort
= my_buffer
.GetPicture(pic_num
).GetPparams().PicSort();
100 if (m_psort
.IsInter())
102 // Extract the references
103 const vector
<int>& refs
= my_buffer
.GetPicture(pic_num
).GetPparams().Refs();
104 num_refs
= refs
.size();
107 // The picture we're doing estimation from
108 m_pic_data
= &(my_buffer
.GetPicture( pic_num
).DataForME(m_encparams
.CombinedME()) );
110 // Set up the hierarchy of motion vector data objects
111 PicturePredParams predparams0
= *m_predparams
;
112 predparams0
.SetXNumBlocks( m_predparams
->XNumBlocks()/4 );
113 predparams0
.SetYNumBlocks( m_predparams
->YNumBlocks()/4 );
115 PicturePredParams predparams1
= *m_predparams
;
116 predparams1
.SetXNumBlocks( m_predparams
->XNumBlocks()/2 );
117 predparams1
.SetYNumBlocks( m_predparams
->YNumBlocks()/2 );
119 m_me_data_set
[0] = new MEData( predparams0
, num_refs
);
120 m_me_data_set
[1] = new MEData( predparams1
, num_refs
);
122 m_me_data_set
[2] = &my_buffer
.GetPicture(pic_num
).GetMEData();
124 // Set up the lambdas to use per block
125 m_me_data_set
[0]->SetLambdaMap( 0 , m_me_data_set
[2]->LambdaMap() , 1.0/m_level_factor
[0] );
126 m_me_data_set
[1]->SetLambdaMap( 1 , m_me_data_set
[2]->LambdaMap() , 1.0/m_level_factor
[1] );
128 // Set up the reference pictures
129 m_ref1_updata
= &(my_buffer
.GetPicture( ref1
).UpDataForME(m_encparams
.CombinedME()) );
134 m_ref2_updata
= &(my_buffer
.GetPicture( ref2
).UpDataForME(m_encparams
.CombinedME()) );
135 // Create an object for computing bi-directional prediction calculations
136 if ( m_predparams
->MVPrecision()==MV_PRECISION_EIGHTH_PIXEL
)
137 m_bicheckdiff
= new BiBlockEighthPel( *m_ref1_updata
,
140 else if ( m_predparams
->MVPrecision()==MV_PRECISION_QUARTER_PIXEL
)
141 m_bicheckdiff
= new BiBlockQuarterPel( *m_ref1_updata
,
145 m_bicheckdiff
= new BiBlockHalfPel( *m_ref1_updata
,
155 // Create an object for doing intra calculations
156 m_intradiff
= new IntraBlockDiff( *m_pic_data
);
158 // Loop over all the superblocks, doing the work //
159 ///////////////////////////////////////////////////
161 for (m_ysb_loc
=0 ; m_ysb_loc
<m_predparams
->YNumSB() ; ++m_ysb_loc
){
162 for (m_xsb_loc
=0 ; m_xsb_loc
<m_predparams
->XNumSB(); ++m_xsb_loc
){
169 delete m_bicheckdiff
;
172 // Finally, although not strictly part of motion estimation,
173 // we have to assign DC values for
174 // blocks we're decided are intra.
175 SetDC( my_buffer
, pic_num
);
179 void ModeDecider::DoSBDecn()
181 // Does the mode decision for the given SB, in three stages
183 // Start with 4x4 modes
185 float old_best_SB_cost
= m_me_data_set
[2]->SBCosts()[m_ysb_loc
][m_xsb_loc
];
190 // Do 1x1 mode if merging worked before
191 if ( m_me_data_set
[2]->SBCosts()[m_ysb_loc
][m_xsb_loc
] <= old_best_SB_cost
)
193 old_best_SB_cost
= m_me_data_set
[2]->SBCosts()[m_ysb_loc
][m_xsb_loc
];
199 void ModeDecider::DoLevelDecn( int level
)
201 // Computes the best costs if we were to
202 // stick to a decomposition at this level
204 // Looks at two cases: the prediction mode is
205 // constant across the SB; and the pred mode
206 // for each constituent is different.
208 // The limits of the prediction units
209 const int xstart
= m_xsb_loc
<<level
;
210 const int ystart
= m_ysb_loc
<<level
;
212 const int xend
= xstart
+ (1<<level
);
213 const int yend
= ystart
+ (1<<level
);
215 // Case 1: prediction modes are all different
218 for ( int j
=ystart
; j
<yend
; ++j
)
220 for (int i
=xstart
; i
<xend
; ++i
)
223 DoME( i
, j
, level
);
224 SB_cost
+= DoUnitDecn( i
, j
,level
);
229 // if we've improved on the best cost, we should propagate data in
230 // the base level motion vector set
233 m_me_data_set
[2]->SBSplit()[m_ysb_loc
][m_xsb_loc
] = 2;
234 m_me_data_set
[2]->SBCosts()[m_ysb_loc
][m_xsb_loc
] = SB_cost
;
237 if ( level
<2 && SB_cost
<= m_me_data_set
[2]->SBCosts()[m_ysb_loc
][m_xsb_loc
] )
239 m_me_data_set
[2]->SBCosts()[m_ysb_loc
][m_xsb_loc
] = SB_cost
;
240 m_me_data_set
[2]->SBSplit()[m_ysb_loc
][m_xsb_loc
] = level
;
242 // Parameters of the base-level blocks corresponding to each
249 for ( int j
=ystart
; j
<yend
; ++j
)
251 yblock_start
= j
<<(2-level
);
252 yblock_end
= (j
+1)<<(2-level
);
253 for ( int i
=xstart
; i
<xend
; ++i
)
255 xblock_start
= i
<<(2-level
);
256 xblock_end
= (i
+1)<<(2-level
);
258 for ( int v
=yblock_start
; v
<yblock_end
; ++v
)
260 for ( int u
=xblock_start
; u
<xblock_end
; ++u
)
262 m_me_data_set
[2]->Mode()[v
][u
] = m_me_data_set
[level
]->Mode()[j
][i
];
263 m_me_data_set
[2]->DC( Y_COMP
)[v
][u
] = m_me_data_set
[level
]->DC( Y_COMP
)[j
][i
];
264 m_me_data_set
[2]->Vectors(1)[v
][u
] = m_me_data_set
[level
]->Vectors(1)[j
][i
];
266 m_me_data_set
[2]->Vectors(2)[v
][u
] = m_me_data_set
[level
]->Vectors(2)[j
][i
];
279 void ModeDecider::DoME(const int xpos
, const int ypos
, const int level
)
281 // Do motion estimation for a prediction unit using the
282 // four vectors derived from the next level as a guide
284 MEData
& me_data
= *(m_me_data_set
[level
]);
285 const MEData
& guide_data
= *(m_me_data_set
[level
+1]);
287 // The corresponding location of the guide data
288 const int guide_xpos
= xpos
<<1;
289 const int guide_ypos
= ypos
<<1;
291 // The location of the lowest level vectors
292 const int xblock
= xpos
<< ( 2 - level
);
293 const int yblock
= ypos
<< ( 2 - level
);
295 // The list of potential candidate vectors
296 CandidateList cand_list
;
298 // The lambda to use for motion estimation
299 const float lambda
= me_data
.LambdaMap()[ypos
][xpos
];
301 // The predicting motion vector
304 for ( int j
=0 ; j
<2 ; ++j
)
305 for (int i
=0 ; i
<2 ; ++i
)
306 AddNewVlist( cand_list
, guide_data
.Vectors(1)[guide_ypos
+j
][guide_xpos
+i
] , 0 , 0 );
308 if (xblock
>0 && yblock
>0)
309 mv_pred
= MvMedian( m_me_data_set
[2]->Vectors(1)[yblock
][xblock
-1] ,
310 m_me_data_set
[2]->Vectors(1)[yblock
-1][xblock
-1],
311 m_me_data_set
[2]->Vectors(1)[yblock
-1][xblock
]);
312 else if (xblock
==0 && yblock
>0)
313 mv_pred
= MvMean( m_me_data_set
[2]->Vectors(1)[yblock
-1][xblock
],
314 m_me_data_set
[2]->Vectors(1)[yblock
-1][xblock
+1]);
315 else if (xblock
>0 && yblock
==0)
316 mv_pred
= MvMean( m_me_data_set
[2]->Vectors(1)[yblock
][xblock
-1],
317 m_me_data_set
[2]->Vectors(1)[yblock
+1][xblock
-1]);
323 BlockMatcher
my_bmatch1( *m_pic_data
,
325 m_predparams
->LumaBParams(level
) ,
326 m_predparams
->MVPrecision(),
327 me_data
.Vectors(1) , me_data
.PredCosts(1) );
328 me_data
.PredCosts(1)[ypos
][xpos
].total
= 100000000.0f
;
329 my_bmatch1
.FindBestMatchSubp( xpos
, ypos
, cand_list
, mv_pred
, lambda
);
332 {//do the same for the other reference
336 for ( int j
=0 ; j
<2 ; ++j
)
337 for (int i
=0 ; i
<2 ; ++i
)
338 AddNewVlist( cand_list
, guide_data
.Vectors(2)[guide_ypos
+j
][guide_xpos
+i
] , 0 , 0 );
340 if (xblock
>0 && yblock
>0)
341 mv_pred
= MvMedian( m_me_data_set
[2]->Vectors(2)[yblock
][xblock
-1] ,
342 m_me_data_set
[2]->Vectors(2)[yblock
-1][xblock
-1],
343 m_me_data_set
[2]->Vectors(2)[yblock
-1][xblock
]);
344 else if (xblock
==0 && yblock
>0)
345 mv_pred
= MvMean( m_me_data_set
[2]->Vectors(2)[yblock
-1][xblock
],
346 m_me_data_set
[2]->Vectors(2)[yblock
-1][xblock
+1]);
347 else if (xblock
>0 && yblock
==0)
348 mv_pred
= MvMean( m_me_data_set
[2]->Vectors(2)[yblock
][xblock
-1],
349 m_me_data_set
[2]->Vectors(2)[yblock
+1][xblock
-1]);
355 BlockMatcher
my_bmatch2( *m_pic_data
,
357 m_predparams
->LumaBParams(level
) ,
358 m_predparams
->MVPrecision(),
359 me_data
.Vectors(2) , me_data
.PredCosts(2) );
360 me_data
.PredCosts(2)[ypos
][xpos
].total
= 100000000.0f
;
361 my_bmatch2
.FindBestMatchSubp( xpos
, ypos
, cand_list
, mv_pred
, lambda
);
368 float ModeDecider::DoUnitDecn(const int xpos
, const int ypos
, const int level
)
370 // For a given prediction unit (SB, subSB or block) find the best
371 // mode, given that the REF1 and REF2 motion estimation has
372 // already been done.
374 MEData
& me_data
= *( m_me_data_set
[level
] );
376 // Coords of the top-leftmost block belonging to this unit
377 // const int xblock = xpos<<(2-level);
378 // const int yblock = ypos<<(2-level);
380 const float loc_lambda
= me_data
.LambdaMap()[ypos
][xpos
];
383 float mode_cost(0.0);
385 float best_SAD_value
;
387 BlockDiffParams dparams
;
389 dparams
.SetBlockLimits( m_predparams
->LumaBParams( level
) , *m_pic_data
, xpos
, ypos
);
391 // First check REF1 costs //
392 /**************************/
394 // mode_cost = ModeCost( xblock , yblock )*m_mode_factor[level];
395 me_data
.Mode()[ypos
][xpos
] = REF1_ONLY
;
396 me_data
.PredCosts(1)[ypos
][xpos
].total
*= m_level_factor
[level
];
397 min_unit_cost
= me_data
.PredCosts(1)[ypos
][xpos
].total
+ mode_cost
;
398 best_SAD_value
= me_data
.PredCosts(1)[ypos
][xpos
].SAD
;
402 // Next check REF2 costs //
403 /*************************/
405 // mode_cost = ModeCost( xblock , yblock )*m_mode_factor[level];
406 me_data
.PredCosts(2)[ypos
][xpos
].total
*= m_level_factor
[level
];
407 unit_cost
= me_data
.PredCosts(2)[ypos
][xpos
].total
+ mode_cost
;
408 if ( unit_cost
<min_unit_cost
)
410 me_data
.Mode()[ypos
][xpos
] = REF2_ONLY
;
411 min_unit_cost
= unit_cost
;
412 best_SAD_value
= me_data
.PredCosts(2)[ypos
][xpos
].SAD
;
415 // Calculate the cost if we were to use bi-predictions //
416 /****************************************************************/
417 // mode_cost = ModeCost( xpos , ypos )*m_mode_factor[level];
419 me_data
.BiPredCosts()[ypos
][xpos
].mvcost
=
420 me_data
.PredCosts(1)[ypos
][xpos
].mvcost
+
421 me_data
.PredCosts(2)[ypos
][xpos
].mvcost
;
423 me_data
.BiPredCosts()[ypos
][xpos
].SAD
= m_bicheckdiff
->Diff(dparams
,
424 me_data
.Vectors(1)[ypos
][xpos
] ,
425 me_data
.Vectors(2)[ypos
][xpos
] );
427 me_data
.BiPredCosts()[ypos
][xpos
].SetTotal( loc_lambda
);
429 me_data
.BiPredCosts()[ypos
][xpos
].total
*= m_level_factor
[level
];
430 unit_cost
= me_data
.BiPredCosts()[ypos
][xpos
].total
+ mode_cost
;
432 if ( unit_cost
<min_unit_cost
)
434 me_data
.Mode()[ypos
][xpos
] = REF1AND2
;
435 min_unit_cost
= unit_cost
;
436 best_SAD_value
= me_data
.BiPredCosts()[ypos
][xpos
].SAD
;
441 // Calculate the cost if we were to code the block as intra //
442 /************************************************************/
444 if ( level
==2 && best_SAD_value
> 4.0*m_predparams
->LumaBParams( level
).Xblen()*
445 m_predparams
->LumaBParams( level
).Yblen() )
447 // mode_cost = ModeCost( xblock , yblock ) * m_mode_factor[level];
448 me_data
.IntraCosts()[ypos
][xpos
] = m_intradiff
->Diff( dparams
, me_data
.DC( Y_COMP
)[ypos
][xpos
] );
449 // me_data.IntraCosts()[ypos][xpos] += loc_lambda *
450 // GetDCVar( me_data.DC( Y_COMP )[ypos][xpos] , GetDCPred( xblock , yblock ) );
451 me_data
.IntraCosts()[ypos
][xpos
] *= m_level_factor
[level
];
452 unit_cost
= me_data
.IntraCosts()[ypos
][xpos
] + mode_cost
;
454 if ( unit_cost
<min_unit_cost
&& me_data
.IntraCosts()[ypos
][xpos
]<0.85*best_SAD_value
)
456 me_data
.Mode()[ypos
][xpos
] = INTRA
;
457 min_unit_cost
= unit_cost
;
461 return min_unit_cost
;
464 ValueType
ModeDecider::GetDCPred( int xblock
, int yblock
)
466 ValueType dc_pred
= 0;
468 if ( xblock
>0 && m_me_data_set
[2]->Mode()[yblock
][xblock
-1] == INTRA
)
470 dc_pred
= m_me_data_set
[2]->DC( Y_COMP
)[yblock
][xblock
-1];
471 if ( yblock
>0 && m_me_data_set
[2]->Mode()[yblock
-1][xblock
] == INTRA
)
473 dc_pred
+= m_me_data_set
[2]->DC( Y_COMP
)[yblock
-1][xblock
];
481 float ModeDecider::ModeCost(const int xindex
, const int yindex
)
483 // Computes the variation of the given mode, predmode, from its immediate neighbours
484 // First, get a prediction for the mode
486 unsigned int mode_predictor
= (unsigned int)(REF1_ONLY
);
487 const TwoDArray
<PredMode
>& preddata( m_me_data_set
[2]->Mode() );
489 unsigned int num_ref1_nbrs( 0 );
490 unsigned int num_ref2_nbrs( 0 );
492 if (xindex
> 0 && yindex
> 0)
494 num_ref1_nbrs
+= ((unsigned int)( preddata
[yindex
-1][xindex
] ) ) & 1;
495 num_ref1_nbrs
+= ((unsigned int)( preddata
[yindex
-1][xindex
-1] ) ) & 1;
496 num_ref1_nbrs
+= ((unsigned int)( preddata
[yindex
][xindex
-1] ) ) & 1;
498 mode_predictor
= num_ref1_nbrs
>>1;
500 num_ref2_nbrs
+= ((unsigned int)( preddata
[yindex
-1][xindex
] ) ) & 2;
501 num_ref2_nbrs
+= ((unsigned int)( preddata
[yindex
-1][xindex
-1] ) ) & 2;
502 num_ref2_nbrs
+= ((unsigned int)( preddata
[yindex
][xindex
-1] ) ) & 2;
505 mode_predictor
^= ( (num_ref2_nbrs
>>1)<<1 );
507 else if (xindex
> 0 && yindex
== 0)
508 mode_predictor
= (unsigned int)( preddata
[0][xindex
-1] );
509 else if (xindex
== 0 && yindex
> 0)
510 mode_predictor
= (unsigned int)( preddata
[yindex
-1][0] );
512 unsigned int var
= (mode_predictor
& 1)+((mode_predictor
>>1) &1);
514 return var
*m_me_data_set
[2]->LambdaMap()[yindex
][xindex
];
518 float ModeDecider::GetDCVar( const ValueType dc_val
, const ValueType dc_pred
)
520 return 4.0*std::abs( static_cast<float>( dc_val
- dc_pred
) );
523 ValueType
ModeDecider::GetBlockDC(const PicArray
& pic_data
,
524 int xunit
, int yunit
, int split
, CompSort cs
)
526 BlockDiffParams dparams
;
529 dparams
.SetBlockLimits( m_predparams
->ChromaBParams( split
) ,
530 pic_data
, xunit
, yunit
);
532 dparams
.SetBlockLimits( m_predparams
->LumaBParams( split
) ,
533 pic_data
, xunit
, yunit
);
535 IntraBlockDiff
intradiff( pic_data
);
537 return intradiff
.CalcDC( dparams
);
540 void ModeDecider::SetDC( const PicArray
& pic_data
, MEData
& me_data
, CompSort cs
)
543 TwoDArray
<ValueType
>& dcarray
= me_data
.DC( cs
);
544 TwoDArray
<ValueType
> temp_dcarray (dcarray
.LengthY(), dcarray
.LengthX() );
546 for ( int y
=0 ; y
<dcarray
.LengthY() ; ++y
){
547 for ( int x
=0 ; x
<dcarray
.LengthX() ; ++x
){
548 temp_dcarray
[y
][x
] = GetBlockDC( pic_data
, x
, y
, 2, cs
);
552 for ( int x
=0 ; x
<dcarray
.LengthX() ; ++x
){
553 dcarray
[0][x
] = temp_dcarray
[0][x
];
555 for ( int y
=1 ; y
<dcarray
.LengthY()-1 ; ++y
){
556 dcarray
[y
][0] = temp_dcarray
[y
][0];
557 for ( int x
=1 ; x
<dcarray
.LengthX()-1 ; ++x
){
558 dcarray
[y
][x
] = (temp_dcarray
[y
-1][x
-1]+3*temp_dcarray
[y
-1][x
]+temp_dcarray
[y
-1][x
+1]+
559 3*temp_dcarray
[y
][x
-1]+ 3*temp_dcarray
[y
][x
+1]+
560 temp_dcarray
[y
+1][x
-1]+3*temp_dcarray
[y
+1][x
]+temp_dcarray
[y
+1][x
+1]+8 )>>4;
562 dcarray
[y
][dcarray
.LastX()] = temp_dcarray
[y
][dcarray
.LastX()];
566 void ModeDecider::SetDC( EncQueue
& my_buffer
, int pic_num
)
568 MEData
& me_data
= my_buffer
.GetPicture(pic_num
).GetMEData();
569 SetDC( my_buffer
.GetPicture( pic_num
).OrigData(Y_COMP
) , me_data
, Y_COMP
);
570 SetDC( my_buffer
.GetPicture( pic_num
).OrigData(U_COMP
) , me_data
, U_COMP
);
571 SetDC( my_buffer
.GetPicture( pic_num
).OrigData(V_COMP
) , me_data
, V_COMP
);