1. /*
  2.     Project  : H.264 encoder test    
  3.     Module   : Intra coding related functions
  4.  
  5.     Author   : Marko 'Fador' Viitanen
  6.  
  7.     Date     : 30/06/2009
  8.     Modified : 01/07/2009
  9.  
  10. */
  11.  
  12. #include <stdio.h>
  13. #include "common.h"
  14. #include "psnr.h"
  15. #include "intra.h"
  16.  
  17.  
  18. //Macro for result comparing
  19. #define COMPARE(MODE) \
  20.     tempsad=SAD(cur4x4L, pred4x4L,(uint32)4,(uint32)4); \
  21.     if(tempsad<bestcost) \
  22.     {\
  23.         bestcost=tempsad;\
  24.         bestIntra4x4PredMode=MODE;\
  25.         for(temp_x=0;temp_x<4;temp_x++) \
  26.         {\
  27.             for(temp_y=0;temp_y<4;temp_y++)\
  28.             {\
  29.                 residual[temp_x+temp_y*4]=(cur4x4L[temp_x+temp_y*4]);\
  30.                 residual[temp_x+temp_y*4]-=(pred4x4L[temp_x+temp_y*4]);\
  31.             }\
  32.         }\
  33.     }
  34.  
  35.  
  36. #define RETURNPRED() \
  37.         for(temp_x=0;temp_x<4;temp_x++) \
  38.         {\
  39.             for(temp_y=0;temp_y<4;temp_y++)\
  40.             {\
  41.                 residual[temp_x+temp_y*4]=pred4x4L[temp_x+temp_y*4];\
  42.             }\
  43.         }\
  44.         return 1;
  45.  
  46.  
  47.  
  48. #define P(X,Y) p[(X)+1+((Y)+1)*9]
  49.  
  50.  
  51. typedef uint8 (modefunc)(uint8 *pred4x4L, uint8 *p, uint8 *pred4x4L_avail);
  52.  
  53. //Recommendation page 126
  54. //Mode -1 = encode all and select best
  55. sint8 intrapred_4x4(uint8 *frame, sint32 *residual, uint32 x, uint32 y, uint32 xoff, uint32 yoff, uint32 *cost, sint8 mode)
  56. {
  57.    
  58.     uint32 temp_x,temp_y,tempsad;
  59.     uint32 bestcost=0xffffffff;
  60.     sint8 bestIntra4x4PredMode=-1;
  61.     uint8 Intra4x4PredMode;    
  62.  
  63.     //Extended sub-macroblock
  64.     uint8 p[9*5];
  65.  
  66.     uint8 pred4x4L[4*4];
  67.     uint8 cur4x4L[4*4];    
  68.  
  69.     //Different prediction mode functions here
  70.     modefunc *funcs[9]={&intraPred4x4Mode0,&intraPred4x4Mode1,&intraPred4x4Mode2,
  71.                         &intraPred4x4Mode3,&intraPred4x4Mode4,&intraPred4x4Mode5,
  72.                         &intraPred4x4Mode6,&intraPred4x4Mode7,&intraPred4x4Mode8};
  73.  
  74.     //Fill the availability array
  75.     uint8 pred4x4L_avail[9*5];
  76.     //Fill with ones
  77.     memset(pred4x4L_avail,1,9*5);
  78.  
  79.     //First column not available at xoff==0
  80.     if(xoff==0)
  81.     {
  82.         pred4x4L_avail[0]=pred4x4L_avail[9]=pred4x4L_avail[18]=pred4x4L_avail[28]=pred4x4L_avail[36]=0;
  83.     }
  84.     else
  85.     {
  86.         temp_x=0;
  87.         //Fill I,J,K,L
  88.         for(temp_y=1;temp_y<5;temp_y++)
  89.             p[temp_y*9+temp_x]=frame[xoff+(temp_x-1)+(yoff+(temp_y-1))*x];
  90.     }
  91.  
  92.     //First row not available on yoff==0
  93.     if(yoff==0)
  94.     {
  95.          pred4x4L_avail[0]=pred4x4L_avail[1]=pred4x4L_avail[2]=pred4x4L_avail[3]=
  96.              pred4x4L_avail[4]=pred4x4L_avail[5]=pred4x4L_avail[6]=pred4x4L_avail[7]=pred4x4L_avail[8]=0;
  97.     }
  98.     else
  99.     {
  100.         temp_y=0;
  101.         //Fill (M),A,B,C & D
  102.         for(temp_x=(pred4x4L_avail[0]?0:1);temp_x<5;temp_x++)
  103.             p[temp_y*9+temp_x]=frame[xoff+(temp_x-1)+(yoff+(temp_y-1))*x];
  104.     }
  105.  
  106.  
  107.     //E-H not available at right side
  108.     if((xoff%16 == 15 && yoff%16!=0) || (x-xoff)==4)
  109.     {        
  110.         pred4x4L_avail[5]=pred4x4L_avail[6]=pred4x4L_avail[7]=pred4x4L_avail[8]=0;
  111.     }
  112.     else
  113.     {
  114.         temp_y=0;
  115.         //Fill E,F,G & H
  116.         for(temp_x=5;temp_x<9;temp_x++)
  117.             p[temp_y*9+temp_x]=frame[xoff+(temp_x-1)+(yoff+(temp_y-1))*x];
  118.     }
  119.    
  120.  
  121.  
  122.     //Current MB
  123.     for(temp_x=0;temp_x<4;temp_x++)
  124.             for(temp_y=0;temp_y<4;temp_y++)
  125.                 cur4x4L[temp_x+temp_y*4]=frame[xoff+temp_x+(yoff+temp_y)*x];
  126.  
  127.     //If we return only one prediction result
  128.     if(mode!=-1)
  129.     {
  130.         (*funcs[mode])(pred4x4L,p,pred4x4L_avail);
  131.         RETURNPRED();      
  132.     }
  133.     else
  134.     {
  135.         //Loop through all prediction modes calling the functions
  136.         //and if prediction is executed, compare the SAD of the results to
  137.         //current best cost
  138.         for(Intra4x4PredMode=0;Intra4x4PredMode<8;Intra4x4PredMode++)
  139.         {
  140.             if((*funcs[Intra4x4PredMode])(pred4x4L,p,pred4x4L_avail))
  141.             {
  142.                 COMPARE(Intra4x4PredMode);
  143.             }
  144.         }
  145.     }
  146.  
  147.     *cost=bestcost;
  148.  
  149.     return bestIntra4x4PredMode;
  150. }
  151.  
  152. //MODE0 - Intra_4x4_Vertical
  153. // This mode shall be used only when the samples p[ x, -1 ] with x = 0..3 are marked as
  154. //"available for Intra_4x4prediction".
  155. uint8 intraPred4x4Mode0(uint8 *pred4x4L, uint8 *p, uint8 *pred4x4L_avail)
  156. {
  157.     uint32 temp_x;
  158.     uint32 temp_y;
  159.  
  160.     if(pred4x4L_avail[1] //&& pred4x4L_avail[2] &&
  161.         //pred4x4L_avail[3] &&pred4x4L_avail[4]
  162.         )
  163.     {
  164.         for(temp_x=0;temp_x<4;temp_x++)
  165.         {
  166.             for(temp_y=0;temp_y<4;temp_y++)
  167.             {
  168.                 pred4x4L[ temp_x+temp_y*4 ] = P(temp_x, -1);
  169.             }
  170.         }      
  171.         return 1;
  172.     }
  173.     return 0;
  174. }
  175.  
  176. //MODE1 - Intra_4x4_Horizontal
  177. //This mode shall be used only when the samples p[ -1, y ],
  178. //with y = 0..3 are marked as "available for Intra_4x4 prediction".
  179. uint8 intraPred4x4Mode1(uint8 *pred4x4L, uint8 *p, uint8 *pred4x4L_avail)
  180. {
  181.     uint32 temp_x;
  182.     uint32 temp_y;
  183.    
  184.     if(pred4x4L_avail[9] // && pred4x4L_avail[18] &&
  185.        //pred4x4L_avail[27] && pred4x4L_avail[36]
  186.         )
  187.     {
  188.         for(temp_x=0;temp_x<4;temp_x++)
  189.             for(temp_y=0;temp_y<4;temp_y++)
  190.                 pred4x4L[ temp_x+temp_y*4 ] = P(-1,temp_y);
  191.         return 1;
  192.     }
  193.     return 0;
  194. }
  195.  
  196. //MODE2 - Intra_4x4_DC
  197. //If all samples p[ x, -1 ], with x = 0..3 and p[ -1, y ],
  198. //with y = 0..3 are marked as "available for Intra_4x4 prediction"
  199. uint8 intraPred4x4Mode2(uint8 *pred4x4L, uint8 *p, uint8 *pred4x4L_avail)
  200. {
  201.     uint32 temp_x;
  202.     uint32 temp_y;
  203.  
  204.     if(pred4x4L_avail[9] && //pred4x4L_avail[18] &&
  205.         //pred4x4L_avail[27] &&pred4x4L_avail[36] &&
  206.         pred4x4L_avail[1] //&& pred4x4L_avail[2] &&
  207.         //pred4x4L_avail[3] &&pred4x4L_avail[4]
  208.         )
  209.     {
  210.         for(temp_x=0;temp_x<4;temp_x++)
  211.             for(temp_y=0;temp_y<4;temp_y++)
  212.                 pred4x4L[ temp_x+temp_y*4 ] = (P(0,-1) + P(1,-1) + P(2,-1) +
  213.                                                P(3,-1) + P(-1,0) + P(-1,1) +
  214.                                                P(-1,2) + P(-1,3) + 4) >> 3;
  215.         return 1;
  216.     }
  217.     //- Otherwise, if any samples p[ x, -1 ], with x = 0..3 are marked as
  218.     //"not available for Intra_4x4 prediction" and all
  219.     //samples p[ -1, y ], with y = 0..3 are marked as "available for Intra_4x4 prediction"
  220.     else if(pred4x4L_avail[9]// && pred4x4L_avail[18] &&
  221.             //pred4x4L_avail[27] &&pred4x4L_avail[36]
  222.             )
  223.     {
  224.         for(temp_y=0;temp_y<4;temp_y++)
  225.             for(temp_x=0;temp_x<4;temp_x++)
  226.                 pred4x4L[ temp_x+temp_y*4 ] = (P(-1,0)+P(-1,1)+P(-1,2)+P(-1,3)+2)>>2;
  227.         return 1;
  228.     }
  229.     //- Otherwise, if any samples p[ -1, y ], with y = 0..3 are marked as
  230.     //"not available for Intra_4x4 prediction" and all
  231.     //samples p[ x, -1 ], with x = 0 .. 3 are marked as "available for Intra_4x4 prediction"
  232.     else if(pred4x4L_avail[1] //&& pred4x4L_avail[2] &&
  233.         //pred4x4L_avail[3] &&pred4x4L_avail[4]
  234.             )
  235.     {
  236.         for(temp_y=0;temp_y<4;temp_y++)
  237.             for(temp_x=0;temp_x<4;temp_x++)
  238.                 pred4x4L[ temp_x+temp_y*4 ] = (P(0,-1)+P(1,-1)+P(2,-1)+P(3,-1)+2)>>2;
  239.         return 1;
  240.     }
  241.     return 0;
  242. }
  243.  
  244. //MODE3 - Intra_4x4_Diagonal_Down_Left
  245. //This mode shall be used only when the samples p[ x, -1 ] with x = 0..7 are marked as
  246. //"available for Intra_4x4 prediction".
  247. uint8 intraPred4x4Mode3(uint8 *pred4x4L, uint8 *p, uint8 *pred4x4L_avail)
  248. {
  249.     uint32 temp_x;
  250.     uint32 temp_y;
  251.     if(pred4x4L_avail[1] && //pred4x4L_avail[2] &&
  252.        //pred4x4L_avail[3] && pred4x4L_avail[4] &&
  253.        pred4x4L_avail[5] //&& pred4x4L_avail[6] &&
  254.        //pred4x4L_avail[7] && pred4x4L_avail[8]
  255.         )
  256.     {
  257.         for(temp_y=0;temp_y<4;temp_y++)
  258.         {
  259.             for(temp_x=0;temp_x<4;temp_x++)
  260.             {
  261.                 if(temp_y==3&&temp_x==3)
  262.                 {
  263.                     pred4x4L[temp_x+ temp_y*4] = ( P(6,-1) + 3 * P(7,-1) + 2 ) >> 2;
  264.                 }
  265.                 else
  266.                 {
  267.                     pred4x4L[temp_x+ temp_y*4] = ( P((temp_x+temp_y),-1) + 2 * P(temp_x+temp_y+1,-1) + P(temp_x+temp_y+2,-1)+2) >> 2;
  268.                 }
  269.             }
  270.         }
  271.         return 1;
  272.     }
  273.     return 0;
  274. }
  275.  
  276. //MODE4 - Intra_4x4_Diagonal_Down_Right
  277. //This mode shall be used only when the samples
  278. //p[ x, -1 ] with x = 0..3 and p[ -1, y ] with y = -1..3 are marked as
  279. //"available for Intra_4x4 prediction
  280. uint8 intraPred4x4Mode4(uint8 *pred4x4L, uint8 *p, uint8 *pred4x4L_avail)
  281. {
  282.     uint32 temp_x;
  283.     uint32 temp_y;
  284.     if(pred4x4L_avail[1] &&// pred4x4L_avail[2] &&
  285.        //pred4x4L_avail[3] && pred4x4L_avail[4] &&
  286.        pred4x4L_avail[0] //&& pred4x4L_avail[9] &&
  287.        //pred4x4L_avail[18]&& pred4x4L_avail[27]&&
  288.        //pred4x4L_avail[36]
  289.        )
  290.     {
  291.  
  292.         for(temp_x=0;temp_x<4;temp_x++)
  293.         {
  294.             for(temp_y=0;temp_y<4;temp_y++)
  295.             {
  296.                 if(temp_x>temp_y)
  297.                     pred4x4L[temp_x+temp_y*4] = ( P(temp_x-temp_y-2,-1) + 2 * P(temp_x-temp_y-1,-1) + P(temp_x-temp_y,-1) + 2 ) >> 2;
  298.                 else if(temp_x<temp_y)
  299.                     pred4x4L[temp_x+temp_y*4] = ( P(-1,temp_y-temp_x-2) + 2 * P(-1,temp_y-temp_x-1) + P(-1,temp_y-temp_x) + 2 ) >> 2;
  300.                 else
  301.                     pred4x4L[temp_x+temp_y*4] =( P(0,-1) + 2 * P(-1,-1) + P(-1,0) + 2 ) >> 2;
  302.             }
  303.         }
  304.         return 1;
  305.     }
  306.     return 0;
  307. }
  308.  
  309. //MODE5 - Intra_4x4_Vertical_Right
  310. //This mode shall be used only when the samples
  311. //p[ x, -1 ] with x = 0..3 and p[ -1, y ] with y = -1..3 are marked as
  312. //"available for Intra_4x4 prediction".
  313. uint8 intraPred4x4Mode5(uint8 *pred4x4L, uint8 *p, uint8 *pred4x4L_avail)
  314. {
  315.     uint32 temp_x;
  316.     uint32 temp_y;
  317.     if(pred4x4L_avail[1] &&// pred4x4L_avail[2] &&
  318.        //pred4x4L_avail[3] && pred4x4L_avail[4] &&
  319.        pred4x4L_avail[0] //&& pred4x4L_avail[9] &&
  320.        //pred4x4L_avail[18] && pred4x4L_avail[27]&&
  321.        //pred4x4L_avail[36]
  322.        )
  323.     {
  324.  
  325.         #define zVR (sint32)(2*temp_x-temp_y)
  326.         for(temp_x=0;temp_x<4;temp_x++)
  327.         {
  328.             for(temp_y=0;temp_y<4;temp_y++)
  329.             {
  330.                 if(zVR>=0)
  331.                 {
  332.                     if(zVR%2==0) //0,2,4,6
  333.                         pred4x4L[temp_x+temp_y*4] = ( P(temp_x-( temp_y>>1)-1,-1) + P(temp_x-(temp_y>>1),-1) + 1)>> 1;
  334.                     else //if(zVR%2==1) //1,3,5
  335.                         pred4x4L[temp_x+temp_y*4] = ( P(temp_x-(temp_y>>1)-2,-1) + 2*P(temp_x-(temp_y>>1)-1,-1) + P(temp_x-(temp_y>>1),-1) + 2)>>2;
  336.                 }
  337.                 else
  338.                 {
  339.                     if(zVR==-1)
  340.                         pred4x4L[temp_x+temp_y*4] =(P(-1,0)+2*P(-1,-1)+P(0,-1)+2)>>2;
  341.                     else
  342.                         pred4x4L[temp_x+temp_y*4] = (P(-1,temp_y-1)+2*P(-1,temp_y-2)+P(-1,temp_y-3)+2)>>2;
  343.                 }
  344.             }
  345.         }
  346.         return 1;
  347.     }
  348.     return 0;
  349. }
  350.  
  351. //MODE6 - Intra_4x4_Horizontal_Down
  352. //This mode shall be used only when the samples p[ x, -1 ]
  353. //with x = 0..3 and p[ -1, y ] with y = -1..3 are marked as
  354. //"available for Intra_4x4 prediction".
  355. uint8 intraPred4x4Mode6(uint8 *pred4x4L, uint8 *p, uint8 *pred4x4L_avail)
  356. {
  357.     uint32 temp_x;
  358.     uint32 temp_y;
  359.     if(pred4x4L_avail[1] && //pred4x4L_avail[2] &&
  360.        //pred4x4L_avail[3] && pred4x4L_avail[4] &&
  361.        pred4x4L_avail[0] //&& pred4x4L_avail[9] &&
  362.        //pred4x4L_avail[18]&& pred4x4L_avail[27]&&
  363.        //pred4x4L_avail[36]
  364.         )
  365.     {
  366.  
  367.         #define zHD (sint32)(2*temp_y-temp_x)
  368.         for(temp_x=0;temp_x<4;temp_x++)
  369.         {
  370.             for(temp_y=0;temp_y<4;temp_y++)
  371.             {
  372.                 if(zHD>=0)
  373.                 {
  374.                     if(zHD%2==0) //0,2,4,6
  375.                         pred4x4L[temp_x+temp_y*4] = (P(-1,temp_y-(temp_x>>1)-1) + P(-1,temp_y-(temp_x>>1)) + 1)>>1; //(8-61)
  376.                     else //1,3,5
  377.                         pred4x4L[temp_x+temp_y*4] = (P(-1,temp_y-(temp_x>>1)-2) + 2*P(-1,temp_y-(temp_x>>1)-1) + P(-1,temp_y-(temp_x>>1)) + 2)>> 2; //(8-62)
  378.                 }
  379.                 else
  380.                 {
  381.                     if(zHD==-1)
  382.                         pred4x4L[temp_x+temp_y*4] = (P(-1,0) + 2*P(-1,-1) + P(0,-1) + 2)>>2; //(8-63)
  383.                     else
  384.                         pred4x4L[temp_x+temp_y*4] = (P(temp_x-1,-1) + 2*P(temp_x-2,-1) + P(temp_x-3,-1) + 2)>> 2; //(8-64)
  385.                 }
  386.             }
  387.         }
  388.         return 1;
  389.     }
  390.     return 0;
  391. }
  392.  
  393. //MODE7 - Intra_4x4_Vertical_Left
  394. //This mode shall be used only when the samples p[ x, -1 ]
  395. //with x = 0..7 are marked as "available for Intra_4x4 prediction".
  396. uint8 intraPred4x4Mode7(uint8 *pred4x4L, uint8 *p, uint8 *pred4x4L_avail)
  397. {
  398.     uint32 temp_x;
  399.     uint32 temp_y;
  400.  
  401.     if(pred4x4L_avail[1] &&// pred4x4L_avail[2] &&
  402.        pred4x4L_avail[3] //&& pred4x4L_avail[4] &&
  403.        //pred4x4L_avail[5] && pred4x4L_avail[6] &&
  404.        //pred4x4L_avail[7] && pred4x4L_avail[8]
  405.        )
  406.     {  
  407.         for(temp_x=0;temp_x<4;temp_x++)
  408.         {            
  409.             for(temp_y=0;temp_y<4;temp_y++)
  410.             {
  411.                 if(temp_y==0 && temp_y==2)
  412.                 {
  413.                     pred4x4L[temp_x+temp_y*4] = (P(temp_x+(temp_y>>1),-1) + P(temp_x+(temp_y>>1)+1,-1) + 1) >> 1; //(8-66)
  414.                 }
  415.                 else
  416.                 {
  417.                      pred4x4L[temp_x+temp_y*4] = (P(temp_x+(temp_y>>1),-1) + 2*P(temp_x+(temp_y>>1)+1,-1) + P(temp_x+(temp_y>>1)+2,-1) + 2 )>> 2; //(8-67)
  418.                 }
  419.  
  420.             }
  421.         }
  422.         return 1;
  423.     }
  424.     return 0;
  425. }
  426.  
  427.  
  428.     //MODE8 - Intra_4x4_Horizontal_Up
  429.     //This mode shall be used only when the samples p[ -1, y ]
  430.     //with y = 0..3 are marked as "available for Intra_4x4 prediction".
  431. uint8 intraPred4x4Mode8(uint8 *pred4x4L, uint8 *p, uint8 *pred4x4L_avail)
  432. {
  433.     uint32 temp_x;
  434.     uint32 temp_y;
  435.      if(pred4x4L_avail[1] //&& pred4x4L_avail[2] &&
  436.         //pred4x4L_avail[3] && pred4x4L_avail[4]
  437.         )
  438.     {
  439.  
  440.         #define zHU (sint32)(temp_x+2*temp_y)
  441.         for(temp_x=0;temp_x<4;temp_x++)
  442.         {            
  443.             for(temp_y=0;temp_y<4;temp_y++)
  444.             {
  445.                 if(zHU<5&&zHU%2==0)
  446.                 {
  447.                     pred4x4L[temp_x+temp_y*4] = (P(-1,temp_y+(temp_x>>1)) + P(-1,temp_y+(temp_x>>1)+1) + 1) >> 1;// (8-68)
  448.                 }
  449.                 else if(zHU<5&&zHU%2!=0)
  450.                 {
  451.                      pred4x4L[temp_x+temp_y*4] = (P(-1,temp_y+(temp_x>>1)) + 2*P(-1,temp_y+(temp_x>>1)+1) + P(-1,temp_y+(temp_x>>1)+2) +2) >> 2;//(8-69)
  452.                 }
  453.                 else if(zHU==5)
  454.                 {
  455.                     pred4x4L[temp_x+temp_y*4] = (P(-1,2) + 3*P(-1,3) + 2 ) >> 2;// (8-70)
  456.                 }
  457.                 else
  458.                 {
  459.                     pred4x4L[temp_x+temp_y*4] = P(-1,3);// (8-71)
  460.                 }
  461.             }
  462.         }
  463.         return 1;
  464.     }
  465.     return 0;
  466. }