JM8.6 色度帧内预测函数剖析(IntraChromaPrediction8x8)

 

By jack_incredible

//位于macroblock.c

void IntraChromaPrediction8x8 (int *mb_up, int *mb_left, int*mb_up_left)

{

 

  Macroblock *currMB = &img->mb_data[img->current_mb_nr];

  int     s, s0, s1, s2, s3, i, j, k;

  pel_t** image;

  int     block_x, block_y;

  int     mb_nr             = img->current_mb_nr;

  int     mb_available_up;

  int     mb_available_left[2];

  int     mb_available_up_left;

  int     ih,iv;

  int     ib,ic,iaa;

  int     uv;

  int     hline[8], vline[9];

  int     mode;

  int     best_mode = DC_PRED_8;         //just an initilaization here, should always be overwritten

  int     cost;

  int     min_cost;

  int     diff[16];

  PixelPos up;       //!< pixel position p(0,-1)

  PixelPos left[9];  //!< pixel positions p(-1, -1..8)

 

 

  for (i=0;i<9;i++)

  {

    getNeighbour(mb_nr, -1 ,  i-1 , 0, &left[i]);  //判断左上边像素加上左边8个像素(共9个像素)的有效性,若有效取得其位置信息。

  }

  

  getNeighbour(mb_nr, 0     ,  -1 , 0, &up);  //判断上边左起第一个像素的有效性

 

  mb_available_up                             = up.available;

  mb_available_up_left                        = left[0].available;

  mb_available_left[0] = mb_available_left[1] = left[1].available;

 

  if(input->UseConstrainedIntraPred)  // input->UseConstrainedIntraPred参数来自配置文件,一般情况下为0,即不执行下面块中的程序

  {

    mb_available_up      = up.available ? img->intra_block[up.mb_addr] : 0;

    for (i=1, mb_available_left[0]=1; i<5;i++)

      mb_available_left[0]  &= left[i].available ? img->intra_block[left[i].mb_addr]: 0;

    for (i=5, mb_available_left[1]=1; i<9;i++)

      mb_available_left[1]  &= left[i].available ? img->intra_block[left[i].mb_addr]: 0;

    mb_available_up_left = left[0].available ? img->intra_block[left[0].mb_addr]: 0;

  }

 

  if (mb_up)

    *mb_up = mb_available_up;

  if (mb_left)

    *mb_left = mb_available_left[0] && mb_available_left[1];

  if( mb_up_left )

    *mb_up_left = mb_available_up_left;

 

  // compute all chroma intra prediction modes for both U and V

  for (uv=0; uv<2; uv++)

  {

 image = enc_picture->imgUV[uv];

 

 // DC prediction

 for (block_y=0; block_y<8; block_y+=4)

 for (block_x=0; block_x<8; block_x+=4)

 {

 s=128;

 s0=s1=s2=s3=0;

 //===== get prediction value =====

 switch ((block_y>>1) + (block_x>>2))

 {

 case 0:  //===== TOP LEFT =====    //8x8块的左上边4x4部分进行预测

 if      (mb_available_up)       for (i=0;i<4;i++)  s0 += image[up.pos_y][up.pos_x + i];

 if      (mb_available_left[0])  for (i=1;i<5;i++)  s2 += image[left[i].pos_y][left[i].pos_x];

 if      (mb_available_up && mb_available_left[0])  s  = (s0+s2+4) >> 3;

 else if (mb_available_up)                          s  = (s0   +2) >> 2;

 else if (mb_available_left[0])                     s  = (s2   +2) >> 2;

 break;

 case 1: //===== TOP RIGHT =====   //8x8块的右上边4x4部分进行预测

 if      (mb_available_up)       for (i=4;i<8;i++)  s1 += image[up.pos_y][up.pos_x + i];

 else if (mb_available_left[0])  for (i=1;i<5;i++)  s2 += image[left[i].pos_y][left[i].pos_x];

 if      (mb_available_up)                          s  = (s1   +2) >> 2;

 else if (mb_available_left[0])                     s  = (s2   +2) >> 2;

 break;

 case 2: //===== BOTTOM LEFT =====    //8x8块的左下边4x4部分进行预测

 if      (mb_available_left[1])  for (i=5;i<9;i++)  s3 += image[left[i].pos_y][left[i].pos_x];

 else if (mb_available_up)       for (i=0;i<4;i++)  s0 += image[up.pos_y][up.pos_x + i];

 if      (mb_available_left[1])                     s  = (s3   +2) >> 2;

 else if (mb_available_up)                          s  = (s0   +2) >> 2;

 break;

 case 3: //===== BOTTOM RIGHT =====    //8x8块的右下边4x4部分进行预测

 if      (mb_available_up)       for (i=4;i<8;i++)  s1 += image[up.pos_y][up.pos_x + i];

 if      (mb_available_left[1])  for (i=5;i<9;i++)  s3 += image[left[i].pos_y][left[i].pos_x];

 if      (mb_available_up && mb_available_left[1])  s  = (s1+s3+4) >> 3;

 else if (mb_available_up)                          s  = (s1   +2) >> 2;

 else if (mb_available_left[1])                     s  = (s3   +2) >> 2;

 break;

 }           

 

 //===== prediction =====

 for (j=block_y; j<block_y+4; j++)

 for (i=block_x; i<block_x+4; i++)

 {

 img->mprr_c[uv][DC_PRED_8][i][j] = s;

 }

 }

 

 // vertical prediction

 if (mb_available_up)

 {

 for (i=0; i<8; i++)

 hline[i] = image[up.pos_y][up.pos_x + i];

 for (i=0; i<8; i++)

 for (j=0; j<8; j++)

 img->mprr_c[uv][VERT_PRED_8][i][j] = hline[i];

 }

 

 // horizontal prediction 

 if (mb_available_left[0] && mb_available_left[1])

 {

 for (i=1; i<9; i++)

 vline[i] = image[left[i].pos_y][left[i].pos_x];

 for (i=0; i<8; i++)

 for (j=0; j<8; j++)

 img->mprr_c[uv][HOR_PRED_8][i][j] = vline[j+1]; 

 }

 

 // plane prediction 

 if (mb_available_left[0] && mb_available_left[1] && mb_available_up && mb_available_up_left)

 {

 ih = 4*(hline[7] - image[left[0].pos_y][left[0].pos_x]);

 iv = 4*(vline[7+1] - image[left[0].pos_y][left[0].pos_x]);

 for (i=1;i<4;i++)

 {

 ih += i*(hline[3+i] - hline[3-i]);

 iv += i*(vline[3+i+1] - vline[3-i+1]);

 }

 ib=(17*ih+16)>>5;

 ic=(17*iv+16)>>5;

 

 iaa=16*(hline[7]+vline[7+1]);

 for (j=0; j<8; j++)

 for (i=0; i<8; i++)

 img->mprr_c[uv][PLANE_8][i][j]=max(0,min(255,(iaa+(i-3)*ib +(j-3)*ic + 16)/32));// store plane prediction

 }

  }  //endfor (uv=0; uv<2; uv++)

 

//这个地方貌似好像有点问题,觉得input->rdopt前不应该取!

if (!input->rdopt) // the rd-opt part does not work correctly (see encode_one_macroblock)

  {                       // since ipredmodes could be overwritten => encoder-decoder-mismatches

 // pick lowest cost prediction mode

 min_cost = 1<<20;

 for (i=0;i<8;i++)

 {

 getNeighbour(mb_nr, 0 ,  i , 0, &left[i]);  //获得当前块左边第一列的坐标

 }

 for (mode=DC_PRED_8; mode<=PLANE_8; mode++)

 {

 if ((mode==VERT_PRED_8 && !mb_available_up) ||

 (mode==HOR_PRED_8 && (!mb_available_left[0] || !mb_available_left[1])) ||

 (mode==PLANE_8 && (!mb_available_left[0] || !mb_available_left[1] || !mb_available_up || !mb_available_up_left)))

 continue;

 

 cost = 0;

 for (uv=0; uv<2; uv++)

 {

 image = imgUV_org[uv];

 for (block_y=0; block_y<8; block_y+=4)

 for (block_x=0; block_x<8; block_x+=4)

 {

 for (k=0,j=block_y; j<block_y+4; j++)

 for (i=block_x; i<block_x+4; i++,k++)

 {

 diff[k] = image[left[j].pos_y][left[j].pos_x+i] - img->mprr_c[uv][mode][i][j];  //求差分值

 }

 cost += SATD(diff, input->hadamard);  //SATD变换

 }

 }

 if (cost < min_cost)

 {

 best_mode = mode;

 min_cost = cost;

 }

 }

 

 currMB->c_ipred_mode = best_mode;

  }

 

}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
H.264是一种视频编码标准,其中的帧内预测是其中一种压缩技术。在MATLAB中实现H.264编码可以使用一些开源库和工具,例如JM、x264等。以下是一个示例代码,实现了H.264帧内预测编码: ```matlab % Read input video vidObj = VideoReader('input_video.mp4'); % Create output video object outputVideo = VideoWriter('output_video.mp4','MPEG-4'); outputVideo.FrameRate = vidObj.FrameRate; open(outputVideo); % Set H.264 encoder parameters params = struct('Profile','High','Level','4.0','BitRate',5000000,'FrameRate',vidObj.FrameRate); % Loop through each video frame while hasFrame(vidObj) % Read current frame frame = readFrame(vidObj); % Convert to YCbCr color space YCbCr = rgb2ycbcr(frame); % Split YCbCr into separate components Y = YCbCr(:,:,1); Cb = YCbCr(:,:,2); Cr = YCbCr(:,:,3); % Perform frame intra prediction on Y component Y_pred = intra_prediction(Y); % Combine YCbCr components YCbCr_pred = cat(3,Y_pred,Cb,Cr); % Convert back to RGB color space frame_pred = ycbcr2rgb(YCbCr_pred); % Write encoded frame to output video writeVideo(outputVideo,frame_pred); end % Close output video object close(outputVideo); function Y_pred = intra_prediction(Y) % Block size (8x8) block_size = 8; % Pad input image [rows,cols] = size(Y); Y_pad = padarray(Y,[block_size-1 block_size-1],'replicate','post'); % Perform intra prediction on each block for r = 1:block_size:rows for c = 1:block_size:cols % Get current block block = Y_pad(r:r+block_size-1,c:c+block_size-1); % Calculate prediction mode mode = calculate_mode(block); % Perform prediction switch mode case 0 % DC mode pred = mean(block(:)); case 1 % Horizontal mode pred = repmat(block(1,:),[block_size 1]); case 2 % Vertical mode pred = repmat(block(:,1),[1 block_size]); case 3 % Diagonal mode pred = diag(block); pred = repmat(pred(:),[1 block_size]) + repmat(pred(:)',[block_size 1]); pred = pred/(block_size+1); otherwise error('Invalid prediction mode'); end % Subtract prediction from current block Y_pred(r:r+block_size-1,c:c+block_size-1) = block - pred; end end end function mode = calculate_mode(block) % Calculate sum of absolute differences (SAD) for each mode SAD = zeros(4,1); SAD(1) = sum(abs(block(:)-mean(block(:)))); SAD(2) = sum(abs(block(1,:)-mean(block(:)))); SAD(3) = sum(abs(block(:,1)-mean(block(:)))); SAD(4) = sum(abs(diag(block)-mean(block(:)))); % Find mode with minimum SAD [~,mode] = min(SAD); mode = mode-1; end ``` 这段代码实现了一个简单的帧内预测编码器,基于直接模式选择方法(mode selection),并且使用直流、水平、垂直和对角线预测模式进行预测。在实际应用中,需要使用更复杂的编码器和预测算法,以达到更好的压缩效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值