mmxstate.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /********************************************************************
  2. * *
  3. * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
  4. * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
  5. * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  6. * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
  7. * *
  8. * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
  9. * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
  10. * *
  11. ********************************************************************
  12. function:
  13. last mod: $Id: mmxstate.c 16584 2009-09-26 19:35:55Z tterribe $
  14. ********************************************************************/
  15. /*MMX acceleration of complete fragment reconstruction algorithm.
  16. Originally written by Rudolf Marek.*/
  17. #include <string.h>
  18. #include "x86int.h"
  19. #include "mmxfrag.h"
  20. #include "mmxloop.h"
  21. #if defined(OC_X86_ASM)
  22. void oc_state_frag_recon_mmx(const oc_theora_state *_state,ptrdiff_t _fragi,
  23. int _pli,ogg_int16_t _dct_coeffs[64],int _last_zzi,ogg_uint16_t _dc_quant){
  24. unsigned char *dst;
  25. ptrdiff_t frag_buf_off;
  26. int ystride;
  27. int mb_mode;
  28. /*Apply the inverse transform.*/
  29. /*Special case only having a DC component.*/
  30. if(_last_zzi<2){
  31. /*Note that this value must be unsigned, to keep the __asm__ block from
  32. sign-extending it when it puts it in a register.*/
  33. ogg_uint16_t p;
  34. /*We round this dequant product (and not any of the others) because there's
  35. no iDCT rounding.*/
  36. p=(ogg_int16_t)(_dct_coeffs[0]*(ogg_int32_t)_dc_quant+15>>5);
  37. /*Fill _dct_coeffs with p.*/
  38. __asm{
  39. #define Y eax
  40. #define P ecx
  41. mov Y,_dct_coeffs
  42. movzx P,p
  43. /*mm0=0000 0000 0000 AAAA*/
  44. movd mm0,P
  45. /*mm0=0000 0000 AAAA AAAA*/
  46. punpcklwd mm0,mm0
  47. /*mm0=AAAA AAAA AAAA AAAA*/
  48. punpckldq mm0,mm0
  49. movq [Y],mm0
  50. movq [8+Y],mm0
  51. movq [16+Y],mm0
  52. movq [24+Y],mm0
  53. movq [32+Y],mm0
  54. movq [40+Y],mm0
  55. movq [48+Y],mm0
  56. movq [56+Y],mm0
  57. movq [64+Y],mm0
  58. movq [72+Y],mm0
  59. movq [80+Y],mm0
  60. movq [88+Y],mm0
  61. movq [96+Y],mm0
  62. movq [104+Y],mm0
  63. movq [112+Y],mm0
  64. movq [120+Y],mm0
  65. #undef Y
  66. #undef P
  67. }
  68. }
  69. else{
  70. /*Dequantize the DC coefficient.*/
  71. _dct_coeffs[0]=(ogg_int16_t)(_dct_coeffs[0]*(int)_dc_quant);
  72. oc_idct8x8_mmx(_dct_coeffs,_last_zzi);
  73. }
  74. /*Fill in the target buffer.*/
  75. frag_buf_off=_state->frag_buf_offs[_fragi];
  76. mb_mode=_state->frags[_fragi].mb_mode;
  77. ystride=_state->ref_ystride[_pli];
  78. dst=_state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_SELF]]+frag_buf_off;
  79. if(mb_mode==OC_MODE_INTRA)oc_frag_recon_intra_mmx(dst,ystride,_dct_coeffs);
  80. else{
  81. const unsigned char *ref;
  82. int mvoffsets[2];
  83. ref=
  84. _state->ref_frame_data[_state->ref_frame_idx[OC_FRAME_FOR_MODE(mb_mode)]]
  85. +frag_buf_off;
  86. if(oc_state_get_mv_offsets(_state,mvoffsets,_pli,
  87. _state->frag_mvs[_fragi][0],_state->frag_mvs[_fragi][1])>1){
  88. oc_frag_recon_inter2_mmx(dst,ref+mvoffsets[0],ref+mvoffsets[1],ystride,
  89. _dct_coeffs);
  90. }
  91. else oc_frag_recon_inter_mmx(dst,ref+mvoffsets[0],ystride,_dct_coeffs);
  92. }
  93. }
  94. /*We copy these entire function to inline the actual MMX routines so that we
  95. use only a single indirect call.*/
  96. /*Copies the fragments specified by the lists of fragment indices from one
  97. frame to another.
  98. _fragis: A pointer to a list of fragment indices.
  99. _nfragis: The number of fragment indices to copy.
  100. _dst_frame: The reference frame to copy to.
  101. _src_frame: The reference frame to copy from.
  102. _pli: The color plane the fragments lie in.*/
  103. void oc_state_frag_copy_list_mmx(const oc_theora_state *_state,
  104. const ptrdiff_t *_fragis,ptrdiff_t _nfragis,
  105. int _dst_frame,int _src_frame,int _pli){
  106. const ptrdiff_t *frag_buf_offs;
  107. const unsigned char *src_frame_data;
  108. unsigned char *dst_frame_data;
  109. ptrdiff_t fragii;
  110. int ystride;
  111. dst_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_dst_frame]];
  112. src_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_src_frame]];
  113. ystride=_state->ref_ystride[_pli];
  114. frag_buf_offs=_state->frag_buf_offs;
  115. for(fragii=0;fragii<_nfragis;fragii++){
  116. ptrdiff_t frag_buf_off;
  117. frag_buf_off=frag_buf_offs[_fragis[fragii]];
  118. #define SRC edx
  119. #define DST eax
  120. #define YSTRIDE ecx
  121. #define YSTRIDE3 edi
  122. OC_FRAG_COPY_MMX(dst_frame_data+frag_buf_off,
  123. src_frame_data+frag_buf_off,ystride);
  124. #undef SRC
  125. #undef DST
  126. #undef YSTRIDE
  127. #undef YSTRIDE3
  128. }
  129. }
  130. /*Apply the loop filter to a given set of fragment rows in the given plane.
  131. The filter may be run on the bottom edge, affecting pixels in the next row of
  132. fragments, so this row also needs to be available.
  133. _bv: The bounding values array.
  134. _refi: The index of the frame buffer to filter.
  135. _pli: The color plane to filter.
  136. _fragy0: The Y coordinate of the first fragment row to filter.
  137. _fragy_end: The Y coordinate of the fragment row to stop filtering at.*/
  138. void oc_state_loop_filter_frag_rows_mmx(const oc_theora_state *_state,
  139. int _bv[256],int _refi,int _pli,int _fragy0,int _fragy_end){
  140. OC_ALIGN8(unsigned char ll[8]);
  141. const oc_fragment_plane *fplane;
  142. const oc_fragment *frags;
  143. const ptrdiff_t *frag_buf_offs;
  144. unsigned char *ref_frame_data;
  145. ptrdiff_t fragi_top;
  146. ptrdiff_t fragi_bot;
  147. ptrdiff_t fragi0;
  148. ptrdiff_t fragi0_end;
  149. int ystride;
  150. int nhfrags;
  151. memset(ll,_state->loop_filter_limits[_state->qis[0]],sizeof(ll));
  152. fplane=_state->fplanes+_pli;
  153. nhfrags=fplane->nhfrags;
  154. fragi_top=fplane->froffset;
  155. fragi_bot=fragi_top+fplane->nfrags;
  156. fragi0=fragi_top+_fragy0*(ptrdiff_t)nhfrags;
  157. fragi0_end=fragi0+(_fragy_end-_fragy0)*(ptrdiff_t)nhfrags;
  158. ystride=_state->ref_ystride[_pli];
  159. frags=_state->frags;
  160. frag_buf_offs=_state->frag_buf_offs;
  161. ref_frame_data=_state->ref_frame_data[_refi];
  162. /*The following loops are constructed somewhat non-intuitively on purpose.
  163. The main idea is: if a block boundary has at least one coded fragment on
  164. it, the filter is applied to it.
  165. However, the order that the filters are applied in matters, and VP3 chose
  166. the somewhat strange ordering used below.*/
  167. while(fragi0<fragi0_end){
  168. ptrdiff_t fragi;
  169. ptrdiff_t fragi_end;
  170. fragi=fragi0;
  171. fragi_end=fragi+nhfrags;
  172. while(fragi<fragi_end){
  173. if(frags[fragi].coded){
  174. unsigned char *ref;
  175. ref=ref_frame_data+frag_buf_offs[fragi];
  176. #define PIX eax
  177. #define YSTRIDE3 edi
  178. #define YSTRIDE ecx
  179. #define LL edx
  180. #define D esi
  181. #define D_WORD si
  182. if(fragi>fragi0)OC_LOOP_FILTER_H_MMX(ref,ystride,ll);
  183. if(fragi0>fragi_top)OC_LOOP_FILTER_V_MMX(ref,ystride,ll);
  184. if(fragi+1<fragi_end&&!frags[fragi+1].coded){
  185. OC_LOOP_FILTER_H_MMX(ref+8,ystride,ll);
  186. }
  187. if(fragi+nhfrags<fragi_bot&&!frags[fragi+nhfrags].coded){
  188. OC_LOOP_FILTER_V_MMX(ref+(ystride<<3),ystride,ll);
  189. }
  190. #undef PIX
  191. #undef YSTRIDE3
  192. #undef YSTRIDE
  193. #undef LL
  194. #undef D
  195. #undef D_WORD
  196. }
  197. fragi++;
  198. }
  199. fragi0+=nhfrags;
  200. }
  201. }
  202. #endif