如何在JM8.6代码的编码端提取残差(为简便起见,仅以I4x4宏块为例)

原文转自:http://blog.csdn.net/stpeace/article/details/8205759

要在JM8.6代码中找出某一数据,不能瞎撞,不能用蛮力,而是要根据H.264的流程来找.比如,要在编码端找到像素残差,就可以按照下面的思路来找. (为简便起见,仅以I4x4宏块为例)

       提前说一句:有时候对于同一个量,有好几个地方多可以提取,所以思路不要太局限,重要的是知道该量过去从何而来,将来又何去何从. 下面的思路是提取I4x4宏块中残差的思路.(啰嗦一句:如何要提取所有类型宏块的残差,那么仅在下面这个地方提取则是不够的)

       前面说过,原始的YUV像素存储在imgY_org中,而编码端要对残差进行变换编码,而encode_one_macroblock就是编码一个宏块的关键函数,所以,如果要在编码端提取残差,就可以尝试在encode_one_macroblock所在的文件搜索imgY_org, 一搜索,还真有,但很多,回想一下,残差是怎么形成的?很显然残差的形成必然涉及到相减,也就是要在代码中找“imgY_org[][] - ...”这样形式的代码. 找找,还真有,但是我们需要的“imgY_org[][] - ...”形式的代码却在Mode_Decision_for_4x4IntraBlocks函数中,没关系的,因为encode_one_macroblock调用了Mode_Decision_for_4x4IntraBlocks函数.

      提取残差的代码如下:(其中只有部分代码用于提取残差,以I4x4宏块为例))

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int Mode_Decision_for_4x4IntraBlocks (int  b8,  int  b4,  double  lambda,  int*  min_cost)  
  2. {  
  3.   int     ipmode, best_ipmode = 0, i, j, k, x, y, cost, dummy;  
  4.   int     c_nz, nonzero = 0, rec4x4[4][4], diff[16];  
  5.   double  rdcost;  
  6.   int     block_x     = 8*(b8%2)+4*(b4%2);  
  7.   int     block_y     = 8*(b8/2)+4*(b4/2);  
  8.   int     pic_pix_x   = img->pix_x+block_x;  
  9.   int     pic_pix_y   = img->pix_y+block_y;  
  10.   int     pic_opix_x   = img->opix_x+block_x;  
  11.   int     pic_opix_y   = img->opix_y+block_y;  
  12.   int     pic_block_x = pic_pix_x/4;  
  13.   int     pic_block_y = pic_pix_y/4;  
  14.   double  min_rdcost  = 1e30;  
  15.   
  16.   int left_available, up_available, all_available;  
  17.   
  18.   int     upMode;  
  19.   int     leftMode;  
  20.   int     mostProbableMode;  
  21.   
  22.   static int controlFlag = 0;  
  23.   
  24.   PixelPos left_block;  
  25.   PixelPos top_block;  
  26.   
  27.   getLuma4x4Neighbour(img->current_mb_nr, block_x/4, block_y/4, -1,  0, &left_block);  
  28.   getLuma4x4Neighbour(img->current_mb_nr, block_x/4, block_y/4,  0, -1, &top_block);  
  29.   
  30.   
  31.   // constrained intra pred  
  32.   if (input->UseConstrainedIntraPred)  
  33.   {  
  34.     left_block.available = left_block.available ? img->intra_block[left_block.mb_addr] : 0;  
  35.     top_block.available  = top_block.available  ? img->intra_block[top_block.mb_addr]  : 0;  
  36.   }  
  37.     
  38.   upMode            = top_block.available ? img->ipredmode[top_block.pos_x ][top_block.pos_y ] : -1;  
  39.   leftMode          = left_block.available ? img->ipredmode[left_block.pos_x][left_block.pos_y] : -1;  
  40.     
  41.   mostProbableMode  = (upMode < 0 || leftMode < 0) ? DC_PRED : upMode < leftMode ? upMode : leftMode;  
  42.   
  43.   *min_cost = (1<<20);  
  44.   
  45.   //===== INTRA PREDICTION FOR 4x4 BLOCK =====  
  46.   intrapred_luma (pic_pix_x, pic_pix_y, &left_available, &up_available, &all_available);  
  47.   
  48.   //===== LOOP OVER ALL 4x4 INTRA PREDICTION MODES =====  
  49.   for (ipmode=0; ipmode<NO_INTRA_PMODE; ipmode++)  
  50.   {  
  51.     int available_mode =  (ipmode==DC_PRED) ||  
  52.         ((ipmode==VERT_PRED||ipmode==VERT_LEFT_PRED||ipmode==DIAG_DOWN_LEFT_PRED) && up_available ) ||  
  53.         ((ipmode==HOR_PRED||ipmode==HOR_UP_PRED) && left_available ) ||(all_available);  
  54.     if( available_mode)  
  55.     {  
  56.       if (!input->rdopt)  
  57.       {  
  58.         for (k=j=0; j<4; j++)  
  59.           for (i=0; i<4; i++, k++)  
  60.           {  
  61.             diff[k] = imgY_org[pic_opix_y+j][pic_opix_x+i] - img->mprr[ipmode][j][i];  
  62.           }  
  63.         cost  = (ipmode == mostProbableMode) ? 0 : (int)floor(4 * lambda );  
  64.         cost += SATD (diff, input->hadamard);  
  65.         if (cost < *min_cost)  
  66.         {  
  67.           best_ipmode = ipmode;  
  68.           *min_cost   = cost;  
  69.         }  
  70.       }  
  71.       else  
  72.       {  
  73.         // get prediction and prediction error  
  74.         for (j=0; j<4; j++)  
  75.         for (i=0; i<4; i++)  
  76.         {  
  77.           img->mpr[block_x+i][block_y+j]  = img->mprr[ipmode][j][i];  
  78.           img->m7[i][j]                   = imgY_org[pic_opix_y+j][pic_opix_x+i] - img->mprr[ipmode][j][i];  
  79.         }  
  80.   
  81.   
  82. //**************************************************************  
  83.   
  84.         // 下面是提取残差的代码(原始值,预测值和残差都打印出来)  
  85.   
  86.         // controlFlag是static int 类型的变量,用于表示宏块中的小块  
  87.         // 比如controlFlag为2,则表示第一宏块的第二个4*4小块  
  88.         controlFlag++;  
  89.         if(2 == controlFlag)  
  90.         {  
  91.             printf("****************************\n");  
  92.             for (j = 0; j < 4; j++)  
  93.             {  
  94.                 for (i = 0; i < 4; i++)  
  95.                 {  
  96.                     printf("%d\t",imgY_org[pic_opix_y+j][pic_opix_x+i]);  
  97.                 }  
  98.                 printf("\n");  
  99.             }  
  100.   
  101.               
  102.             printf("****************************\n");  
  103.             for (j = 0; j < 4; j++)  
  104.             {  
  105.                 for (i = 0; i < 4; i++)  
  106.                 {  
  107.                     printf("%d\t",img->mprr[ipmode][j][i]);  
  108.                 }  
  109.                 printf("\n");  
  110.             }  
  111.   
  112.             printf("****************************\n");  
  113.             for (j=0; j<4; j++)  
  114.             {  
  115.                 for (i=0; i<4; i++)  
  116.                 {  
  117.                     printf("%d\t",img->m7[i][j]);  
  118.                 }  
  119.                 printf("\n");  
  120.             }  
  121.         }  
  122.           
  123. //**************************************************************  
  124.   
  125.   
  126.         //===== store the coding state =====  
  127.         store_coding_state (cs_cm);  
  128.         // get and check rate-distortion cost  
  129.         if ((rdcost = RDCost_for_4x4IntraBlocks (&c_nz, b8, b4, ipmode, lambda, min_rdcost, mostProbableMode)) < min_rdcost)  
  130.         {  
  131.           //--- set coefficients ---  
  132.           for (j=0; j<2; j++)  
  133.           for (i=0; i<18;i++)  cofAC4x4[j][i]=img->cofAC[b8][b4][j][i];  
  134.   
  135.           //--- set reconstruction ---  
  136.           for (y=0; y<4; y++)  
  137.           for (x=0; x<4; x++)  rec4x4[y][x] = enc_picture->imgY[pic_pix_y+y][pic_pix_x+x];  
  138.   
  139.           //--- flag if dct-coefficients must be coded ---  
  140.           nonzero = c_nz;  
  141.   
  142.           //--- set best mode update minimum cost ---  
  143.           min_rdcost  = rdcost;  
  144.           best_ipmode = ipmode;  
  145.         }  
  146.         reset_coding_state (cs_cm);  
  147.       }  
  148.     }  
  149.   }  
  150.   
  151.   //===== set intra mode prediction =====  
  152.   img->ipredmode[pic_block_x][pic_block_y] = best_ipmode;  
  153.   img->mb_data[img->current_mb_nr].intra_pred_modes[4*b8+b4] = mostProbableMode == best_ipmode ? -1 : best_ipmode < mostProbableMode ? best_ipmode : best_ipmode-1;  
  154.   
  155.   if (!input->rdopt)  
  156.   {  
  157.     // get prediction and prediction error  
  158.     for (j=0; j<4; j++)  
  159.       for (i=0; i<4; i++)  
  160.       {  
  161.         img->mpr[block_x+i][block_y+j]  = img->mprr[best_ipmode][j][i];  
  162.         img->m7[i][j]                   = imgY_org[pic_opix_y+j][pic_opix_x+i] - img->mprr[best_ipmode][j][i];  
  163.       }  
  164.     nonzero = dct_luma (block_x, block_y, &dummy, 1);  
  165.   }  
  166.   else  
  167.   {  
  168.     //===== restore coefficients =====  
  169.     for (j=0; j<2; j++)  
  170.     for (i=0; i<18;i++)  img->cofAC[b8][b4][j][i]=cofAC4x4[j][i];  
  171.     
  172.     //===== restore reconstruction and prediction (needed if single coeffs are removed) =====  
  173.     for (y=0; y<4; y++)  
  174.     for (x=0; x<4; x++)  
  175.     {  
  176.       enc_picture->imgY[pic_pix_y+y][pic_pix_x+x] = rec4x4[y][x];  
  177.       img->mpr[block_x+x][block_y+y] = img->mprr[best_ipmode][y][x];  
  178.     }  
  179.   }  
  180.   
  181.   return nonzero;  
  182. }  

      结果为:

