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

Audio

开发平台:

Visual C++

  1. /*****************************************************************************
  2.  * mc-c.c: h264 encoder library (Motion Compensation)
  3.  *****************************************************************************
  4.  * Copyright (C) 2003-2008 x264 project
  5.  *
  6.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  7.  *          Loren Merritt <lorenm@u.washington.edu>
  8.  *          Jason Garrett-Glaser <darkshikari@gmail.com>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include "common/common.h"
  28. #include "mc.h"
  29. /* NASM functions */
  30. extern void x264_pixel_avg_16x16_sse2( uint8_t *, int, uint8_t *, int );
  31. extern void x264_pixel_avg_16x8_sse2( uint8_t *, int, uint8_t *, int );
  32. extern void x264_pixel_avg_16x16_mmxext( uint8_t *, int, uint8_t *, int );
  33. extern void x264_pixel_avg_16x8_mmxext( uint8_t *, int, uint8_t *, int );
  34. extern void x264_pixel_avg_8x16_mmxext( uint8_t *, int, uint8_t *, int );
  35. extern void x264_pixel_avg_8x8_mmxext( uint8_t *, int, uint8_t *, int );
  36. extern void x264_pixel_avg_8x4_mmxext( uint8_t *, int, uint8_t *, int );
  37. extern void x264_pixel_avg_4x8_mmxext( uint8_t *, int, uint8_t *, int );
  38. extern void x264_pixel_avg_4x4_mmxext( uint8_t *, int, uint8_t *, int );
  39. extern void x264_pixel_avg_4x2_mmxext( uint8_t *, int, uint8_t *, int );
  40. extern void x264_mc_copy_w4_mmx( uint8_t *, int, uint8_t *, int, int );
  41. extern void x264_mc_copy_w8_mmx( uint8_t *, int, uint8_t *, int, int );
  42. extern void x264_mc_copy_w16_mmx( uint8_t *, int, uint8_t *, int, int );
  43. extern void x264_mc_copy_w16_sse2( uint8_t *, int, uint8_t *, int, int );
  44. extern void x264_mc_copy_w16_sse3( uint8_t *, int, uint8_t *, int, int );
  45. extern void x264_mc_copy_w16_aligned_sse2( uint8_t *, int, uint8_t *, int, int );
  46. extern void x264_pixel_avg_weight_4x4_mmxext( uint8_t *, int, uint8_t *, int, int );
  47. extern void x264_pixel_avg_weight_w8_mmxext( uint8_t *, int, uint8_t *, int, int, int );
  48. extern void x264_pixel_avg_weight_w8_sse2( uint8_t *, int, uint8_t *, int, int, int );
  49. extern void x264_pixel_avg_weight_w16_sse2( uint8_t *, int, uint8_t *, int, int, int );
  50. extern void x264_pixel_avg_weight_w16_mmxext( uint8_t *, int, uint8_t *, int, int, int );
  51. extern void x264_prefetch_fenc_mmxext( uint8_t *, int, uint8_t *, int, int );
  52. extern void x264_prefetch_ref_mmxext( uint8_t *, int, int );
  53. extern void x264_mc_chroma_mmxext( uint8_t *src, int i_src_stride,
  54.                                    uint8_t *dst, int i_dst_stride,
  55.                                    int dx, int dy, int i_width, int i_height );
  56. extern void x264_mc_chroma_sse2( uint8_t *src, int i_src_stride,
  57.                                  uint8_t *dst, int i_dst_stride,
  58.                                  int dx, int dy, int i_width, int i_height );
  59. extern void x264_mc_chroma_ssse3( uint8_t *src, int i_src_stride,
  60.                                   uint8_t *dst, int i_dst_stride,
  61.                                   int dx, int dy, int i_width, int i_height );
  62. extern void x264_plane_copy_mmxext( uint8_t *, int, uint8_t *, int, int w, int h);
  63. extern void *x264_memcpy_aligned_mmx( void * dst, const void * src, size_t n );
  64. extern void *x264_memcpy_aligned_sse2( void * dst, const void * src, size_t n );
  65. extern void x264_memzero_aligned_mmx( void * dst, int n );
  66. extern void x264_memzero_aligned_sse2( void * dst, int n );
  67. #define LOWRES(cpu) 
  68. extern void x264_frame_init_lowres_core_##cpu( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
  69.                                                int src_stride, int dst_stride, int width, int height );
  70. LOWRES(mmxext)
  71. LOWRES(cache32_mmxext)
  72. LOWRES(sse2)
  73. LOWRES(ssse3)
  74. #define PIXEL_AVG_W(width,cpu)
  75. extern void x264_pixel_avg2_w##width##_##cpu( uint8_t *, int, uint8_t *, int, uint8_t *, int );
  76. /* This declares some functions that don't exist, but that isn't a problem. */
  77. #define PIXEL_AVG_WALL(cpu)
  78. PIXEL_AVG_W(4,cpu); PIXEL_AVG_W(8,cpu); PIXEL_AVG_W(12,cpu); PIXEL_AVG_W(16,cpu); PIXEL_AVG_W(20,cpu);
  79. PIXEL_AVG_WALL(mmxext)
  80. PIXEL_AVG_WALL(cache32_mmxext)
  81. PIXEL_AVG_WALL(cache64_mmxext)
  82. PIXEL_AVG_WALL(cache64_sse2)
  83. PIXEL_AVG_WALL(sse2)
  84. #define AVG_WEIGHT(W,H,name) 
  85. static void x264_pixel_avg_weight_ ## W ## x ## H ## _##name( uint8_t *dst, int i_dst, uint8_t *src, int i_src, int i_weight_dst ) 
  86.     x264_pixel_avg_weight_w ## W ## _##name( dst, i_dst, src, i_src, i_weight_dst, H ); 
  87. }
  88. AVG_WEIGHT(16,16,mmxext)
  89. AVG_WEIGHT(16,8,mmxext)
  90. AVG_WEIGHT(8,16,mmxext)
  91. AVG_WEIGHT(8,8,mmxext)
  92. AVG_WEIGHT(8,4,mmxext)
  93. AVG_WEIGHT(16,16,sse2)
  94. AVG_WEIGHT(16,8,sse2)
  95. AVG_WEIGHT(8,16,sse2)
  96. AVG_WEIGHT(8,8,sse2)
  97. AVG_WEIGHT(8,4,sse2)
  98. #define PIXEL_AVG_WTAB(instr, name1, name2, name3, name4, name5)
  99. static void (* const x264_pixel_avg_wtab_##instr[6])( uint8_t *, int, uint8_t *, int, uint8_t *, int ) =
  100. {
  101.     NULL,
  102.     x264_pixel_avg2_w4_##name1,
  103.     x264_pixel_avg2_w8_##name2,
  104.     x264_pixel_avg2_w12_##name3,
  105.     x264_pixel_avg2_w16_##name4,
  106.     x264_pixel_avg2_w20_##name5,
  107. };
  108. /* w16 sse2 is faster than w12 mmx as long as the cacheline issue is resolved */
  109. #define x264_pixel_avg2_w12_cache64_sse2 x264_pixel_avg2_w16_cache64_sse2
  110. #define x264_pixel_avg2_w12_sse3         x264_pixel_avg2_w16_sse3
  111. PIXEL_AVG_WTAB(mmxext, mmxext, mmxext, mmxext, mmxext, mmxext)
  112. #ifdef ARCH_X86
  113. PIXEL_AVG_WTAB(cache32_mmxext, mmxext, cache32_mmxext, cache32_mmxext, cache32_mmxext, cache32_mmxext)
  114. #endif
  115. PIXEL_AVG_WTAB(cache64_mmxext, mmxext, cache64_mmxext, cache64_mmxext, cache64_mmxext, cache64_mmxext)
  116. PIXEL_AVG_WTAB(sse2, mmxext, mmxext, mmxext, sse2, sse2)
  117. PIXEL_AVG_WTAB(cache64_sse2, mmxext, cache64_mmxext, cache64_sse2, cache64_sse2, cache64_sse2)
  118. #define MC_COPY_WTAB(instr, name1, name2, name3)
  119. static void (* const x264_mc_copy_wtab_##instr[5])( uint8_t *, int, uint8_t *, int, int ) =
  120. {
  121.     NULL,
  122.     x264_mc_copy_w4_##name1,
  123.     x264_mc_copy_w8_##name2,
  124.     NULL,
  125.     x264_mc_copy_w16_##name3,
  126. };
  127. MC_COPY_WTAB(mmx,mmx,mmx,mmx)
  128. MC_COPY_WTAB(sse2,mmx,mmx,sse2)
  129. static const int hpel_ref0[16] = {0,1,1,1,0,1,1,1,2,3,3,3,0,1,1,1};
  130. static const int hpel_ref1[16] = {0,0,0,0,2,2,3,2,2,2,3,2,2,2,3,2};
  131. #define MC_LUMA(name,instr1,instr2)
  132. static void mc_luma_##name( uint8_t *dst,    int i_dst_stride,
  133.                   uint8_t *src[4], int i_src_stride,
  134.                   int mvx, int mvy,
  135.                   int i_width, int i_height )
  136. {
  137.     int qpel_idx = ((mvy&3)<<2) + (mvx&3);
  138.     int offset = (mvy>>2)*i_src_stride + (mvx>>2);
  139.     uint8_t *src1 = src[hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) * i_src_stride;
  140.     if( qpel_idx & 5 ) /* qpel interpolation needed */
  141.     {
  142.         uint8_t *src2 = src[hpel_ref1[qpel_idx]] + offset + ((mvx&3) == 3);
  143.         x264_pixel_avg_wtab_##instr1[i_width>>2](
  144.                 dst, i_dst_stride, src1, i_src_stride,
  145.                 src2, i_height );
  146.     }
  147.     else
  148.     {
  149.         x264_mc_copy_wtab_##instr2[i_width>>2](
  150.                 dst, i_dst_stride, src1, i_src_stride, i_height );
  151.     }
  152. }
  153. MC_LUMA(mmxext,mmxext,mmx)
  154. #ifdef ARCH_X86
  155. MC_LUMA(cache32_mmxext,cache32_mmxext,mmx)
  156. MC_LUMA(cache64_mmxext,cache64_mmxext,mmx)
  157. #endif
  158. MC_LUMA(sse2,sse2,sse2)
  159. MC_LUMA(cache64_sse2,cache64_sse2,sse2)
  160. #define GET_REF(name)
  161. static uint8_t *get_ref_##name( uint8_t *dst,   int *i_dst_stride,
  162.                          uint8_t *src[4], int i_src_stride,
  163.                          int mvx, int mvy,
  164.                          int i_width, int i_height )
  165. {
  166.     int qpel_idx = ((mvy&3)<<2) + (mvx&3);
  167.     int offset = (mvy>>2)*i_src_stride + (mvx>>2);
  168.     uint8_t *src1 = src[hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) * i_src_stride;
  169.     if( qpel_idx & 5 ) /* qpel interpolation needed */
  170.     {
  171.         uint8_t *src2 = src[hpel_ref1[qpel_idx]] + offset + ((mvx&3) == 3);
  172.         x264_pixel_avg_wtab_##name[i_width>>2](
  173.                 dst, *i_dst_stride, src1, i_src_stride,
  174.                 src2, i_height );
  175.         return dst;
  176.     }
  177.     else
  178.     {
  179.         *i_dst_stride = i_src_stride;
  180.         return src1;
  181.     }
  182. }
  183. GET_REF(mmxext)
  184. #ifdef ARCH_X86
  185. GET_REF(cache32_mmxext)
  186. GET_REF(cache64_mmxext)
  187. #endif
  188. GET_REF(sse2)
  189. GET_REF(cache64_sse2)
  190. #define HPEL(align, cpu, cpuv, cpuc, cpuh)
  191. void x264_hpel_filter_v_##cpuv( uint8_t *dst, uint8_t *src, int16_t *buf, int stride, int width);
  192. void x264_hpel_filter_c_##cpuc( uint8_t *dst, int16_t *buf, int width );
  193. void x264_hpel_filter_h_##cpuh( uint8_t *dst, uint8_t *src, int width );
  194. void x264_sfence( void );
  195. static void x264_hpel_filter_##cpu( uint8_t *dsth, uint8_t *dstv, uint8_t *dstc, uint8_t *src,
  196.                              int stride, int width, int height )
  197. {
  198.     int16_t *buf;
  199.     int realign = (long)src & (align-1);
  200.     src -= realign;
  201.     dstv -= realign;
  202.     dstc -= realign;
  203.     dsth -= realign;
  204.     width += realign;
  205.     buf = x264_malloc((width+16)*sizeof(int16_t));
  206.     while( height-- )
  207.     {
  208.         x264_hpel_filter_v_##cpuv( dstv, src, buf+8, stride, width );
  209.         x264_hpel_filter_c_##cpuc( dstc, buf+8, width );
  210.         x264_hpel_filter_h_##cpuh( dsth, src, width );
  211.         dsth += stride;
  212.         dstv += stride;
  213.         dstc += stride;
  214.         src  += stride;
  215.     }
  216.     x264_sfence();
  217.     x264_free(buf);
  218. }
  219. HPEL(8, mmxext, mmxext, mmxext, mmxext)
  220. HPEL(16, sse2_amd, mmxext, mmxext, sse2)
  221. HPEL(16, sse2, sse2, sse2, sse2)
  222. HPEL(16, ssse3, sse2, ssse3, sse2)
  223. void x264_mc_init_mmx( int cpu, x264_mc_functions_t *pf )
  224. {
  225.     if( !(cpu&X264_CPU_MMX) )
  226.         return;
  227.     pf->copy[PIXEL_16x16] = x264_mc_copy_w16_mmx;
  228.     pf->copy[PIXEL_8x8]   = x264_mc_copy_w8_mmx;
  229.     pf->copy[PIXEL_4x4]   = x264_mc_copy_w4_mmx;
  230.     pf->memcpy_aligned = x264_memcpy_aligned_mmx;
  231.     pf->memzero_aligned = x264_memzero_aligned_mmx;
  232.     if( !(cpu&X264_CPU_MMXEXT) )
  233.         return;
  234.     pf->mc_luma = mc_luma_mmxext;
  235.     pf->get_ref = get_ref_mmxext;
  236.     pf->mc_chroma = x264_mc_chroma_mmxext;
  237.     pf->avg[PIXEL_16x16] = x264_pixel_avg_16x16_mmxext;
  238.     pf->avg[PIXEL_16x8]  = x264_pixel_avg_16x8_mmxext;
  239.     pf->avg[PIXEL_8x16]  = x264_pixel_avg_8x16_mmxext;
  240.     pf->avg[PIXEL_8x8]   = x264_pixel_avg_8x8_mmxext;
  241.     pf->avg[PIXEL_8x4]   = x264_pixel_avg_8x4_mmxext;
  242.     pf->avg[PIXEL_4x8]   = x264_pixel_avg_4x8_mmxext;
  243.     pf->avg[PIXEL_4x4]   = x264_pixel_avg_4x4_mmxext;
  244.     pf->avg[PIXEL_4x2]   = x264_pixel_avg_4x2_mmxext;
  245.     pf->avg_weight[PIXEL_16x16] = x264_pixel_avg_weight_16x16_mmxext;
  246.     pf->avg_weight[PIXEL_16x8]  = x264_pixel_avg_weight_16x8_mmxext;
  247.     pf->avg_weight[PIXEL_8x16]  = x264_pixel_avg_weight_8x16_mmxext;
  248.     pf->avg_weight[PIXEL_8x8]   = x264_pixel_avg_weight_8x8_mmxext;
  249.     pf->avg_weight[PIXEL_8x4]   = x264_pixel_avg_weight_8x4_mmxext;
  250.     pf->avg_weight[PIXEL_4x4]   = x264_pixel_avg_weight_4x4_mmxext;
  251.     // avg_weight_4x8 is rare and 4x2 is not used
  252.     pf->plane_copy = x264_plane_copy_mmxext;
  253.     pf->hpel_filter = x264_hpel_filter_mmxext;
  254.     pf->frame_init_lowres_core = x264_frame_init_lowres_core_mmxext;
  255.     pf->prefetch_fenc = x264_prefetch_fenc_mmxext;
  256.     pf->prefetch_ref  = x264_prefetch_ref_mmxext;
  257. #ifdef ARCH_X86 // all x86_64 cpus with cacheline split issues use sse2 instead
  258.     if( cpu&X264_CPU_CACHELINE_32 )
  259.     {
  260.         pf->mc_luma = mc_luma_cache32_mmxext;
  261.         pf->get_ref = get_ref_cache32_mmxext;
  262.         pf->frame_init_lowres_core = x264_frame_init_lowres_core_cache32_mmxext;
  263.     }
  264.     else if( cpu&X264_CPU_CACHELINE_64 )
  265.     {
  266.         pf->mc_luma = mc_luma_cache64_mmxext;
  267.         pf->get_ref = get_ref_cache64_mmxext;
  268.         pf->frame_init_lowres_core = x264_frame_init_lowres_core_cache32_mmxext;
  269.     }
  270. #endif
  271.     if( !(cpu&X264_CPU_SSE2) )
  272.         return;
  273.     pf->memcpy_aligned = x264_memcpy_aligned_sse2;
  274.     pf->memzero_aligned = x264_memzero_aligned_sse2;
  275.     pf->hpel_filter = x264_hpel_filter_sse2_amd;
  276.     if( cpu&X264_CPU_SSE2_IS_SLOW )
  277.         return;
  278.     pf->copy[PIXEL_16x16] = x264_mc_copy_w16_aligned_sse2;
  279.     pf->avg[PIXEL_16x16] = x264_pixel_avg_16x16_sse2;
  280.     pf->avg[PIXEL_16x8]  = x264_pixel_avg_16x8_sse2;
  281.     if( !(cpu&X264_CPU_STACK_MOD4) )
  282.     {
  283.         pf->avg_weight[PIXEL_16x16] = x264_pixel_avg_weight_16x16_sse2;
  284.         pf->avg_weight[PIXEL_16x8]  = x264_pixel_avg_weight_16x8_sse2;
  285.         pf->avg_weight[PIXEL_8x16]  = x264_pixel_avg_weight_8x16_sse2;
  286.         pf->avg_weight[PIXEL_8x8]   = x264_pixel_avg_weight_8x8_sse2;
  287.         pf->avg_weight[PIXEL_8x4]   = x264_pixel_avg_weight_8x4_sse2;
  288.     }
  289.     pf->hpel_filter = x264_hpel_filter_sse2;
  290.     pf->frame_init_lowres_core = x264_frame_init_lowres_core_sse2;
  291.     pf->mc_chroma = x264_mc_chroma_sse2;
  292.     if( cpu&X264_CPU_SSE2_IS_FAST )
  293.     {
  294.         pf->mc_luma = mc_luma_sse2;
  295.         pf->get_ref = get_ref_sse2;
  296.         if( cpu&X264_CPU_CACHELINE_64 )
  297.         {
  298.             pf->mc_luma = mc_luma_cache64_sse2;
  299.             pf->get_ref = get_ref_cache64_sse2;
  300.         }
  301.     }
  302.     if( !(cpu&X264_CPU_SSSE3) )
  303.         return;
  304.     pf->hpel_filter = x264_hpel_filter_ssse3;
  305.     pf->frame_init_lowres_core = x264_frame_init_lowres_core_ssse3;
  306.     pf->mc_chroma = x264_mc_chroma_ssse3;
  307. }