csp.c
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:14k
源码类别:

Audio

开发平台:

Visual C++

  1. /*****************************************************************************
  2.  * csp.c: h264 encoder library
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 Laurent Aimar
  5.  * $Id: csp.c,v 1.1 2004/06/03 19:27:06 fenrir Exp $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include "common.h"
  26. static inline void plane_copy( uint8_t *dst, int i_dst,
  27.                                uint8_t *src, int i_src, int w, int h)
  28. {
  29.     for( ; h > 0; h-- )
  30.     {
  31.         memcpy( dst, src, w );
  32.         dst += i_dst;
  33.         src += i_src;
  34.     }
  35. }
  36. static inline void plane_copy_vflip( uint8_t *dst, int i_dst,
  37.                                      uint8_t *src, int i_src, int w, int h)
  38. {
  39.     plane_copy( dst, i_dst, src + (h -1)*i_src, -i_src, w, h );
  40. }
  41. static inline void plane_subsamplev2( uint8_t *dst, int i_dst,
  42.                                       uint8_t *src, int i_src, int w, int h)
  43. {
  44.     for( ; h > 0; h-- )
  45.     {
  46.         uint8_t *d = dst;
  47.         uint8_t *s = src;
  48.         int     i;
  49.         for( i = 0; i < w; i++ )
  50.         {
  51.             *d++ = ( s[0] + s[i_src] + 1 ) >> 1;
  52.             s++;
  53.         }
  54.         dst += i_dst;
  55.         src += 2 * i_src;
  56.     }
  57. }
  58. static inline void plane_subsamplev2_vlip( uint8_t *dst, int i_dst,
  59.                                            uint8_t *src, int i_src, int w, int h)
  60. {
  61.     plane_subsamplev2( dst, i_dst, src + (2*h-1)*i_src, -i_src, w, h );
  62. }
  63. static inline void plane_subsamplehv2( uint8_t *dst, int i_dst,
  64.                                        uint8_t *src, int i_src, int w, int h)
  65. {
  66.     for( ; h > 0; h-- )
  67.     {
  68.         uint8_t *d = dst;
  69.         uint8_t *s = src;
  70.         int     i;
  71.         for( i = 0; i < w; i++ )
  72.         {
  73.             *d++ = ( s[0] + s[1] + s[i_src] + s[i_src+1] + 1 ) >> 2;
  74.             s += 2;
  75.         }
  76.         dst += i_dst;
  77.         src += 2 * i_src;
  78.     }
  79. }
  80. static inline void plane_subsamplehv2_vlip( uint8_t *dst, int i_dst,
  81.                                             uint8_t *src, int i_src, int w, int h)
  82. {
  83.     plane_subsamplehv2( dst, i_dst, src + (2*h-1)*i_src, -i_src, w, h );
  84. }
  85. static void i420_to_i420( x264_frame_t *frm, x264_image_t *img,
  86.                           int i_width, int i_height )
  87. {
  88.     if( img->i_csp & X264_CSP_VFLIP )
  89.     {
  90.         plane_copy_vflip( frm->plane[0], frm->i_stride[0],
  91.                           img->plane[0], img->i_stride[0],
  92.                           i_width, i_height );
  93.         plane_copy_vflip( frm->plane[1], frm->i_stride[1],
  94.                           img->plane[1], img->i_stride[1],
  95.                           i_width / 2, i_height / 2 );
  96.         plane_copy_vflip( frm->plane[2], frm->i_stride[2],
  97.                           img->plane[2], img->i_stride[2],
  98.                           i_width / 2, i_height / 2 );
  99.     }
  100.     else
  101.     {
  102.         plane_copy( frm->plane[0], frm->i_stride[0],
  103.                     img->plane[0], img->i_stride[0],
  104.                     i_width, i_height );
  105.         plane_copy( frm->plane[1], frm->i_stride[1],
  106.                     img->plane[1], img->i_stride[1],
  107.                     i_width / 2, i_height / 2 );
  108.         plane_copy( frm->plane[2], frm->i_stride[2],
  109.                     img->plane[2], img->i_stride[2],
  110.                     i_width / 2, i_height / 2 );
  111.     }
  112. }
  113. static void yv12_to_i420( x264_frame_t *frm, x264_image_t *img,
  114.                           int i_width, int i_height )
  115. {
  116.     if( img->i_csp & X264_CSP_VFLIP )
  117.     {
  118.         plane_copy_vflip( frm->plane[0], frm->i_stride[0],
  119.                           img->plane[0], img->i_stride[0],
  120.                           i_width, i_height );
  121.         plane_copy_vflip( frm->plane[2], frm->i_stride[2],
  122.                           img->plane[1], img->i_stride[1],
  123.                           i_width / 2, i_height / 2 );
  124.         plane_copy_vflip( frm->plane[1], frm->i_stride[1],
  125.                           img->plane[2], img->i_stride[2],
  126.                           i_width / 2, i_height / 2 );
  127.     }
  128.     else
  129.     {
  130.         plane_copy( frm->plane[0], frm->i_stride[0],
  131.                     img->plane[0], img->i_stride[0],
  132.                     i_width, i_height );
  133.         plane_copy( frm->plane[2], frm->i_stride[2],
  134.                     img->plane[1], img->i_stride[1],
  135.                     i_width / 2, i_height / 2 );
  136.         plane_copy( frm->plane[1], frm->i_stride[1],
  137.                     img->plane[2], img->i_stride[2],
  138.                     i_width / 2, i_height / 2 );
  139.     }
  140. }
  141. static void i422_to_i420( x264_frame_t *frm, x264_image_t *img,
  142.                           int i_width, int i_height )
  143. {
  144.     if( img->i_csp & X264_CSP_VFLIP )
  145.     {
  146.         plane_copy_vflip( frm->plane[0], frm->i_stride[0],
  147.                           img->plane[0], img->i_stride[0],
  148.                           i_width, i_height );
  149.         plane_subsamplev2_vlip( frm->plane[1], frm->i_stride[1],
  150.                                 img->plane[1], img->i_stride[1],
  151.                                 i_width / 2, i_height / 2 );
  152.         plane_subsamplev2_vlip( frm->plane[2], frm->i_stride[2],
  153.                                 img->plane[2], img->i_stride[2],
  154.                                 i_width / 2, i_height / 2 );
  155.     }
  156.     else
  157.     {
  158.         plane_copy( frm->plane[0], frm->i_stride[0],
  159.                     img->plane[0], img->i_stride[0],
  160.                     i_width, i_height );
  161.         plane_subsamplev2( frm->plane[1], frm->i_stride[1],
  162.                            img->plane[1], img->i_stride[1],
  163.                            i_width / 2, i_height / 2 );
  164.         plane_subsamplev2( frm->plane[2], frm->i_stride[2],
  165.                            img->plane[2], img->i_stride[2],
  166.                            i_width / 2, i_height / 2 );
  167.     }
  168. }
  169. static void i444_to_i420( x264_frame_t *frm, x264_image_t *img,
  170.                           int i_width, int i_height )
  171. {
  172.     if( img->i_csp & X264_CSP_VFLIP )
  173.     {
  174.         plane_copy_vflip( frm->plane[0], frm->i_stride[0],
  175.                           img->plane[0], img->i_stride[0],
  176.                           i_width, i_height );
  177.         plane_subsamplehv2_vlip( frm->plane[1], frm->i_stride[1],
  178.                                  img->plane[1], img->i_stride[1],
  179.                                  i_width / 2, i_height / 2 );
  180.         plane_subsamplehv2_vlip( frm->plane[2], frm->i_stride[2],
  181.                                  img->plane[2], img->i_stride[2],
  182.                                  i_width / 2, i_height / 2 );
  183.     }
  184.     else
  185.     {
  186.         plane_copy( frm->plane[0], frm->i_stride[0],
  187.                     img->plane[0], img->i_stride[0],
  188.                     i_width, i_height );
  189.         plane_subsamplehv2( frm->plane[1], frm->i_stride[1],
  190.                             img->plane[1], img->i_stride[1],
  191.                             i_width / 2, i_height / 2 );
  192.         plane_subsamplehv2( frm->plane[2], frm->i_stride[2],
  193.                             img->plane[2], img->i_stride[2],
  194.                             i_width / 2, i_height / 2 );
  195.     }
  196. }
  197. static void yuyv_to_i420( x264_frame_t *frm, x264_image_t *img,
  198.                           int i_width, int i_height )
  199. {
  200.     uint8_t *src = img->plane[0];
  201.     int     i_src= img->i_stride[0];
  202.     uint8_t *y   = frm->plane[0];
  203.     uint8_t *u   = frm->plane[1];
  204.     uint8_t *v   = frm->plane[2];
  205.     if( img->i_csp & X264_CSP_VFLIP )
  206.     {
  207.         src += ( i_height - 1 ) * i_src;
  208.         i_src = -i_src;
  209.     }
  210.     for( ; i_height > 0; i_height -= 2 )
  211.     {
  212.         uint8_t *ss = src;
  213.         uint8_t *yy = y;
  214.         uint8_t *uu = u;
  215.         uint8_t *vv = v;
  216.         int w;
  217.         for( w = i_width; w > 0; w -= 2 )
  218.         {
  219.             *yy++ = ss[0];
  220.             *yy++ = ss[2];
  221.             *uu++ = ( ss[1] + ss[1+i_src] + 1 ) >> 1;
  222.             *vv++ = ( ss[3] + ss[3+i_src] + 1 ) >> 1;
  223.             ss += 4;
  224.         }
  225.         src += i_src;
  226.         y += frm->i_stride[0];
  227.         u += frm->i_stride[1];
  228.         v += frm->i_stride[2];
  229.         ss = src;
  230.         yy = y;
  231.         for( w = i_width; w > 0; w -= 2 )
  232.         {
  233.             *yy++ = ss[0];
  234.             *yy++ = ss[2];
  235.             ss += 4;
  236.         }
  237.         src += i_src;
  238.         y += frm->i_stride[0];
  239.     }
  240. }
  241. /* Same value than in XviD */
  242. #define BITS 8
  243. #define FIX(f) ((int)((f) * (1 << BITS) + 0.5))
  244. #define Y_R   FIX(0.257)
  245. #define Y_G   FIX(0.504)
  246. #define Y_B   FIX(0.098)
  247. #define Y_ADD 16
  248. #define U_R   FIX(0.148)
  249. #define U_G   FIX(0.291)
  250. #define U_B   FIX(0.439)
  251. #define U_ADD 128
  252. #define V_R   FIX(0.439)
  253. #define V_G   FIX(0.368)
  254. #define V_B   FIX(0.071)
  255. #define V_ADD 128
  256. #define RGB_TO_I420( name, POS_R, POS_G, POS_B, S_RGB ) 
  257. static void name( x264_frame_t *frm, x264_image_t *img, 
  258.                   int i_width, int i_height )           
  259. {                                                       
  260.     uint8_t *src = img->plane[0];                       
  261.     int     i_src= img->i_stride[0];                    
  262.     int     i_y  = frm->i_stride[0];                    
  263.     uint8_t *y   = frm->plane[0];                       
  264.     uint8_t *u   = frm->plane[1];                       
  265.     uint8_t *v   = frm->plane[2];                       
  266.                                                         
  267.     if( img->i_csp & X264_CSP_VFLIP )                   
  268.     {                                                   
  269.         src += ( i_height - 1 ) * i_src;                
  270.         i_src = -i_src;                                 
  271.     }                                                   
  272.                                                         
  273.     for(  ; i_height > 0; i_height -= 2 )               
  274.     {                                                   
  275.         uint8_t *ss = src;                              
  276.         uint8_t *yy = y;                                
  277.         uint8_t *uu = u;                                
  278.         uint8_t *vv = v;                                
  279.         int w;                                          
  280.                                                         
  281.         for( w = i_width; w > 0; w -= 2 )               
  282.         {                                               
  283.             int cr = 0,cg = 0,cb = 0;                   
  284.             int r, g, b;                                
  285.                                                         
  286.             /* Luma */                                  
  287.             cr = r = ss[POS_R];                         
  288.             cg = g = ss[POS_G];                         
  289.             cb = b = ss[POS_B];                         
  290.                                                         
  291.             yy[0] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS);    
  292.                                                         
  293.             cr+= r = ss[POS_R+i_src];                   
  294.             cg+= g = ss[POS_G+i_src];                   
  295.             cb+= b = ss[POS_B+i_src];                   
  296.             yy[i_y] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS);  
  297.             yy++;                                       
  298.             ss += S_RGB;                                
  299.                                                         
  300.             cr+= r = ss[POS_R];                         
  301.             cg+= g = ss[POS_G];                         
  302.             cb+= b = ss[POS_B];                         
  303.                                                         
  304.             yy[0] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS);    
  305.                                                         
  306.             cr+= r = ss[POS_R+i_src];                   
  307.             cg+= g = ss[POS_G+i_src];                   
  308.             cb+= b = ss[POS_B+i_src];                   
  309.             yy[i_y] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS);  
  310.             yy++;                                       
  311.             ss += S_RGB;                                
  312.                                                         
  313.             /* Chroma */                                
  314.             *uu++ = (uint8_t)(U_ADD + ((-U_R * cr - U_G * cg + U_B * cb) >> (BITS+2)) ); 
  315.             *vv++ = (uint8_t)(V_ADD + (( V_R * cr - V_G * cg - V_B * cb) >> (BITS+2)) ); 
  316.         }                                               
  317.                                                         
  318.         src += 2*i_src;                                   
  319.         y += 2*frm->i_stride[0];                        
  320.         u += frm->i_stride[1];                          
  321.         v += frm->i_stride[2];                          
  322.     }                                                   
  323. }
  324. RGB_TO_I420( rgb_to_i420,  0, 1, 2, 3 );
  325. RGB_TO_I420( bgr_to_i420,  2, 1, 0, 3 );
  326. RGB_TO_I420( bgra_to_i420, 2, 1, 0, 4 );
  327. void x264_csp_init( int cpu, int i_csp, x264_csp_function_t *pf )
  328. {
  329.     switch( i_csp )
  330.     {
  331.         case X264_CSP_I420:
  332.             pf->i420 = i420_to_i420;
  333.             pf->i422 = i422_to_i420;
  334.             pf->i444 = i444_to_i420;
  335.             pf->yv12 = yv12_to_i420;
  336.             pf->yuyv = yuyv_to_i420;
  337.             pf->rgb  = rgb_to_i420;
  338.             pf->bgr  = bgr_to_i420;
  339.             pf->bgra = bgra_to_i420;
  340.             break;
  341.         default:
  342.             /* For now, can't happen */
  343.             fprintf( stderr, "arg in x264_csp_initn" );
  344.             exit( -1 );
  345.             break;
  346.     }
  347. }