****************************
251     254     254     253
228     205     213     185
197     173     185     136
177     189     198     160
****************************
238     238     238     238
205     205     205     205
167     167     167     167
160     160     160     160
****************************
13      16      16      15
23      0       8       -20
30      6       18      -31
17      29      38      0

 

      三个矩阵分别对应第一帧第一宏块的第二个4*4块的原始值、预测值和残差,为了验证上述结果的正确性,可以用H.264visa分析一下,结果如下:

 

      原始值为:(注意: H.264visa也可以读取原始的YUV数据)
====================== Y Data ======================
+----------------+----------------+----------------+----------------+
| 43,216,254,249,|251,254,254,253,|251,252,254,254,|254,254,254,253,|
| 49,198,193,211,|228,205,213,185,|211,207,186,248,|198,203,208,183,|
| 48,194,177,171,|197,173,185,136,|191,195,138,179,|142,176,177,135,|
| 46,214,225,169,|177,189,198,160,|203,208,177,165,|173,196,191,156,|
+----------------+----------------+----------------+----------------+
| 41,185,208,180,|203,228,226,200,|214,226,225,227,|228,225,224,210,|
| 31,130,173,178,|215,230,221,212,|220,229,227,228,|229,227,226,226,|
| 29,119,194,216,|211,213,219,222,|225,223,220,219,|218,218,218,218,|
| 25,126,219,224,|217,224,227,227,|227,226,225,224,|220,220,221,222,|
+----------------+----------------+----------------+----------------+
| 26,131,215,223,|226,225,225,225,|225,226,223,219,|221,221,219,220,|
| 30,136,216,226,|223,224,225,225,|224,221,217,221,|222,219,220,226,|
| 30,136,216,227,|224,224,225,223,|221,218,221,216,|211,224,224,211,|
| 29,135,217,225,|222,221,222,222,|221,209,181,155,|186,210,186,164,|
+----------------+----------------+----------------+----------------+
| 29,134,216,224,|226,230,230,227,|206,177,146,113,|149,162,147,150,|
| 29,135,219,231,|225,201,190,185,|163,144,153,140,|127,143,165,184,|
| 30,139,210,192,|165,142,134,133,|143,141,129,138,|150,178,201,207,|
| 30,125,166,145,|144,154,132,111,|118,161,175,180,|204,214,213,209,|
+----------------+----------------+----------------+----------------+

 

       预测值为:(注意:H.264visa相当于一个解码器,解码端的残差和编码端的残差必定相等)

