Exemplo n.º 1
0
void MvDataCodec::CodePredmode(const MvData& in_data)
{
    int val = in_data.Mode()[b_yp][b_xp] - BlockModePrediction( in_data.Mode() ); 
    
    if (val < 0)
        val += 4;  //produce value mod 4    
    
    for (int bin = 1;  bin<= val;  ++bin)
        EncodeSymbol( 0 , ChoosePredContext( in_data , bin ) ); 
                 
    if (val  !=  3) //if we've had three zeroes, know we must have value 3
        EncodeSymbol( 1 , ChoosePredContext( in_data , val + 1 ) ); 
}
Exemplo n.º 2
0
void MvDataCodec::CodeMv2(const MvData& in_data)
{
    const MvArray& mv_array = in_data.Vectors(2);
    const MVector pred = Mv2Prediction( mv_array , in_data.Mode() );     

    const int valx = mv_array[b_yp][b_xp].x - pred.x; 
    const int abs_valx = abs(valx); 
    
    for (int bin = 1; bin <= abs_valx; ++bin)
        EncodeSymbol( 0 , ChooseREF2xContext( in_data , bin ) ); 

    EncodeSymbol( 1 , ChooseREF2xContext( in_data , abs_valx + 1 ) ); 
    
    if (valx != 0)
        EncodeSymbol( ( (valx > 0)? 1 : 0) , ChooseREF2xSignContext( in_data ) ); 

    const int valy = mv_array[b_yp][b_xp].y-pred.y; 
    const int abs_valy = std::abs(valy);     
    
    for (int bin = 1; bin<=abs_valy; ++bin )
        EncodeSymbol( 0 , ChooseREF2yContext( in_data , bin ) ); 
    
    EncodeSymbol( 1 , ChooseREF2yContext( in_data , abs_valy + 1 ) ); 
    
    if (valy != 0)
        EncodeSymbol( ( (valy > 0)? 1 : 0) , ChooseREF2ySignContext( in_data ) ); 
}
Exemplo n.º 3
0
void MvDataCodec::CodeDC(const MvData& in_data)
{    
    //begin with Y DC value    
    const ValueType valY = in_data.DC( Y_COMP )[b_yp][b_xp]
                           - DCPrediction( in_data.DC(Y_COMP) , in_data.Mode() ); 
    const ValueType abs_valY = std::abs( valY ); 

    for (ValueType bin = 1; bin <= abs_valY; ++bin)
        EncodeSymbol( 0 , ChooseYDCContext( in_data , bin ) ); 

    EncodeSymbol( 1 , ChooseYDCContext (in_data , abs_valY + 1 ) ); 
    
    if (valY != 0)
        EncodeSymbol( ( (valY > 0)? 1 : 0) , ChooseYDCSignContext( in_data ) ); 

    //now do U and V if necessary
    if (m_cformat != Yonly)
    {
        //continue with U and V DC values
        const int valU =  in_data.DC(U_COMP)[b_yp][b_xp]
                          - DCPrediction(in_data.DC( U_COMP ) , in_data.Mode()); 
        const int abs_valU = std::abs( valU ); 

        for (ValueType bin = 1;  bin<=abs_valU ; ++bin)
            EncodeSymbol( 0 , ChooseUDCContext( in_data , bin ) ); 
        
        EncodeSymbol( 1 , ChooseUDCContext( in_data , abs_valU + 1 ) ); 
        
        if (valU != 0)
            EncodeSymbol( ( (valU > 0) ? 1 : 0) , ChooseUDCSignContext( in_data ) ); 
        
        const int valV = in_data.DC( V_COMP )[b_yp][b_xp] 
                         - DCPrediction( in_data.DC( V_COMP ) , in_data.Mode() ); 
        const int abs_valV = std::abs( valV ); 

        for (ValueType bin = 1; bin<=abs_valV ; ++bin)
            EncodeSymbol( 0 , ChooseVDCContext( in_data , bin ) ); 

        EncodeSymbol( 1 , ChooseVDCContext( in_data , abs_valV + 1 ) ); 
        
        if (valV != 0)
            EncodeSymbol( ( (valV > 0)? 1 : 0) , ChooseVDCSignContext( in_data ) ); 
    }
}
Exemplo n.º 4
0
void MvDataCodec::DecodePredmode( MvData& out_data )
{
    int val = 0; 
    int bin = 1; 
    bool bit; 
    
    do
    {
        DecodeSymbol( bit , ChoosePredContext( out_data , bin ) ); 
        
        if (!bit)
            val++; 
        
        bin++; 
    }
    while (!bit && val != 3);  
    
    out_data.Mode()[b_yp][b_xp] = PredMode( ( val + BlockModePrediction (out_data.Mode() ) ) %4); 
}
Exemplo n.º 5
0
void MvDataCodec::DecodeMv2( MvData& out_data )
{
    MVector pred = Mv2Prediction( out_data.Vectors(2) , out_data.Mode() ); 
    int val = 0; 
    int bin = 1; 
    bool bit; 
    
    do
    {
        DecodeSymbol( bit , ChooseREF2xContext( out_data , bin ) ); 
        
        if ( !bit )
            val++; 
        
        bin++; 
    }
    while ( !bit ); 
    
    if (val != 0)
    {
        DecodeSymbol( bit , ChooseREF2xSignContext( out_data ) ); 
        
        if (!bit)
            val = -val; 
    }
    
    out_data.Vectors(2)[b_yp][b_xp].x = val + pred.x; 

    val = 0; 
    bin = 1; 
    
    do
    {
        DecodeSymbol( bit , ChooseREF2yContext( out_data , bin ) ); 
        
        if ( !bit )
            val++; 
        
        bin++; 
    }
    while ( !bit ); 
    
    if (val != 0)
    {
        DecodeSymbol( bit , ChooseREF2ySignContext( out_data ) ); 
        
        if ( !bit )
            val = -val; 
    }
    
    out_data.Vectors(2)[b_yp][b_xp].y = val + pred.y; 
}
Exemplo n.º 6
0
// Main decode function
void PredModeCodec::DoWorkDecode( MvData& out_data)
{
    int step,max; 
    int split_depth; 
    int xstart,ystart;     

    // Then the prediction mode
    for (m_sb_yp = 0,m_sb_tlb_y = 0; m_sb_yp < out_data.SBSplit().LengthY(); ++m_sb_yp,m_sb_tlb_y += 4)
    {
        for (m_sb_xp = 0,m_sb_tlb_x = 0; m_sb_xp < out_data.SBSplit().LengthX(); ++m_sb_xp,m_sb_tlb_x += 4)
        {
            split_depth = out_data.SBSplit()[m_sb_yp][m_sb_xp]; 
            step =  4  >>  (split_depth); 
            max  = (1 << split_depth); 

            //now do all the block mvs in the mb
            for (int j = 0; j < max; ++j)
            {                
                for (int i = 0; i < max; ++i)
                {
                    xstart = m_b_xp = m_sb_tlb_x + i * step; 
                    ystart = m_b_yp = m_sb_tlb_y + j * step;                                             
                    
                    DecodeVal(out_data); 

                    // propagate throughout SB    
                    for (m_b_yp = ystart; m_b_yp < ystart+step; m_b_yp++)
                    {
                        for (m_b_xp = xstart; m_b_xp < xstart+step; m_b_xp++)
                        {                    
                            out_data.Mode()[m_b_yp][m_b_xp] = out_data.Mode()[ystart][xstart]; 
                        }//m_b_xp
                    }//m_b_yp
                }//i                    
            }//j

        }//m_sb_xp
    }//m_sb_yp
}  
Exemplo n.º 7
0
void MotionCompensator::CompensateComponent( Picture* pic ,
                                             Picture* refsptr[2] ,
                                             const MvData& mv_data ,
                                             const CompSort cs )
{
    // Set up references to pictures and references
    PicArray& pic_data_out = pic->Data( cs );

    // Size of picture component being motion compensated

    const PicArray& ref1up = refsptr[0]->UpData( cs );
    const PicArray& ref2up = refsptr[1]->UpData( cs );

    // Set up a row of blocks which will contain the MC data, which
    // we'll add or subtract to pic_data_out
    TwoDArray<ValueType> pic_data(m_bparams.Yblen(), pic_data_out.LengthX(), 0 );

    // Factors to compensate for subsampling of chroma
    int xscale_shift = 0;
    int yscale_shift = 0;
    if ( cs != Y_COMP )
    {
        if (m_cformat == format420)
        {
            xscale_shift = 1;
            yscale_shift = 1;
        }
        else if (m_cformat == format422)
        {
            xscale_shift = 1;
            yscale_shift = 0;
        }
    }

    ImageCoords pic_size(pic->GetPparams().Xl(), pic->GetPparams().Yl());
    if ( cs != Y_COMP )
    {
        pic_size.x = pic->GetPparams().ChromaXl();
        pic_size.y = pic->GetPparams().ChromaYl();
    }


    // Reference to the relevant DC array
    const TwoDArray<ValueType>& dcarray = mv_data.DC( cs );

    // Set up references to the vectors
    const int num_refs = pic->GetPparams().Refs().size();
    const MvArray* mv_array1;
    const MvArray* mv_array2;
    mv_array1 = &mv_data.Vectors(1);
    if (num_refs ==2 )
        mv_array2 = &mv_data.Vectors(2);
    else
        mv_array2 = &mv_data.Vectors(1);

    ReConfig();//set all the weighting blocks up

    //Blocks are listed left to right, line by line.
    MVector mv1,mv2;
    PredMode block_mode;

    //Coords of the top-left corner of a block
    ImageCoords pos;

    //Loop for each block in the output image.
    //The CompensateBlock function will use the image pointed to by ref1up
    //and add the compensated pixels to the image pointed to by pic_data.
    size_t wgt_idx;

    int save_from_row = m_bparams.Ybsep()-m_bparams.Yoffset();

    // unpadded picture dimensions
    const int x_end_data = pic_data_out.FirstX() + std::min(pic_data_out.LengthX(), pic_size.x );
    const int y_end_data = pic_data_out.FirstY() + std::min(pic_data_out.LengthY(), pic_size.y );

    const int blocks_per_mb_row = m_predparams.XNumBlocks()/m_predparams.XNumSB();
    const int blocks_per_sb_row = blocks_per_mb_row>>1;

    // The picture does not contain integral number of blocks. So not all
    // blocks need to be processed. Compute the relevant blocks to be
    // processed 
    int y_num_blocks = std::min((NUM_USED_BLKS(pic_size.y,m_bparams.Ybsep(),m_bparams.Yblen())), 
                       m_predparams.YNumBlocks());
    int x_num_blocks = std::min((NUM_USED_BLKS(pic_size.x,m_bparams.Xbsep(),m_bparams.Xblen())),  
                       m_predparams.XNumBlocks());

    //Loop over all the block rows
    pos.y = -m_bparams.Yoffset();
    for(int yblock = 0; yblock < y_num_blocks; ++yblock)
    {
        pos.x = -m_bparams.Xoffset();
        int xincr, xb_incr = 0;
        //loop over all the blocks in a row
        for(int xblock = 0 ; xblock < x_num_blocks; xblock+=xb_incr)
        {
            int split_mode =  mv_data.SBSplit()[yblock/blocks_per_mb_row][xblock/blocks_per_mb_row];

            int blk_x, blk_y = 1;

            switch (split_mode)
            {
            case 0: // processing superblock
                blk_x = blocks_per_mb_row;
                break;
            case 1: // processing sub-superblock
                blk_x = blocks_per_sb_row;
                break;
            case 2: // processing block
            default:
                blk_x = 1;
                break;
            }

            //Decide which weights to use.
            if (pos.x >=0 && (xblock+blk_x) < x_num_blocks)
            {
                // block is entirely within picture in x direction
                if (pos.y < 0)
                    wgt_idx = 1;
                else if ((yblock+blk_y) < y_num_blocks)
                    wgt_idx = 4;
                else
                    wgt_idx = 7;
            }
            else if (pos.x < 0)
            {
                // left edge of block is outside picture in x direction
                if (pos.y < 0)
                    wgt_idx = 0;
                else if ((yblock+blk_y) < y_num_blocks)
                    wgt_idx = 3;
                else
                    wgt_idx = 6;
            }
            else
            {
                // right edge of block is outside picture in x direction
                if (pos.y < 0)
                    wgt_idx = 2;
                else if ((yblock+blk_y) < y_num_blocks)
                    wgt_idx = 5;
                else
                    wgt_idx = 8;
            }


            block_mode = mv_data.Mode()[yblock][xblock];

            TwoDArray<ValueType> *wt;

            if (split_mode == 0) //Block part of a MacroBlock
            {
                wt = &m_macro_block_weights[wgt_idx];
                xb_incr = blocks_per_mb_row;
            }
            else if (split_mode == 1) //Block part of a SubBlock
            {
                wt = &m_sub_block_weights[wgt_idx];
                xb_incr = blocks_per_sb_row;
            }
            else
            {
                wt = &m_block_weights[wgt_idx];
                xb_incr = 1;
            }
            xincr = m_bparams.Xbsep() * xb_incr;

            mv1 = (*mv_array1)[yblock][xblock];
            mv1.x >>= xscale_shift;
            mv1.y >>= yscale_shift;

            mv2 = (*mv_array2)[yblock][xblock];
            mv2.x >>= xscale_shift;
            mv2.y >>= yscale_shift;

            CompensateBlock(pic_data, pos, pic_size, block_mode, dcarray[yblock][xblock], ref1up, mv1, ref2up, mv2, *wt);

            //Increment the block horizontal position
            pos.x += xincr;

        }//xblock

        // Update the pic data
        // Use only the first Ybsep rows since the remaining rows are
        // needed for the next row of blocks since we are using overlapped
        // blocks motion compensation
        if (m_add_or_sub == SUBTRACT)
        {
            int start_y = std::max(pic_data_out.FirstY() , pos.y) ;
            int end_y = std::min (pic_data_out.FirstY() + pos.y + m_bparams.Ybsep() , y_end_data);

            if (yblock == y_num_blocks - 1)
            {
                end_y = pic_data_out.LengthY();
                if (end_y > y_end_data)
                    end_y = y_end_data;

            }

            for ( int i = start_y, pos_y = 0; i < end_y; i++, pos_y++)
            {
                ValueType *pic_row = pic_data[pos_y];
                ValueType *out_row = pic_data_out[i];

                for ( int j =pic_data_out.FirstX(); j < x_end_data; ++j)
                {
                    out_row[j] -= static_cast<ValueType>( (pic_row[j] + 32) >> 6 );
                }

                // Okay, we've done all the actual blocks. Now if the picture is further padded
                // we need to set the padded values to zero beyond the last block in the row,
                // for all the picture lines in the block row. Need only do this when we're
                // subtracting.

                for (int j=pic_size.x; j<pic_data_out.LengthX() ; ++j )
                {
                    out_row[pic_data_out.FirstX()+j] = 0;
                }
            }
        }
        else // (m_add_or_sub == ADD)
        {
Exemplo n.º 8
0
void MvDataCodec::DecodeDC( MvData& out_data )
{
    //begin with Y DC value    
    ValueType val = 0; 
    int bin = 1; 
    bool bit; 
    
    do
    {
        DecodeSymbol( bit , ChooseYDCContext( out_data , bin ) ); 
        
        if ( !bit )
            val++; 
        
        bin++; 
    }
    while ( !bit ); 
    
    if (val != 0)
    {
        DecodeSymbol( bit , ChooseYDCSignContext( out_data ) ); 
        
        if (!bit)
            val = -val; 
    }
    
    out_data.DC( Y_COMP )[b_yp][b_xp] = val + DCPrediction( out_data.DC( Y_COMP ) , out_data.Mode()); 

    if (m_cformat != Yonly)
    {
        //move onto U and V DC values
        val = 0; 
        bin = 1; 
        
        do
        {
            DecodeSymbol( bit , ChooseUDCContext( out_data , bin ) ); 
            
            if (!bit)
                val++; 
            
            bin++; 
        }
        while (!bit); 
        
        if (val != 0)
        {
            DecodeSymbol( bit , ChooseUDCSignContext ( out_data ) ); 
            
            if (!bit)
                val = -val; 
        }
        
        out_data.DC( U_COMP )[b_yp][b_xp] = val + DCPrediction( out_data.DC( U_COMP ) , out_data.Mode()); 

        val = 0; 
        bin = 1; 
        
        do
        {
            DecodeSymbol( bit , ChooseVDCContext( out_data , bin ) ); 
            
            if ( !bit )
                val++; 
            
            bin++; 
        }
        while ( !bit ); 
        
        if (val != 0)
        {
            DecodeSymbol( bit , ChooseVDCSignContext( out_data ) ); 
            
            if ( !bit )
                val = -val; 
        }
        
        out_data.DC( V_COMP )[b_yp][b_xp] = val + DCPrediction( out_data.DC( V_COMP ) , out_data.Mode() ); 
    }
}
Exemplo n.º 9
0
void MvDataCodec::DoWorkDecode( MvData& out_data, int num_bits)
{
    int step,max; 
    int pstep,pmax;     
    int split_depth; 
    bool common_ref; 
    int xstart,ystart;     

    for (mb_yp = 0,mb_tlb_y = 0; mb_yp < out_data.MBSplit().LengthY(); ++mb_yp,mb_tlb_y += 4)
    {
        for (mb_xp = 0,mb_tlb_x = 0; mb_xp < out_data.MBSplit().LengthX(); ++mb_xp,mb_tlb_x += 4)
        {
             //start with split mode
            DecodeMBSplit( out_data ); 
            split_depth = out_data.MBSplit()[mb_yp][mb_xp]; 
            step =  4  >>  (split_depth); 
            max  = (1 << split_depth); 

            //next do common_ref
            if(split_depth  !=  0)
            {
                DecodeMBCom( out_data ); 
                pstep = step; 
                pmax = max; 
            }
            else
            {
                out_data.MBCommonMode()[mb_yp][mb_xp] = true; 
                pstep = 4; 
                pmax = 1; 
            }
            
            common_ref = out_data.MBCommonMode()[mb_yp][mb_xp]; 

            // do prediction modes
            for (b_yp = mb_tlb_y;  b_yp < mb_tlb_y + 4;  b_yp += pstep)
            {                
                for (b_xp = mb_tlb_x; b_xp < mb_tlb_x + 4;  b_xp += pstep)
                {
                    DecodePredmode(out_data); 
                    
                    // propagate throughout MB                
                    for (int y = b_yp;  y < b_yp + pstep;  y++)
                        for (int x = b_xp;  x < b_xp + pstep;  x++)
                            out_data.Mode()[y][x] = out_data.Mode()[b_yp][b_xp];                                                         
                }
            }

               //now do all the block mvs in the mb
            for (int j = 0; j < max; ++j)
            {                
                for (int i = 0; i < max; ++i)
                {
                    xstart = b_xp = mb_tlb_x + i * step; 
                    ystart = b_yp = mb_tlb_y + j * step;                                             
                    
                    if (out_data.Mode()[b_yp][b_xp] == REF1_ONLY || out_data.Mode()[b_yp][b_xp] == REF1AND2 )
                        DecodeMv1( out_data ); 
                    
                    if (out_data.Mode()[b_yp][b_xp] == REF2_ONLY || out_data.Mode()[b_yp][b_xp] == REF1AND2 )
                        DecodeMv2( out_data ); 
                    
                    if(out_data.Mode()[b_yp][b_xp] == INTRA)
                        DecodeDC( out_data ); 
                    
                      //propagate throughout MB    
                    for (b_yp = ystart; b_yp < ystart+step; b_yp++)
                    {
                        for (b_xp = xstart; b_xp < xstart+step; b_xp++)
                        {                    
                            out_data.Vectors(1)[b_yp][b_xp].x = out_data.Vectors(1)[ystart][xstart].x; 
                            out_data.Vectors(1)[b_yp][b_xp].y = out_data.Vectors(1)[ystart][xstart].y; 
                            out_data.Vectors(2)[b_yp][b_xp].x = out_data.Vectors(2)[ystart][xstart].x; 
                            out_data.Vectors(2)[b_yp][b_xp].y = out_data.Vectors(2)[ystart][xstart].y; 
                            out_data.DC( Y_COMP )[b_yp][b_xp] = out_data.DC( Y_COMP )[ystart][xstart]; 
                            out_data.DC( U_COMP )[b_yp][b_xp] = out_data.DC( U_COMP )[ystart][xstart]; 
                            out_data.DC( V_COMP )[b_yp][b_xp] = out_data.DC( V_COMP )[ystart][xstart]; 
                        }//b_xp
                    }//b_yp
                }//i                    
            }//j

        }//mb_xp
    }//mb_yp

}
Exemplo n.º 10
0
void MvDataCodec::DoWorkCode( MvData& in_data )
{
    int step,max; 
    int pstep,pmax; 
    int split_depth; 
    bool common_ref; 

    MB_count = 0; 
    
    for (mb_yp = 0, mb_tlb_y = 0;  mb_yp < in_data.MBSplit().LengthY();  ++mb_yp, mb_tlb_y += 4)
    {
        for (mb_xp = 0,mb_tlb_x = 0; mb_xp < in_data.MBSplit().LengthX(); ++mb_xp,mb_tlb_x += 4)
        {
             //start with split mode
            CodeMBSplit(in_data); 
            split_depth = in_data.MBSplit()[mb_yp][mb_xp]; 

            step = 4  >>  (split_depth); 
            max = (1 << split_depth); 

            //next do common_ref
            if(split_depth != 0)
            {
                CodeMBCom(in_data); 
                pstep = step; 
                pmax = max; 
            }
            else
            {
                pstep = 4; 
                pmax = 1; 
            }
            common_ref = in_data.MBCommonMode()[mb_yp][mb_xp]; 


            //do prediction modes            
            for (b_yp = mb_tlb_y; b_yp < mb_tlb_y+4; b_yp += pstep)
                for (b_xp = mb_tlb_x; b_xp < mb_tlb_x+4; b_xp += pstep)
                    CodePredmode(in_data); 
            
            step = 4 >> (split_depth);             
            
               //now do all the block mvs in the mb            
            for (b_yp = mb_tlb_y; b_yp < mb_tlb_y+4; b_yp += step)
            {
                for (b_xp = mb_tlb_x; b_xp < mb_tlb_x+4; b_xp += step)
                {
                    if (in_data.Mode()[b_yp][b_xp] == REF1_ONLY || in_data.Mode()[b_yp][b_xp] == REF1AND2 )
                        CodeMv1(in_data); 
                    
                    if (in_data.Mode()[b_yp][b_xp] == REF2_ONLY || in_data.Mode()[b_yp][b_xp] == REF1AND2 )
                        CodeMv2(in_data); 
                    
                    if(in_data.Mode()[b_yp][b_xp] == INTRA)
                        CodeDC(in_data);                     
                }//b_xp
            }//b_yp    
            
            //TODO: Update all contexts here?
            
        }//mb_xp
    }//mb_yp

}
Exemplo n.º 11
0
void MotionCompensator::CompensateComponent(Frame& picframe, const Frame &ref1frame, const Frame& ref2frame,
    const MvData& mv_data,const CompSort cs)
{
    // Set up references to pictures and references
    PicArray& pic_data_out = picframe.Data( cs );

    const PicArray& ref1up = ref1frame.UpData( cs );
    const PicArray& ref2up = ref2frame.UpData( cs );

    // Set up another picture which will contain the MC data, which
    // we'll add or subtract to pic_data_out
    TwoDArray<CalcValueType> pic_data(pic_data_out.LengthY(), pic_data_out.LengthX() , 0);

    // Factors to compensate for subsampling of chroma
    int xscale_factor = 1;
    int yscale_factor = 1;

    if ( cs != Y_COMP )
    {
        if (m_cformat == format420)
        {
            xscale_factor = 2;
            yscale_factor = 2;
        }
        else if (m_cformat == format422)
        {
            xscale_factor = 2;
            yscale_factor = 1;
        }
        else if (m_cformat == format411)
        {
            xscale_factor = 4;
            yscale_factor = 1;
        }

    } 

    // Reference to the relevant DC array
    const TwoDArray<ValueType>& dcarray = mv_data.DC( cs );

    // Set up references to the vectors
    const int num_refs = picframe.GetFparams().Refs().size();
    const MvArray* mv_array1; 
    const MvArray* mv_array2;
    mv_array1 = &mv_data.Vectors(1);
    if (num_refs ==2 )
        mv_array2 = &mv_data.Vectors(2);
    else
        mv_array2 = &mv_data.Vectors(1);

    ReConfig();//set all the weighting blocks up    

    //Blocks are listed left to right, line by line.
    MVector mv1,mv2;
    PredMode block_mode;
    ValueType dc;

    //Coords of the top-left corner of a block
    ImageCoords pos;

    //Loop for each block in the output image.
    //The CompensateBlock function will use the image pointed to by ref1up
    //and add the compensated pixels to the image pointed to by pic_data.
    size_t wgt_idx;

    //Loop over all the block rows

    pos.y = -m_bparams.Yoffset();
    for(int yblock = 0; yblock < m_cparams.YNumBlocks(); ++yblock)
    {
        pos.x = -m_bparams.Xoffset();
        //loop over all the blocks in a row
        for(int xblock = 0 ; xblock < m_cparams.XNumBlocks(); ++xblock)
        {

            //Decide which weights to use.
            if((xblock != 0)&&(xblock < m_cparams.XNumBlocks() - 1))
            {
                if((yblock != 0)&&(yblock < m_cparams.YNumBlocks() - 1))    
                    wgt_idx = 4;
                else if(yblock == 0) 
                    wgt_idx = 1;
                else 
                    wgt_idx= 7;
            }
            else if(xblock == 0)
            {
                if((yblock != 0)&&(yblock < m_cparams.YNumBlocks() - 1))    
                    wgt_idx = 3;
                else if(yblock == 0) 
                    wgt_idx = 0;
                else 
                    wgt_idx = 6;
            }
            else
            {
                if((yblock != 0)&&(yblock < m_cparams.YNumBlocks() - 1))    
                    wgt_idx = 5;
                else if(yblock == 0) 
                    wgt_idx = 2;
                else 
                    wgt_idx = 8;
            }

            block_mode = mv_data.Mode()[yblock][xblock];
            mv1 = (*mv_array1)[yblock][xblock];
            mv1.x /= xscale_factor;
            mv1.y /= yscale_factor;

            mv2 = (*mv_array2)[yblock][xblock];
            mv2.x /= xscale_factor;
            mv2.y /= yscale_factor;


            dc = dcarray[yblock][xblock]<<2;// DC is only given 8 bits, 
                                            // so need to shift to get 10-bit data

            if(block_mode == REF1_ONLY)
            {
                CompensateBlock(pic_data, ref1up, mv1, pos, m_block_weights[wgt_idx]);
            }
            else if (block_mode == REF2_ONLY)
            {                
                CompensateBlock(pic_data, ref2up, mv2, pos, m_block_weights[wgt_idx]);
            }
            else if(block_mode == REF1AND2)
            {
                CompensateBlock(pic_data, ref1up, mv1, pos, m_half_block_weights[wgt_idx]);
                CompensateBlock(pic_data, ref2up, mv2, pos, m_half_block_weights[wgt_idx]);                    
            }
            else
            {//we have a DC block.
                DCBlock(pic_data, dc,pos, m_block_weights[wgt_idx]);
            }

            //Increment the block horizontal position
            pos.x += m_bparams.Xbsep();

        }//xblock

        //Increment the block vertical position
        pos.y += m_bparams.Ybsep();

    }//yblock

    if ( m_add_or_sub == SUBTRACT)
    {
        int x_end_data = std::min(pic_data.LastX(), m_cparams.XNumBlocks()*m_bparams.Xbsep() );
        int y_end_data = std::min(pic_data.LastY(), m_cparams.YNumBlocks()*m_bparams.Ybsep() );

        for ( int i =pic_data.FirstY(); i <= y_end_data; i++)
        {
            for ( int j =pic_data.FirstX(); j <= x_end_data; ++j)
            {
                pic_data_out[i][j] -= static_cast<ValueType>( (pic_data[i][j] + 1024) >> 11 );
            }
 
            // Okay, we've done all the actual blocks. Now if the picture is further padded
            // we need to set the padded values to zero beyond the last block in the row,
            // for all the picture lines in the block row. Need only do this when we're
            // subtracting.

            for (int j=( m_cparams.XNumBlocks()*m_bparams.Xbsep() ); j<pic_data.LengthX() ; ++j )
            {
                pic_data_out[i][j] = 0;
            }
        }
        // Finally, now we've done all the blocks, we must set all padded lines below 
        // the last row equal to 0, if we're subtracting
        for ( int y=m_cparams.YNumBlocks()*m_bparams.Ybsep() ; y<pic_data.LengthY() ; ++y )
        {
            for ( int x=0 ; x<pic_data.LengthX() ; ++x )
            {
                pic_data_out[y][x] = 0;
            }

        }
    }