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)
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
36 * ***** END LICENSE BLOCK ***** */
39 #include <libdirac_encoder/enc_queue.h>
40 #include <libdirac_motionest/motion_estimate.h>
41 #include <libdirac_motionest/pixel_match.h>
42 #include <libdirac_motionest/me_subpel.h>
43 #include <libdirac_motionest/me_mode_decn.h>
44 using namespace dirac
;
49 MotionEstimator::MotionEstimator( const EncoderParams
& encp
):
53 void MotionEstimator::DoME( EncQueue
& my_buffer
, int pic_num
)
55 MEData
& me_data
= my_buffer
.GetPicture( pic_num
).GetMEData();
57 const PictureParams
& pparams
= my_buffer
.GetPicture(pic_num
).GetPparams();
60 //Initial search gives vectors for each reference accurate to 1 pixel
62 PixelMatcher
pix_match( m_encparams
);
63 pix_match
.DoSearch( my_buffer
, pic_num
);
67 const std::vector
<int>& refs
= my_buffer
.GetPicture(pic_num
).GetPparams().Refs();
69 const int num_refs
= refs
.size();
70 if ( pparams
.IsBPicture())
71 lambda
= m_encparams
.L2MELambda();
73 lambda
= m_encparams
.L1MELambda();
75 // Set up the lambda to be used
76 me_data
.SetLambdaMap( num_refs
, lambda
);
78 MVPrecisionType orig_prec
= m_encparams
.MVPrecision();
81 // Pixel accurate vectors are then refined to sub-pixel accuracy
83 if (orig_prec
!= MV_PRECISION_PIXEL
)
85 SubpelRefine
pelrefine( m_encparams
);
86 pelrefine
.DoSubpel( my_buffer
, pic_num
);
91 // Mutiplying the motion vectors by 2 and setting MV precision to
92 // HALF_PIXEL to implement pixel accurate motion estimate
93 MvArray
&mv_arr1
= me_data
.Vectors(1);
94 for (int j
= 0; j
< mv_arr1
.LengthY(); ++j
)
96 for (int i
= 0; i
< mv_arr1
.LengthX(); ++i
)
97 mv_arr1
[j
][i
] = mv_arr1
[j
][i
] << 1;
101 MvArray
&mv_arr2
= me_data
.Vectors(2);
102 for (int j
= 0; j
< mv_arr2
.LengthY(); ++j
)
104 for (int i
= 0; i
< mv_arr2
.LengthX(); ++i
)
105 mv_arr2
[j
][i
] = mv_arr2
[j
][i
] << 1;
108 m_encparams
.SetMVPrecision(MV_PRECISION_HALF_PIXEL
);
112 // We now have to decide how each superblock should be split
113 // and which references should be used, and so on.
115 ModeDecider
my_mode_dec( m_encparams
);
116 my_mode_dec
.DoModeDecn( my_buffer
, pic_num
);
118 if (orig_prec
== MV_PRECISION_PIXEL
)
121 // Divide the motion vectors by 2 to convert back to pixel
122 // accurate motion vectors and reset MV precision to
124 MvArray
&mv_arr1
= me_data
.Vectors(1);
125 for (int j
= 0; j
< mv_arr1
.LengthY(); ++j
)
127 for (int i
= 0; i
< mv_arr1
.LengthX(); ++i
)
128 mv_arr1
[j
][i
] = mv_arr1
[j
][i
] >> 1;
132 MvArray
&mv_arr2
= me_data
.Vectors(2);
133 for (int j
= 0; j
< mv_arr2
.LengthY(); ++j
)
135 for (int i
= 0; i
< mv_arr2
.LengthX(); ++i
)
136 mv_arr2
[j
][i
] = mv_arr2
[j
][i
]>>1;
139 m_encparams
.SetMVPrecision(MV_PRECISION_PIXEL
);
142 // Finally, although not strictly part of motion estimation,
143 // we have to assign DC values for chroma components for
144 // blocks we're decided are intra.
146 SetChromaDC( my_buffer
, pic_num
);
151 ValueType
MotionEstimator::GetChromaBlockDC(const PicArray
& pic_data
,
152 int xunit
, int yunit
, int split
)
154 BlockDiffParams dparams
;
155 dparams
.SetBlockLimits( m_encparams
.ChromaBParams( split
) ,
156 pic_data
, xunit
, yunit
);
160 IntraBlockDiff
intradiff( pic_data
);
162 intradiff
.Diff( dparams
, dc
);
167 void MotionEstimator::SetChromaDC( const PicArray
& pic_data
, MEData
& me_data
, CompSort csort
)
170 // Lower limit of block coords in SB
172 // Upper limit of block coords in SB
176 int xsubSBtl
,ysubSBtl
;
177 int xsubSBbr
,ysubSBbr
;
179 TwoDArray
<ValueType
>& dcarray
= me_data
.DC( csort
);
183 // Coords of the prediction units (at appropriate level)
186 // The delimiters of the blocks contained in the prediction unit
192 for ( int ysb
=0 ; ysb
<me_data
.SBSplit().LengthY() ; ++ysb
)
194 for ( int xsb
=0 ; xsb
<me_data
.SBSplit().LengthX() ; ++xsb
)
197 level
= me_data
.SBSplit()[ysb
][xsb
];
206 xsubSBbr
= xsubSBtl
+2;
207 ysubSBbr
= ysubSBtl
+2;
210 for (int j
= 0 ; j
<(1<<level
) ;++j
)
212 for (int i
= 0 ; i
<(1<<level
) ;++i
)
214 xunit
= ( xsb
<<level
) + i
;
215 yunit
= ( ysb
<<level
) + j
;
217 xstart
= xunit
<<( 2-level
);
218 ystart
= yunit
<<( 2-level
);
220 xend
= xstart
+ ( 1<<( 2-level
) );
221 yend
= ystart
+ ( 1<<( 2-level
) );
223 if ( me_data
.Mode()[ystart
][xstart
] == INTRA
)
224 // Get the DC value for the unit
225 dc
= GetChromaBlockDC( pic_data
, xunit
, yunit
, level
);
227 // Copy it into the corresponding blocks
228 for ( int q
=ystart
; q
< yend
; ++q
)
229 for ( int p
=xstart
; p
< xend
; ++p
)
239 void MotionEstimator::SetChromaDC( EncQueue
& my_buffer
, int pic_num
)
241 MEData
& me_data
= my_buffer
.GetPicture(pic_num
).GetMEData();
242 SetChromaDC( my_buffer
.GetPicture( pic_num
).OrigData(U_COMP
) , me_data
, U_COMP
);
243 SetChromaDC( my_buffer
.GetPicture( pic_num
).OrigData(V_COMP
) , me_data
, V_COMP
);