====================== Y Data ======================
+----------------+----------------+----------------+----------------+
|128,128,128,128,|238,238,238,238,|255,255,255,255,|245,228,210,192,|
|128,128,128,128,|205,205,205,205,|180,180,180,180,|210,192,174,170,|
|128,128,128,128,|167,167,167,167,|137,137,137,137,|174,170,166,166,|
|128,128,128,128,|160,160,160,160,|169,169,169,169,|166,166,166,166,|
+----------------+----------------+----------------+----------------+
|161,161,161,161,|179,189,182,169,|201,201,201,201,|219,219,219,219,|
|161,161,161,161,|184,185,175,169,|214,214,214,214,|227,227,227,227,|
|161,161,161,161,|189,182,169,169,|216,216,216,216,|219,219,219,219,|
|161,161,161,161,|185,175,169,169,|229,229,229,229,|227,227,227,227,|
+----------------+----------------+----------------+----------------+
| 28,127,218,229,|224,224,224,224,|227,227,228,227,|224,224,224,224,|
| 28,127,218,229,|224,224,224,224,|224,225,227,227,|214,214,214,214,|
| 28,127,218,229,|224,224,224,224,|224,224,224,225,|212,212,212,212,|
| 28,127,218,229,|224,224,224,224,|224,224,224,224,|165,165,165,165,|
+----------------+----------------+----------------+----------------+
| 33,130,216,224,|231,223,215,194,|204,182,160,142,|127,133,139,147,|
| 33,130,216,224,|215,194,173,162,|160,142,125,120,|139,147,154,165,|
| 33,130,216,224,|173,162,150,150,|125,120,116,116,|154,165,176,176,|
| 33,130,216,224,|150,150,150,150,|116,116,116,116,|176,176,176,176,|
+----------------+----------------+----------------+----------------+

 

      残差为:(注意:H.264visa相当于一个解码器,而解码端的残差与编码端的残差只是近似,并不相等)

