PageRenderTime 26ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/cortado-0.6.0/src/com/fluendo/jheora/Filter.java

#
Java | 396 lines | 238 code | 62 blank | 96 comment | 52 complexity | f06e4451906e47ac438c577e2fa958df MD5 | raw file
  1. /* Jheora
  2. * Copyright (C) 2004 Fluendo S.L.
  3. *
  4. * Written by: 2004 Wim Taymans <wim@fluendo.com>
  5. *
  6. * Many thanks to
  7. * The Xiph.Org Foundation http://www.xiph.org/
  8. * Jheora was based on their Theora reference decoder.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Library General Public License
  12. * as published by the Free Software Foundation; either version 2 of
  13. * the License, or (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 Library General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Library General Public
  21. * License along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23. */
  24. package com.fluendo.jheora;
  25. import com.fluendo.utils.*;
  26. public final class Filter
  27. {
  28. /* in-loop filter tables. one of these is used in dct_decode.c */
  29. private static final byte[] LoopFilterLimitValuesV1 = {
  30. 30, 25, 20, 20, 15, 15, 14, 14,
  31. 13, 13, 12, 12, 11, 11, 10, 10,
  32. 9, 9, 8, 8, 7, 7, 7, 7,
  33. 6, 6, 6, 6, 5, 5, 5, 5,
  34. 4, 4, 4, 4, 3, 3, 3, 3,
  35. 2, 2, 2, 2, 2, 2, 2, 2,
  36. 0, 0, 0, 0, 0, 0, 0, 0,
  37. 0, 0, 0, 0, 0, 0, 0, 0
  38. };
  39. /* Loop filter bounding values */
  40. private byte[] LoopFilterLimits = new byte[Constants.Q_TABLE_SIZE];
  41. private int[] FiltBoundingValue = new int[512];
  42. private void SetupBoundingValueArray_Generic(int FLimit)
  43. {
  44. /* Set up the bounding value array. */
  45. MemUtils.set (FiltBoundingValue, 0, 0, 512);
  46. for (int i = 0; i < FLimit; i++ ){
  47. FiltBoundingValue[256-i-FLimit] = (-FLimit+i);
  48. FiltBoundingValue[256-i] = -i;
  49. FiltBoundingValue[256+i] = i;
  50. FiltBoundingValue[256+i+FLimit] = FLimit-i;
  51. }
  52. }
  53. /* copy in-loop filter limits from the bitstream header into our instance */
  54. public void copyFilterTables(Info ci) {
  55. System.arraycopy(ci.LoopFilterLimitValues, 0, LoopFilterLimits, 0, Constants.Q_TABLE_SIZE);
  56. }
  57. /* initialize the filter limits from our static table */
  58. public void InitFilterTables() {
  59. System.arraycopy(LoopFilterLimitValuesV1, 0, LoopFilterLimits, 0, Constants.Q_TABLE_SIZE);
  60. }
  61. public void SetupLoopFilter(int FrameQIndex){
  62. int FLimit;
  63. /* nb: this was using the V2 values rather than V1
  64. we think is was a mistake; the results were not used */
  65. FLimit = LoopFilterLimits[FrameQIndex];
  66. SetupBoundingValueArray_Generic(FLimit);
  67. }
  68. private static final short clamp255(int val) {
  69. return (short)((~(val>>31)) & 255 & (val | ((255-val)>>31)));
  70. }
  71. private void FilterHoriz(short[] PixelPtr, int idx,
  72. int LineLength,
  73. int[] BoundingValuePtr)
  74. {
  75. int j;
  76. int FiltVal;
  77. for ( j = 0; j < 8; j++ ){
  78. FiltVal =
  79. ( PixelPtr[0 + idx] ) -
  80. ( PixelPtr[1 + idx] * 3 ) +
  81. ( PixelPtr[2 + idx] * 3 ) -
  82. ( PixelPtr[3 + idx] );
  83. FiltVal = BoundingValuePtr[256 + ((FiltVal + 4) >> 3)];
  84. PixelPtr[1 + idx] = clamp255(PixelPtr[1 + idx] + FiltVal);
  85. PixelPtr[2 + idx] = clamp255(PixelPtr[2 + idx] - FiltVal);
  86. idx += LineLength;
  87. }
  88. }
  89. private void FilterVert(short[] PixelPtr, int idx,
  90. int LineLength,
  91. int[] BoundingValuePtr){
  92. int j;
  93. int FiltVal;
  94. /* the math was correct, but negative array indicies are forbidden
  95. by ANSI/C99 and will break optimization on several modern
  96. compilers */
  97. idx -= 2*LineLength;
  98. for ( j = 0; j < 8; j++ ) {
  99. FiltVal =
  100. ( PixelPtr[idx + 0] ) -
  101. ( PixelPtr[idx + LineLength] * 3 ) +
  102. ( PixelPtr[idx + 2 * LineLength] * 3 ) -
  103. ( PixelPtr[idx + 3 * LineLength] );
  104. FiltVal = BoundingValuePtr[256 + ((FiltVal + 4) >> 3)];
  105. PixelPtr[idx + LineLength] = clamp255(PixelPtr[idx + LineLength] + FiltVal);
  106. PixelPtr[idx + 2 * LineLength] = clamp255(PixelPtr[idx + 2*LineLength] - FiltVal);
  107. idx++;
  108. }
  109. }
  110. public void LoopFilter(Playback pbi){
  111. int FragsAcross=pbi.HFragments;
  112. int FromFragment;
  113. int FragsDown = pbi.VFragments;
  114. int LineFragments;
  115. int LineLength;
  116. int FLimit;
  117. int QIndex;
  118. int i,j,m,n;
  119. int index;
  120. /* Set the limit value for the loop filter based upon the current
  121. quantizer. */
  122. QIndex = pbi.frameQIS[0];
  123. FLimit = LoopFilterLimits[QIndex];
  124. if ( FLimit == 0 ) return;
  125. SetupBoundingValueArray_Generic(FLimit);
  126. for ( j = 0; j < 3 ; j++){
  127. switch(j) {
  128. case 0: /* y */
  129. FromFragment = 0;
  130. FragsAcross = pbi.HFragments;
  131. FragsDown = pbi.VFragments;
  132. LineLength = pbi.YStride;
  133. LineFragments = pbi.HFragments;
  134. break;
  135. case 1: /* u */
  136. FromFragment = pbi.YPlaneFragments;
  137. FragsAcross = pbi.HFragments >> 1;
  138. FragsDown = pbi.VFragments >> 1;
  139. LineLength = pbi.UVStride;
  140. LineFragments = pbi.HFragments / 2;
  141. break;
  142. /*case 2: v */
  143. default:
  144. FromFragment = pbi.YPlaneFragments + pbi.UVPlaneFragments;
  145. FragsAcross = pbi.HFragments >> 1;
  146. FragsDown = pbi.VFragments >> 1;
  147. LineLength = pbi.UVStride;
  148. LineFragments = pbi.HFragments / 2;
  149. break;
  150. }
  151. i=FromFragment;
  152. /**************************************************************
  153. First Row
  154. **************************************************************/
  155. /* first column conditions */
  156. /* only do 2 prediction if fragment coded and on non intra or if
  157. all fragments are intra */
  158. if( pbi.display_fragments[i] != 0){
  159. /* Filter right hand border only if the block to the right is
  160. not coded */
  161. if ( pbi.display_fragments[ i + 1 ] == 0){
  162. FilterHoriz(pbi.LastFrameRecon,
  163. pbi.recon_pixel_index_table[i]+6,
  164. LineLength,FiltBoundingValue);
  165. }
  166. /* Bottom done if next row set */
  167. if( pbi.display_fragments[ i + LineFragments] == 0){
  168. FilterVert(pbi.LastFrameRecon,
  169. pbi.recon_pixel_index_table[i+LineFragments],
  170. LineLength, FiltBoundingValue);
  171. }
  172. }
  173. i++;
  174. /***************************************************************/
  175. /* middle columns */
  176. for ( n = 1 ; n < FragsAcross - 1 ; n++) {
  177. if( pbi.display_fragments[i] != 0){
  178. index = pbi.recon_pixel_index_table[i];
  179. /* Filter Left edge always */
  180. FilterHoriz(pbi.LastFrameRecon, index-2,
  181. LineLength, FiltBoundingValue);
  182. /* Filter right hand border only if the block to the right is
  183. not coded */
  184. if (pbi.display_fragments[ i + 1 ] == 0){
  185. FilterHoriz(pbi.LastFrameRecon,
  186. index+6,
  187. LineLength, FiltBoundingValue);
  188. }
  189. /* Bottom done if next row set */
  190. if(pbi.display_fragments[ i + LineFragments] == 0){
  191. FilterVert(pbi.LastFrameRecon,
  192. pbi.recon_pixel_index_table[i+LineFragments],
  193. LineLength, FiltBoundingValue);
  194. }
  195. }
  196. i++;
  197. }
  198. /***************************************************************/
  199. /* Last Column */
  200. if( pbi.display_fragments[i] != 0){
  201. /* Filter Left edge always */
  202. FilterHoriz(pbi.LastFrameRecon,
  203. pbi.recon_pixel_index_table[i] - 2 ,
  204. LineLength, FiltBoundingValue);
  205. /* Bottom done if next row set */
  206. if(pbi.display_fragments[ i + LineFragments] == 0){
  207. FilterVert(pbi.LastFrameRecon,
  208. pbi.recon_pixel_index_table[i+LineFragments],
  209. LineLength, FiltBoundingValue);
  210. }
  211. }
  212. i++;
  213. /***************************************************************/
  214. /* Middle Rows */
  215. /***************************************************************/
  216. for ( m = 1 ; m < FragsDown-1 ; m++) {
  217. /*****************************************************************/
  218. /* first column conditions */
  219. /* only do 2 prediction if fragment coded and on non intra or if
  220. all fragments are intra */
  221. if(pbi.display_fragments[i] != 0){
  222. index = pbi.recon_pixel_index_table[i];
  223. /* TopRow is always done */
  224. FilterVert(pbi.LastFrameRecon, index,
  225. LineLength, FiltBoundingValue);
  226. /* Filter right hand border only if the block to the right is
  227. not coded */
  228. if (pbi.display_fragments[ i + 1 ] == 0){
  229. FilterHoriz(pbi.LastFrameRecon, index + 6,
  230. LineLength, FiltBoundingValue);
  231. }
  232. /* Bottom done if next row set */
  233. if(pbi.display_fragments[ i + LineFragments] == 0){
  234. FilterVert(pbi.LastFrameRecon,
  235. pbi.recon_pixel_index_table[i+LineFragments],
  236. LineLength, FiltBoundingValue);
  237. }
  238. }
  239. i++;
  240. /*****************************************************************/
  241. /* middle columns */
  242. for ( n = 1 ; n < FragsAcross - 1 ; n++, i++){
  243. if( pbi.display_fragments[i] != 0){
  244. index = pbi.recon_pixel_index_table[i];
  245. /* Filter Left edge always */
  246. FilterHoriz(pbi.LastFrameRecon, index - 2,
  247. LineLength, FiltBoundingValue);
  248. /* TopRow is always done */
  249. FilterVert(pbi.LastFrameRecon, index,
  250. LineLength, FiltBoundingValue);
  251. /* Filter right hand border only if the block to the right
  252. is not coded */
  253. if (pbi.display_fragments[ i + 1 ] == 0){
  254. FilterHoriz(pbi.LastFrameRecon, index + 6,
  255. LineLength, FiltBoundingValue);
  256. }
  257. /* Bottom done if next row set */
  258. if(pbi.display_fragments[ i + LineFragments] == 0){
  259. FilterVert(pbi.LastFrameRecon,
  260. pbi.recon_pixel_index_table[i+LineFragments],
  261. LineLength, FiltBoundingValue);
  262. }
  263. }
  264. }
  265. /******************************************************************/
  266. /* Last Column */
  267. if( pbi.display_fragments[i] != 0){
  268. index = pbi.recon_pixel_index_table[i];
  269. /* Filter Left edge always*/
  270. FilterHoriz(pbi.LastFrameRecon, index - 2,
  271. LineLength, FiltBoundingValue);
  272. /* TopRow is always done */
  273. FilterVert(pbi.LastFrameRecon, index,
  274. LineLength, FiltBoundingValue);
  275. /* Bottom done if next row set */
  276. if(pbi.display_fragments[ i + LineFragments] == 0){
  277. FilterVert(pbi.LastFrameRecon,
  278. pbi.recon_pixel_index_table[i+LineFragments],
  279. LineLength, FiltBoundingValue);
  280. }
  281. }
  282. i++;
  283. }
  284. /*******************************************************************/
  285. /* Last Row */
  286. /* first column conditions */
  287. /* only do 2 prediction if fragment coded and on non intra or if
  288. all fragments are intra */
  289. if(pbi.display_fragments[i] != 0){
  290. index = pbi.recon_pixel_index_table[i];
  291. /* TopRow is always done */
  292. FilterVert(pbi.LastFrameRecon, index,
  293. LineLength, FiltBoundingValue);
  294. /* Filter right hand border only if the block to the right is
  295. not coded */
  296. if (pbi.display_fragments[ i + 1 ] == 0){
  297. FilterHoriz(pbi.LastFrameRecon, index+6,
  298. LineLength, FiltBoundingValue);
  299. }
  300. }
  301. i++;
  302. /******************************************************************/
  303. /* middle columns */
  304. for ( n = 1 ; n < FragsAcross - 1 ; n++, i++){
  305. if( pbi.display_fragments[i] != 0){
  306. index = pbi.recon_pixel_index_table[i];
  307. /* Filter Left edge always */
  308. FilterHoriz(pbi.LastFrameRecon, index-2,
  309. LineLength, FiltBoundingValue);
  310. /* TopRow is always done */
  311. FilterVert(pbi.LastFrameRecon, index,
  312. LineLength, FiltBoundingValue);
  313. /* Filter right hand border only if the block to the right is
  314. not coded */
  315. if (pbi.display_fragments[ i + 1 ] == 0){
  316. FilterHoriz(pbi.LastFrameRecon, index+6,
  317. LineLength, FiltBoundingValue);
  318. }
  319. }
  320. }
  321. /******************************************************************/
  322. /* Last Column */
  323. if(pbi.display_fragments[i] != 0){
  324. index = pbi.recon_pixel_index_table[i];
  325. /* Filter Left edge always */
  326. FilterHoriz(pbi.LastFrameRecon, index - 2,
  327. LineLength, FiltBoundingValue);
  328. /* TopRow is always done */
  329. FilterVert(pbi.LastFrameRecon, index,
  330. LineLength, FiltBoundingValue);
  331. }
  332. }
  333. }
  334. }