00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include <libdirac_common/mot_comp.h>
00042 #include <libdirac_common/motion.h>
00043 #include <libdirac_common/frame_buffer.h>
00044 using namespace dirac;
00045
00046 using std::vector;
00047
00048
00050
00051
00052
00053
00054
00055
00056
00057 MotionCompensator::MotionCompensator( const CodecParams &cp , const AddOrSub direction ):
00058 m_cparams(cp),
00059 luma_or_chroma(true),
00060 m_add_or_sub( direction )
00061 {
00062
00063 m_block_weights = NULL;
00064 m_half_block_weights = NULL;
00065 ReConfig();
00066 }
00067
00068
00069 MotionCompensator::~MotionCompensator(){
00070
00071
00072 delete[] m_block_weights;
00073 delete[] m_half_block_weights;
00074 }
00075
00076
00077 void MotionCompensator::CompensateFrame(FrameBuffer& my_buffer,int fnum,const MvData& mv_data)
00078 {
00079
00080 int ref1_idx,ref2_idx;
00081 Frame& my_frame=my_buffer.GetFrame(fnum);
00082 const FrameSort& fsort=my_frame.GetFparams().FSort();
00083
00084 m_cformat = my_frame.GetFparams().CFormat();
00085
00086 if (fsort!=I_frame)
00087 {
00088
00089 const vector<int>& refs=my_frame.GetFparams().Refs();
00090 if (refs.size()>0)
00091 {
00092
00093 ref1_idx=refs[0];
00094 if (refs.size()>1)
00095 ref2_idx=refs[1];
00096 else
00097 ref2_idx=refs[0];
00098
00099 const Frame& ref1frame=my_buffer.GetFrame(ref1_idx);
00100 const Frame& ref2frame=my_buffer.GetFrame(ref2_idx);
00101
00102 luma_or_chroma = true;
00103
00104 CompensateComponent( my_frame , ref1frame , ref2frame , mv_data , Y_COMP);
00105
00106 if ( m_cformat != Yonly )
00107 {
00108 luma_or_chroma = false;
00109 CompensateComponent( my_frame , ref1frame , ref2frame , mv_data , U_COMP);
00110 CompensateComponent( my_frame , ref1frame , ref2frame , mv_data , V_COMP);
00111 }
00112 }
00113 }
00114 }
00115
00116
00118
00119
00120
00121
00122
00123 void MotionCompensator::ReConfig()
00124 {
00125 if (luma_or_chroma)
00126 m_bparams = m_cparams.LumaBParams(2);
00127 else
00128 m_bparams = m_cparams.ChromaBParams(2);
00129
00130 if(m_block_weights != NULL)
00131 delete[] m_block_weights;
00132
00133 if(m_half_block_weights != NULL)
00134 delete[] m_half_block_weights;
00135
00136
00137 m_block_weights = new TwoDArray<CalcValueType>[9];
00138 m_half_block_weights = new TwoDArray<CalcValueType>[9];
00139 for(int i = 0; i < 9; i++)
00140 {
00141 m_block_weights[i].Resize( m_bparams.Yblen() , m_bparams.Xblen() );
00142 m_half_block_weights[i].Resize( m_bparams.Yblen() , m_bparams.Xblen() );
00143 }
00144
00145
00146 CreateBlock( m_bparams , false , false , m_half_block_weights[0] );
00147 CreateBlock( m_bparams , false , true , m_half_block_weights[3] );
00148 CreateBlock( m_bparams , true , false , m_half_block_weights[1] );
00149 CreateBlock( m_bparams , true , true , m_half_block_weights[4] );
00150
00151
00152 FlipX( m_half_block_weights[3] , m_bparams , m_half_block_weights[5] );
00153 FlipX( m_half_block_weights[0] , m_bparams , m_half_block_weights[2] );
00154 FlipY( m_half_block_weights[0] , m_bparams , m_half_block_weights[6] );
00155 FlipX( m_half_block_weights[6] , m_bparams , m_half_block_weights[8] );
00156 FlipY( m_half_block_weights[1] , m_bparams , m_half_block_weights[7] );
00157
00158 for( int k = 0; k < 9; k++)
00159 {
00160 for ( int j =m_half_block_weights[k].FirstY(); j <= m_half_block_weights[k].LastY(); j++)
00161 {
00162 for ( int i =m_half_block_weights[k].FirstX(); i <= m_half_block_weights[k].LastX(); i++)
00163 {
00164 m_block_weights[k][j][i] = m_half_block_weights[k][j][i] << 1;
00165 }
00166 }
00167 }
00168 }
00169
00170 void MotionCompensator::CompensateComponent(Frame& picframe, const Frame &ref1frame, const Frame& ref2frame,
00171 const MvData& mv_data,const CompSort cs)
00172 {
00173
00174 PicArray& pic_data_out = picframe.Data( cs );
00175
00176 const PicArray& ref1up = ref1frame.UpData( cs );
00177 const PicArray& ref2up = ref2frame.UpData( cs );
00178
00179
00180
00181 TwoDArray<CalcValueType> pic_data(pic_data_out.LengthY(), pic_data_out.LengthX() , 0);
00182
00183
00184 int xscale_factor = 1;
00185 int yscale_factor = 1;
00186
00187 if ( cs != Y_COMP )
00188 {
00189 if (m_cformat == format420)
00190 {
00191 xscale_factor = 2;
00192 yscale_factor = 2;
00193 }
00194 else if (m_cformat == format422)
00195 {
00196 xscale_factor = 2;
00197 yscale_factor = 1;
00198 }
00199 else if (m_cformat == format411)
00200 {
00201 xscale_factor = 4;
00202 yscale_factor = 1;
00203 }
00204
00205 }
00206
00207
00208 const TwoDArray<ValueType>& dcarray = mv_data.DC( cs );
00209
00210
00211 const int num_refs = picframe.GetFparams().Refs().size();
00212 const MvArray* mv_array1;
00213 const MvArray* mv_array2;
00214 mv_array1 = &mv_data.Vectors(1);
00215 if (num_refs ==2 )
00216 mv_array2 = &mv_data.Vectors(2);
00217 else
00218 mv_array2 = &mv_data.Vectors(1);
00219
00220 ReConfig();
00221
00222
00223 MVector mv1,mv2;
00224 PredMode block_mode;
00225 ValueType dc;
00226
00227
00228 ImageCoords pos;
00229
00230
00231
00232
00233 size_t wgt_idx;
00234
00235
00236
00237 pos.y = -m_bparams.Yoffset();
00238 for(int yblock = 0; yblock < m_cparams.YNumBlocks(); ++yblock)
00239 {
00240 pos.x = -m_bparams.Xoffset();
00241
00242 for(int xblock = 0 ; xblock < m_cparams.XNumBlocks(); ++xblock)
00243 {
00244
00245
00246 if((xblock != 0)&&(xblock < m_cparams.XNumBlocks() - 1))
00247 {
00248 if((yblock != 0)&&(yblock < m_cparams.YNumBlocks() - 1))
00249 wgt_idx = 4;
00250 else if(yblock == 0)
00251 wgt_idx = 1;
00252 else
00253 wgt_idx= 7;
00254 }
00255 else if(xblock == 0)
00256 {
00257 if((yblock != 0)&&(yblock < m_cparams.YNumBlocks() - 1))
00258 wgt_idx = 3;
00259 else if(yblock == 0)
00260 wgt_idx = 0;
00261 else
00262 wgt_idx = 6;
00263 }
00264 else
00265 {
00266 if((yblock != 0)&&(yblock < m_cparams.YNumBlocks() - 1))
00267 wgt_idx = 5;
00268 else if(yblock == 0)
00269 wgt_idx = 2;
00270 else
00271 wgt_idx = 8;
00272 }
00273
00274 block_mode = mv_data.Mode()[yblock][xblock];
00275 mv1 = (*mv_array1)[yblock][xblock];
00276 mv1.x /= xscale_factor;
00277 mv1.y /= yscale_factor;
00278
00279 mv2 = (*mv_array2)[yblock][xblock];
00280 mv2.x /= xscale_factor;
00281 mv2.y /= yscale_factor;
00282
00283
00284 dc = dcarray[yblock][xblock]<<2;
00285
00286
00287 if(block_mode == REF1_ONLY)
00288 {
00289 CompensateBlock(pic_data, ref1up, mv1, pos, m_block_weights[wgt_idx]);
00290 }
00291 else if (block_mode == REF2_ONLY)
00292 {
00293 CompensateBlock(pic_data, ref2up, mv2, pos, m_block_weights[wgt_idx]);
00294 }
00295 else if(block_mode == REF1AND2)
00296 {
00297 CompensateBlock(pic_data, ref1up, mv1, pos, m_half_block_weights[wgt_idx]);
00298 CompensateBlock(pic_data, ref2up, mv2, pos, m_half_block_weights[wgt_idx]);
00299 }
00300 else
00301 {
00302 DCBlock(pic_data, dc,pos, m_block_weights[wgt_idx]);
00303 }
00304
00305
00306 pos.x += m_bparams.Xbsep();
00307
00308 }
00309
00310
00311 pos.y += m_bparams.Ybsep();
00312
00313 }
00314
00315 if ( m_add_or_sub == SUBTRACT)
00316 {
00317 int x_end_data = std::min(pic_data.LastX(), m_cparams.XNumBlocks()*m_bparams.Xbsep() );
00318 int y_end_data = std::min(pic_data.LastY(), m_cparams.YNumBlocks()*m_bparams.Ybsep() );
00319
00320 for ( int i =pic_data.FirstY(); i <= y_end_data; i++)
00321 {
00322 for ( int j =pic_data.FirstX(); j <= x_end_data; ++j)
00323 {
00324 pic_data_out[i][j] -= static_cast<ValueType>( (pic_data[i][j] + 1024) >> 11 );
00325 }
00326
00327
00328
00329
00330
00331
00332 for (int j=( m_cparams.XNumBlocks()*m_bparams.Xbsep() ); j<pic_data.LengthX() ; ++j )
00333 {
00334 pic_data_out[i][j] = 0;
00335 }
00336 }
00337
00338
00339 for ( int y=m_cparams.YNumBlocks()*m_bparams.Ybsep() ; y<pic_data.LengthY() ; ++y )
00340 {
00341 for ( int x=0 ; x<pic_data.LengthX() ; ++x )
00342 {
00343 pic_data_out[y][x] = 0;
00344 }
00345
00346 }
00347 }
00348 else
00349 {
00350 for ( int i =pic_data.FirstY(); i <= pic_data.LastY(); i++)
00351 {
00352 for ( int j =pic_data.FirstX(); j <= pic_data.LastX(); j++)
00353 {
00354 pic_data_out[i][j] += static_cast<ValueType>( (pic_data[i][j] + 1024) >> 11 );
00355 }
00356 }
00357 }
00358 }
00359
00360 void MotionCompensator::CompensateBlock( TwoDArray<CalcValueType> &pic_data , const PicArray &refup_data , const MVector &mv ,
00361 const ImageCoords& pos , const TwoDArray<CalcValueType>& wt_array )
00362 {
00363
00364
00365 const ImageCoords start_pos( std::max(pos.x,0) , std::max(pos.y,0) );
00366 const ImageCoords end_pos( std::min( pos.x + m_bparams.Xblen() , pic_data.LengthX() ) ,
00367 std::min( pos.y + m_bparams.Yblen() , pic_data.LengthY() ) );
00368
00369
00370
00371 const ImageCoords diff( start_pos.x - pos.x , start_pos.y - pos.y );
00372
00373
00374
00375 const MVector roundvec( mv.x>>2 , mv.y>>2 );
00376
00377
00378 const MVector rmdr( mv.x - ( roundvec.x<<2 ) , mv.y - ( roundvec.y<<2 ) );
00379
00380
00381 const ImageCoords ref_start( ( start_pos.x<<1 ) + roundvec.x ,( start_pos.y<<1 ) + roundvec.y );
00382
00383
00384 const ValueType TLweight( (4 - rmdr.x) * (4 - rmdr.y) );
00385 const ValueType TRweight( rmdr.x * ( 4 - rmdr.y ) );
00386 const ValueType BLweight( ( 4 - rmdr.x ) * rmdr.y );
00387 const ValueType BRweight( rmdr.x * rmdr.y );
00388
00389
00390
00391 const int refXlen = refup_data.LengthX();
00392 const int refYlen = refup_data.LengthY();
00393 bool do_bounds_checking = false;
00394
00395
00396
00397 if( ref_start.x < 0 )
00398 do_bounds_checking = true;
00399 else if( ref_start.x + ((end_pos.x - start_pos.x)<<1 ) >= refXlen )
00400 do_bounds_checking = true;
00401 if( ref_start.y < 0 )
00402 do_bounds_checking = true;
00403 else if( ref_start.y + ((end_pos.y - start_pos.y)<<1 ) >= refYlen)
00404 do_bounds_checking = true;
00405
00406 if( !do_bounds_checking )
00407 {
00408 for(int c = start_pos.y, wY = diff.y, uY = ref_start.y; c < end_pos.y; ++c, ++wY, uY += 2)
00409 {
00410 for(int l = start_pos.x, wX = diff.x, uX = ref_start.x; l < end_pos.x; ++l, ++wX, uX += 2)
00411 {
00412
00413 pic_data[c][l] += (( TLweight * refup_data[uY][uX] +
00414 TRweight * refup_data[uY][uX+1] +
00415 BLweight * refup_data[uY+1][uX] +
00416 BRweight * refup_data[uY+1][uX+1] +
00417 8
00418 ) >> 4) * wt_array[wY][wX];
00419 }
00420 }
00421 }
00422 else
00423 {
00424
00425
00426 for(int c = start_pos.y, wY = diff.y, uY = ref_start.y,BuY=BChk(uY,refYlen),BuY1=BChk(uY+1,refYlen);
00427 c < end_pos.y; ++c, ++wY, uY += 2,BuY=BChk(uY,refYlen),BuY1=BChk(uY+1,refYlen))
00428 {
00429 for(int l = start_pos.x, wX = diff.x, uX = ref_start.x,BuX=BChk(uX,refXlen),BuX1=BChk(uX+1,refXlen);
00430 l < end_pos.x; ++l, ++wX, uX += 2,BuX=BChk(uX,refXlen),BuX1=BChk(uX+1,refXlen))
00431 {
00432
00433 pic_data[c][l] += (( TLweight * refup_data[BuY][BuX] +
00434 TRweight * refup_data[BuY][BuX1] +
00435 BLweight * refup_data[BuY1][BuX]+
00436 BRweight * refup_data[BuY1][BuX1] +
00437 8
00438 ) >> 4) * wt_array[wY][wX];
00439 }
00440 }
00441
00442 }
00443
00444 }
00445
00446 void MotionCompensator::DCBlock( TwoDArray<CalcValueType> &pic_data ,const ValueType dc , const ImageCoords& pos ,
00447 const TwoDArray<CalcValueType>& wt_array)
00448 {
00449
00450
00451 const ImageCoords start_pos( std::max(0 , pos.x) , std::max(0 , pos.y) );
00452 const ImageCoords end_pos( std::min(pos.x + m_bparams.Xblen() , pic_data.LengthX() ) ,
00453 std::min(pos.y + m_bparams.Yblen() , pic_data.LengthY() ) );
00454
00455
00456
00457 const ImageCoords diff(start_pos.x - pos.x , start_pos.y - pos.y);
00458
00459
00460
00461 for(int c = start_pos.y, wY = diff.y; c < end_pos.y; ++c, ++wY)
00462 {
00463 for(int l = start_pos.x, wX = diff.x; l < end_pos.x; ++l, ++wX)
00464 {
00465 pic_data[c][l] += dc * wt_array[wY][wX];
00466 }
00467 }
00468 }
00469
00470
00471
00472 float MotionCompensator::RaisedCosine(float t, float B)
00473 {
00474 if(std::abs(t)>(B+1.0)/2.0)
00475 return 0.0f;
00476 else if(std::abs(t)<(1.0-B)/2.0)
00477 return 1.0f;
00478 else
00479 return( 0.5 * ( 1.0 + std::cos( 3.141592654 * ( std::abs(t)-(1.0-B)/2.0 )/B ) ) );
00480 }
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493 void MotionCompensator::CreateBlock(const OLBParams &bparams, bool FullX, bool FullY, TwoDArray<CalcValueType>& WeightArray)
00494 {
00495
00496 OneDArray<CalcValueType> HWts( WeightArray.LengthX() );
00497 OneDArray<CalcValueType> VWts( WeightArray.LengthY() );
00498
00499
00500 float rolloffX = (float(bparams.Xblen()+1)/float(bparams.Xbsep())) - 1;
00501 float rolloffY = (float(bparams.Yblen()+1)/float(bparams.Ybsep())) - 1;
00502 float val;
00503
00504
00505 for(int x = 0; x < bparams.Xblen(); ++x)
00506 {
00507 val = (float(x) - (float(bparams.Xblen()-1)/2.0))/float(bparams.Xbsep());
00508 HWts[x] = static_cast<CalcValueType>( 32.0 * RaisedCosine(val,rolloffX) );
00509 HWts[x] = std::max( HWts[x] , 1 );
00510 HWts[x] = std::min( HWts[x] , 32 );
00511 }
00512
00513
00514 for(int y = 0; y < bparams.Yblen(); ++y)
00515 {
00516 val = (float(y) - (float(bparams.Yblen()-1)/2.0))/float(bparams.Ybsep());
00517 VWts[y] = static_cast<CalcValueType>( 32.0 * RaisedCosine(val,rolloffY) );
00518 VWts[y] = std::max( VWts[y] , 1 );
00519 VWts[y] = std::min( VWts[y] , 32 );
00520 }
00521
00522
00523 for(int x = HWts.Last(); x > HWts.Last()-bparams.Xoffset(); --x)
00524 {
00525 if (HWts[x] + HWts[HWts.Last()-(x-bparams.Xbsep())] > 32)
00526 HWts[HWts.Last()-(x-bparams.Xbsep())] = 32-HWts[x];
00527
00528 else if (HWts[x] + HWts[HWts.Last()-(x-bparams.Xbsep())] < 32)
00529 HWts[x] = 32-HWts[HWts.Last()-(x-bparams.Xbsep())];
00530 }
00531
00532
00533 if (!FullX)
00534 {
00535 for( int x = 0; x < (bparams.Xblen()>>1) ; ++x)
00536 HWts[x] = 32;
00537 }
00538 else
00539 {
00540 for( int x = 0; x < (bparams.Xblen()>>1); ++x)
00541 HWts[x] = HWts[HWts.Last()-x];
00542 }
00543
00544
00545 for(int y = VWts.Last(); y > VWts.Last()-bparams.Yoffset(); --y)
00546 {
00547 if (VWts[y] + VWts[VWts.Last()-(y-bparams.Ybsep())] > 32)
00548 VWts[VWts.Last()-(y-bparams.Ybsep())] = 32-VWts[y];
00549 else if (VWts[y] + VWts[VWts.Last()-(y-bparams.Ybsep())] < 32)
00550 VWts[y] = 32-VWts[VWts.Last()-(y-bparams.Ybsep())];
00551 }
00552
00553
00554 if (!FullY)
00555 {
00556 for( int y = 0 ; y < (bparams.Yblen()>>1); ++y)
00557 VWts[y] = 32;
00558 }
00559 else
00560 {
00561 for( int y = 0 ; y < (bparams.Yblen()>>1); ++y)
00562 VWts[y] = VWts[VWts.Last()-y];
00563 }
00564
00565 for(int y = 0; y < bparams.Yblen(); ++y)
00566 {
00567 for(int x = 0; x < bparams.Xblen(); ++x)
00568 {
00569 WeightArray[y][x] = VWts[y] * HWts[x];
00570 }
00571 }
00572
00573 }
00574
00575
00576 void MotionCompensator::FlipX(const TwoDArray<CalcValueType>& Original, const OLBParams &bparams, TwoDArray<CalcValueType>& Flipped)
00577 {
00578 for(int x = 0; x < bparams.Xblen(); ++x)
00579 {
00580 for(int y = 0; y < bparams.Yblen(); ++y)
00581 {
00582 Flipped[y][x] = Original[y][(bparams.Xblen()-1) - x];
00583 }
00584 }
00585 }
00586
00587
00588 void MotionCompensator::FlipY(const TwoDArray<CalcValueType>& Original, const OLBParams &bparams, TwoDArray<CalcValueType>& Flipped)
00589 {
00590 for(int x = 0; x < bparams.Xblen(); ++x)
00591 {
00592 for(int y = 0; y < bparams.Yblen(); ++y)
00593 {
00594 Flipped[y][x] = Original[(bparams.Yblen()-1) - y][x];
00595 }
00596 }
00597 }