====================== Y Data ======================
+------------------------+------------------------+------------------------+------------------------+
|  -78,   88,  132,  110,|   24,   14,   24,   19,|   -8,    7,   -3,   -4,|   16,   31,   48,   51,|
|  -81,   63,   67,   77,|   30,    1,   11,  -25,|   19,   24,    6,   59,|  -12,   20,   32,   10,|
|  -83,   62,   48,   39,|   25,    6,   16,  -30,|   54,   46,    4,   44,|  -30,    7,    5,  -32,|
|  -80,   87,   93,   32,|   14,   24,   34,    9,|   31,   37,    7,   -3,|    6,   28,   21,   -9,|
+------------------------+------------------------+------------------------+------------------------+
| -117,   22,   51,   22,|   25,   35,   38,   32,|   18,   18,   18,   18,|    5,    5,    5,    5,|
| -135,  -22,   22,   19,|   32,   43,   50,   45,|   13,   13,   13,   13,|    3,    3,    3,    3,|
| -131,  -38,   38,   55,|   20,   35,   48,   47,|    3,    3,    3,    3,|   -2,   -2,   -2,   -2,|
| -133,  -34,   57,   68,|   27,   43,   60,   60,|   -2,   -2,   -2,   -2,|   -5,   -5,   -5,   -5,|
+------------------------+------------------------+------------------------+------------------------+
|    5,    3,   -2,   -5,|    0,    0,    0,    0,|   -4,   -4,   -3,   -3,|   -5,   -6,   -5,   -2,|
|    5,    3,   -2,   -5,|    0,    0,    0,    0,|   -3,   -5,  -10,  -13,|   -2,    5,   14,   15,|
|    5,    3,   -2,   -5,|    0,    0,    0,    0,|   -3,   -5,  -10,  -13,|    0,   14,   15,    3,|
|    5,    3,   -2,   -5,|    0,    0,    0,    0,|    2,  -13,  -44,  -59,|   23,   35,   24,    0,|
+------------------------+------------------------+------------------------+------------------------+
|   -4,   -4,    0,    4,|    1,    5,   18,   26,|    0,    0,   -2,  -34,|   25,   20,    8,    3,|
|    2,    7,   11,   10,|   13,    3,    9,   25,|    6,    7,   25,   26,|   -9,   -3,    9,   15,|
|    0,    6,   -8,  -28,|   -5,  -11,  -17,  -17,|   16,   20,   12,   16,|   -5,    4,   22,   31,|
|   -6,   -5,  -39,  -74,|   -9,    3,  -10,  -34,|    6,   43,   55,   60,|   33,   33,   35,   35,|
+------------------------+------------------------+------------------------+------------------------+

 

       最后,如果上面代码中的if(2 == controlFlag)改为if(1 == controlFlag),那么结果为:

****************************
43      216     254     249
49      198     193     211
48      194     177     171
46      214     225     169
****************************
128     128     128     128
128     128     128     128
128     128     128     128
128     128     128     128
****************************
-85     88      126     121
-79     70      65      83
-80     66      49      43
-82     86      97      41

 

       与上面的H.264visa的结果进行对比,一切都一目了然,便不再赘述了.

 

       P.S. 后来,我发现,上面的过程是有瑕疵的,因为对于一个宏块来说,Mode_Decision_for_4x4IntraBlocks函数不止被调用16次,所以并不对应16个4*4块,为什么会有这种情况呢?跟踪代码后发现,原来对于一个4*4块而言,要选出最终最合理的帧内预测模式,所要进行的DCT变换次数远不止16次. 所以如果要真正在编码端提取像素残差,就应该对这么多次有所选择, 而JM8.6代码必然要作出了这样的选择,找找就可以了.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值