init_intra_maps.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. /*Daala video codec
  2. Copyright (c) 2012 Daala project contributors. All rights reserved.
  3. Redistribution and use in source and binary forms, with or without
  4. modification, are permitted provided that the following conditions are met:
  5. - Redistributions of source code must retain the above copyright notice, this
  6. list of conditions and the following disclaimer.
  7. - Redistributions in binary form must reproduce the above copyright notice,
  8. this list of conditions and the following disclaimer in the documentation
  9. and/or other materials provided with the distribution.
  10. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
  11. AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  12. IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  13. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  14. FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  15. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  16. SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  17. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  18. OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  19. OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/
  20. #ifdef HAVE_CONFIG_H
  21. #include "config.h"
  22. #endif
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <limits.h>
  26. #include <string.h>
  27. #include "intra_fit_tools.h"
  28. #include "../src/dct.c"
  29. #include "../src/internal.c"
  30. /*For validation purposes only.
  31. Copied from libvpx.*/
  32. #if B_SZ==4
  33. #define B_DC_PRED (OD_INTRA_DC)
  34. #define B_TM_PRED (OD_INTRA_TM)
  35. #define B_VE_PRED (OD_INTRA_VE)
  36. #define B_HE_PRED (OD_INTRA_HE)
  37. #define B_LD_PRED (OD_INTRA_LD)
  38. #define B_RD_PRED (OD_INTRA_RD)
  39. #define B_VR_PRED (OD_INTRA_VR)
  40. #define B_VL_PRED (OD_INTRA_VL)
  41. #define B_HU_PRED (OD_INTRA_HU)
  42. #define B_HD_PRED (OD_INTRA_HD)
  43. void vp8_intra4x4_predict_c(const unsigned char *src, int src_stride,
  44. int b_mode,
  45. unsigned char *dst, int dst_stride)
  46. {
  47. int i, r, c;
  48. const unsigned char *Above = src - src_stride;
  49. unsigned char Left[4];
  50. unsigned char top_left = Above[-1];
  51. Left[0] = src[-1];
  52. Left[1] = src[-1 + src_stride];
  53. Left[2] = src[-1 + 2 * src_stride];
  54. Left[3] = src[-1 + 3 * src_stride];
  55. switch (b_mode)
  56. {
  57. case B_DC_PRED:
  58. {
  59. int expected_dc = 0;
  60. for (i = 0; i < 4; i++)
  61. {
  62. expected_dc += Above[i];
  63. expected_dc += Left[i];
  64. }
  65. expected_dc = (expected_dc + 4) >> 3;
  66. for (r = 0; r < 4; r++)
  67. {
  68. for (c = 0; c < 4; c++)
  69. {
  70. dst[c] = expected_dc;
  71. }
  72. dst += dst_stride;
  73. }
  74. }
  75. break;
  76. case B_TM_PRED:
  77. {
  78. /* prediction similar to true_motion prediction */
  79. for (r = 0; r < 4; r++)
  80. {
  81. for (c = 0; c < 4; c++)
  82. {
  83. int pred = Above[c] - top_left + Left[r];
  84. if (pred < 0)
  85. pred = 0;
  86. if (pred > 255)
  87. pred = 255;
  88. dst[c] = pred;
  89. }
  90. dst += dst_stride;
  91. }
  92. }
  93. break;
  94. case B_VE_PRED:
  95. {
  96. unsigned int ap[4];
  97. ap[0] = (top_left + 2 * Above[0] + Above[1] + 2) >> 2;
  98. ap[1] = (Above[0] + 2 * Above[1] + Above[2] + 2) >> 2;
  99. ap[2] = (Above[1] + 2 * Above[2] + Above[3] + 2) >> 2;
  100. ap[3] = (Above[2] + 2 * Above[3] + Above[4] + 2) >> 2;
  101. for (r = 0; r < 4; r++)
  102. {
  103. for (c = 0; c < 4; c++)
  104. {
  105. dst[c] = ap[c];
  106. }
  107. dst += dst_stride;
  108. }
  109. }
  110. break;
  111. case B_HE_PRED:
  112. {
  113. unsigned int lp[4];
  114. lp[0] = (top_left + 2 * Left[0] + Left[1] + 2) >> 2;
  115. lp[1] = (Left[0] + 2 * Left[1] + Left[2] + 2) >> 2;
  116. lp[2] = (Left[1] + 2 * Left[2] + Left[3] + 2) >> 2;
  117. lp[3] = (Left[2] + 2 * Left[3] + Left[3] + 2) >> 2;
  118. for (r = 0; r < 4; r++)
  119. {
  120. for (c = 0; c < 4; c++)
  121. {
  122. dst[c] = lp[r];
  123. }
  124. dst += dst_stride;
  125. }
  126. }
  127. break;
  128. case B_LD_PRED:
  129. {
  130. const unsigned char *ptr = Above;
  131. dst[0 * dst_stride + 0] = (ptr[0] + ptr[1] * 2 + ptr[2] + 2) >> 2;
  132. dst[0 * dst_stride + 1] =
  133. dst[1 * dst_stride + 0] = (ptr[1] + ptr[2] * 2 + ptr[3] + 2) >> 2;
  134. dst[0 * dst_stride + 2] =
  135. dst[1 * dst_stride + 1] =
  136. dst[2 * dst_stride + 0] = (ptr[2] + ptr[3] * 2 + ptr[4] + 2) >> 2;
  137. dst[0 * dst_stride + 3] =
  138. dst[1 * dst_stride + 2] =
  139. dst[2 * dst_stride + 1] =
  140. dst[3 * dst_stride + 0] = (ptr[3] + ptr[4] * 2 + ptr[5] + 2) >> 2;
  141. dst[1 * dst_stride + 3] =
  142. dst[2 * dst_stride + 2] =
  143. dst[3 * dst_stride + 1] = (ptr[4] + ptr[5] * 2 + ptr[6] + 2) >> 2;
  144. dst[2 * dst_stride + 3] =
  145. dst[3 * dst_stride + 2] = (ptr[5] + ptr[6] * 2 + ptr[7] + 2) >> 2;
  146. dst[3 * dst_stride + 3] = (ptr[6] + ptr[7] * 2 + ptr[7] + 2) >> 2;
  147. }
  148. break;
  149. case B_RD_PRED:
  150. {
  151. unsigned char pp[9];
  152. pp[0] = Left[3];
  153. pp[1] = Left[2];
  154. pp[2] = Left[1];
  155. pp[3] = Left[0];
  156. pp[4] = top_left;
  157. pp[5] = Above[0];
  158. pp[6] = Above[1];
  159. pp[7] = Above[2];
  160. pp[8] = Above[3];
  161. dst[3 * dst_stride + 0] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
  162. dst[3 * dst_stride + 1] =
  163. dst[2 * dst_stride + 0] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
  164. dst[3 * dst_stride + 2] =
  165. dst[2 * dst_stride + 1] =
  166. dst[1 * dst_stride + 0] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
  167. dst[3 * dst_stride + 3] =
  168. dst[2 * dst_stride + 2] =
  169. dst[1 * dst_stride + 1] =
  170. dst[0 * dst_stride + 0] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
  171. dst[2 * dst_stride + 3] =
  172. dst[1 * dst_stride + 2] =
  173. dst[0 * dst_stride + 1] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
  174. dst[1 * dst_stride + 3] =
  175. dst[0 * dst_stride + 2] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
  176. dst[0 * dst_stride + 3] = (pp[6] + pp[7] * 2 + pp[8] + 2) >> 2;
  177. }
  178. break;
  179. case B_VR_PRED:
  180. {
  181. unsigned char pp[9];
  182. pp[0] = Left[3];
  183. pp[1] = Left[2];
  184. pp[2] = Left[1];
  185. pp[3] = Left[0];
  186. pp[4] = top_left;
  187. pp[5] = Above[0];
  188. pp[6] = Above[1];
  189. pp[7] = Above[2];
  190. pp[8] = Above[3];
  191. dst[3 * dst_stride + 0] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
  192. dst[2 * dst_stride + 0] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
  193. dst[3 * dst_stride + 1] =
  194. dst[1 * dst_stride + 0] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
  195. dst[2 * dst_stride + 1] =
  196. dst[0 * dst_stride + 0] = (pp[4] + pp[5] + 1) >> 1;
  197. dst[3 * dst_stride + 2] =
  198. dst[1 * dst_stride + 1] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
  199. dst[2 * dst_stride + 2] =
  200. dst[0 * dst_stride + 1] = (pp[5] + pp[6] + 1) >> 1;
  201. dst[3 * dst_stride + 3] =
  202. dst[1 * dst_stride + 2] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
  203. dst[2 * dst_stride + 3] =
  204. dst[0 * dst_stride + 2] = (pp[6] + pp[7] + 1) >> 1;
  205. dst[1 * dst_stride + 3] = (pp[6] + pp[7] * 2 + pp[8] + 2) >> 2;
  206. dst[0 * dst_stride + 3] = (pp[7] + pp[8] + 1) >> 1;
  207. }
  208. break;
  209. case B_VL_PRED:
  210. {
  211. const unsigned char *pp = Above;
  212. dst[0 * dst_stride + 0] = (pp[0] + pp[1] + 1) >> 1;
  213. dst[1 * dst_stride + 0] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
  214. dst[2 * dst_stride + 0] =
  215. dst[0 * dst_stride + 1] = (pp[1] + pp[2] + 1) >> 1;
  216. dst[1 * dst_stride + 1] =
  217. dst[3 * dst_stride + 0] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
  218. dst[2 * dst_stride + 1] =
  219. dst[0 * dst_stride + 2] = (pp[2] + pp[3] + 1) >> 1;
  220. dst[3 * dst_stride + 1] =
  221. dst[1 * dst_stride + 2] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
  222. dst[0 * dst_stride + 3] =
  223. dst[2 * dst_stride + 2] = (pp[3] + pp[4] + 1) >> 1;
  224. dst[1 * dst_stride + 3] =
  225. dst[3 * dst_stride + 2] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
  226. dst[2 * dst_stride + 3] = (pp[4] + pp[5] + 1) >> 1;
  227. dst[3 * dst_stride + 3] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
  228. }
  229. break;
  230. case B_HD_PRED:
  231. {
  232. unsigned char pp[9];
  233. pp[0] = Left[3];
  234. pp[1] = Left[2];
  235. pp[2] = Left[1];
  236. pp[3] = Left[0];
  237. pp[4] = top_left;
  238. pp[5] = Above[0];
  239. pp[6] = Above[1];
  240. pp[7] = Above[2];
  241. pp[8] = Above[3];
  242. dst[3 * dst_stride + 0] = (pp[0] + pp[1] + 1) >> 1;
  243. dst[3 * dst_stride + 1] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
  244. dst[2 * dst_stride + 0] =
  245. dst[3 * dst_stride + 2] = (pp[1] + pp[2] + 1) >> 1;
  246. dst[2 * dst_stride + 1] =
  247. dst[3 * dst_stride + 3] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
  248. dst[2 * dst_stride + 2] =
  249. dst[1 * dst_stride + 0] = (pp[2] + pp[3] + 1) >> 1;
  250. dst[2 * dst_stride + 3] =
  251. dst[1 * dst_stride + 1] = (pp[2] + pp[3] * 2 + pp[4] + 2) >> 2;
  252. dst[1 * dst_stride + 2] =
  253. dst[0 * dst_stride + 0] = (pp[3] + pp[4] + 1) >> 1;
  254. dst[1 * dst_stride + 3] =
  255. dst[0 * dst_stride + 1] = (pp[3] + pp[4] * 2 + pp[5] + 2) >> 2;
  256. dst[0 * dst_stride + 2] = (pp[4] + pp[5] * 2 + pp[6] + 2) >> 2;
  257. dst[0 * dst_stride + 3] = (pp[5] + pp[6] * 2 + pp[7] + 2) >> 2;
  258. }
  259. break;
  260. case B_HU_PRED:
  261. {
  262. unsigned char *pp = Left;
  263. dst[0 * dst_stride + 0] = (pp[0] + pp[1] + 1) >> 1;
  264. dst[0 * dst_stride + 1] = (pp[0] + pp[1] * 2 + pp[2] + 2) >> 2;
  265. dst[0 * dst_stride + 2] =
  266. dst[1 * dst_stride + 0] = (pp[1] + pp[2] + 1) >> 1;
  267. dst[0 * dst_stride + 3] =
  268. dst[1 * dst_stride + 1] = (pp[1] + pp[2] * 2 + pp[3] + 2) >> 2;
  269. dst[1 * dst_stride + 2] =
  270. dst[2 * dst_stride + 0] = (pp[2] + pp[3] + 1) >> 1;
  271. dst[1 * dst_stride + 3] =
  272. dst[2 * dst_stride + 1] = (pp[2] + pp[3] * 2 + pp[3] + 2) >> 2;
  273. dst[2 * dst_stride + 2] =
  274. dst[2 * dst_stride + 3] =
  275. dst[3 * dst_stride + 0] =
  276. dst[3 * dst_stride + 1] =
  277. dst[3 * dst_stride + 2] =
  278. dst[3 * dst_stride + 3] = pp[3];
  279. }
  280. break;
  281. }
  282. }
  283. #endif
  284. #define USE_DCT_SATD (0)
  285. #if !(USE_DCT_SATD&&B_SZ==4)
  286. static void od_diff_hadamard(short _buf[B_SZ*B_SZ],
  287. const unsigned char *_src,int _src_stride,
  288. const unsigned char *_ref,int _ref_stride){
  289. int i;
  290. for(i=0;i<B_SZ;i++){
  291. int t[B_SZ];
  292. int r;
  293. int j;
  294. int k;
  295. int l;
  296. /*Hadamard stage 1:*/
  297. for(j=0;j<(B_SZ>>1);j++){
  298. t[j]=_src[j]-_ref[j]+_src[j+(B_SZ>>1)]-_ref[j+(B_SZ>>1)];
  299. t[j+(B_SZ>>1)]=_src[j]-_ref[j]-_src[j+(B_SZ>>1)]+_ref[j+(B_SZ>>1)];
  300. }
  301. /*Hadamard stages 2...N-1:*/
  302. for(l=B_SZ>>2;l>1;l>>=1){
  303. for(k=0;k<B_SZ;k+=2*l){
  304. for(j=0;j<l;j++){
  305. r=t[j+k];
  306. t[j+k]=r+t[j+k+l];
  307. t[j+k+l]=r-t[j+k+l];
  308. }
  309. }
  310. }
  311. /*Hadamard stage N:*/
  312. for(k=0;k<B_SZ;k+=2){
  313. _buf[k*B_SZ+i]=(short)(t[k]+t[k+1]);
  314. _buf[(k+1)*B_SZ+i]=(short)(t[k]-t[k+1]);
  315. }
  316. _src+=_src_stride;
  317. _ref+=_ref_stride;
  318. }
  319. }
  320. static unsigned od_hadamard_sad(const short _buf[B_SZ*B_SZ]){
  321. unsigned sad;
  322. int i;
  323. sad=0;
  324. for(i=0;i<B_SZ;i++){
  325. int t[B_SZ];
  326. int j;
  327. int k;
  328. int l;
  329. int r;
  330. /*Hadamard stage 1:*/
  331. for(j=0;j<(B_SZ>>1);j++){
  332. t[j]=_buf[i*B_SZ+j]+_buf[i*B_SZ+j+(B_SZ>>1)];
  333. t[j+(B_SZ>>1)]=_buf[i*B_SZ+j]-_buf[i*B_SZ+j+(B_SZ>>1)];
  334. }
  335. /*Hadamard stages 2...N-1:*/
  336. for(l=B_SZ>>2;l>1;l>>=1){
  337. for(k=0;k<B_SZ;k+=2*l){
  338. for(j=0;j<l;j++){
  339. r=t[j+k];
  340. t[j+k]=r+t[j+k+l];
  341. t[j+k+l]=r-t[j+k+l];
  342. }
  343. }
  344. }
  345. /*Hadamard stage N:*/
  346. for(k=0;k<B_SZ;k+=2){
  347. sad+=abs(t[k]+t[k+1]);
  348. sad+=abs(t[k]-t[k+1]);
  349. }
  350. }
  351. return sad;
  352. }
  353. static unsigned od_satd(const unsigned char *_src,int _src_stride,
  354. const unsigned char *_ref,int _ref_stride){
  355. short buf[B_SZ*B_SZ];
  356. od_diff_hadamard(buf,_src,_src_stride,_ref,_ref_stride);
  357. return od_hadamard_sad(buf);
  358. }
  359. #else
  360. /*Computes the SATD using the actual DCT, instead of the Hadamard transform.
  361. This is useful for comparing SATD numbers to the frequency domain techniques
  362. without having to worry about scaling.*/
  363. static unsigned od_satd(const unsigned char *_src,int _src_stride,
  364. const unsigned char *_ref,int _ref_stride){
  365. od_coeff buf[B_SZ*B_SZ];
  366. unsigned satd;
  367. int i;
  368. int j;
  369. OD_ASSERT(B_SZ==4);
  370. for(i=0;i<B_SZ;i++){
  371. for(j=0;j<B_SZ;j++){
  372. buf[B_SZ*i+j]=_src[j]-_ref[j];
  373. }
  374. _src+=_src_stride;
  375. _ref+=_ref_stride;
  376. }
  377. #if B_SZ_LOG>=OD_LOG_BSIZE0&&B_SZ_LOG<OD_LOG_BSIZE0+OD_NBSIZES
  378. (*OD_FDCT_2D[B_SZ_LOG-OD_LOG_BSIZE0])(buf,B_SZ,buf,B_SZ);
  379. #else
  380. # error "Need an fDCT implementation for this block size."
  381. #endif
  382. satd=0;
  383. for(i=0;i<B_SZ;i++){
  384. for(j=0;j<B_SZ;j++)satd+=abs(buf[B_SZ*i+j]);
  385. }
  386. return satd;
  387. }
  388. #endif
  389. typedef struct init_intra_maps_ctx init_intra_maps_ctx;
  390. struct init_intra_maps_ctx{
  391. const char *name;
  392. unsigned char *map;
  393. unsigned *weights;
  394. int pli;
  395. int nxblocks;
  396. int nyblocks;
  397. long long n;
  398. double satd_avg;
  399. };
  400. static int init_intra_plane_start(void *_ctx,const char *_name,
  401. const video_input_info *_info,int _pli,int _nxblocks,int _nyblocks){
  402. init_intra_maps_ctx *ctx;
  403. (void)_info;
  404. ctx=(init_intra_maps_ctx *)_ctx;
  405. ctx->name=_name;
  406. ctx->map=(unsigned char *)malloc(_nxblocks*(size_t)_nyblocks);
  407. ctx->weights=(unsigned *)malloc(
  408. _nxblocks*(size_t)_nyblocks*sizeof(*ctx->weights));
  409. ctx->pli=_pli;
  410. ctx->nxblocks=_nxblocks;
  411. ctx->nyblocks=_nyblocks;
  412. return EXIT_SUCCESS;
  413. }
  414. static void init_intra_block(void *_ctx,const unsigned char *_data,int _stride,
  415. int _bi,int _bj){
  416. init_intra_maps_ctx *ctx;
  417. unsigned best_satd;
  418. unsigned next_best_satd;
  419. int mode;
  420. int best_mode;
  421. ctx=(init_intra_maps_ctx *)_ctx;
  422. best_mode=0;
  423. best_satd=UINT_MAX;
  424. next_best_satd=UINT_MAX;
  425. for(mode=0;mode<10;mode++){
  426. unsigned char block[B_SZ*B_SZ];
  427. unsigned satd;
  428. memset(block,0,B_SZ*B_SZ);
  429. vp8_intra_predict(block,B_SZ,_data,_stride,mode);
  430. #if B_SZ==4
  431. {
  432. unsigned char block2[B_SZ*B_SZ];
  433. vp8_intra4x4_predict_c(_data,_stride,mode,block2,B_SZ);
  434. if(memcmp(block,block2,sizeof(block2))!=0){
  435. fprintf(stderr,"Intra prediction mismatch.\n");
  436. exit(EXIT_FAILURE);
  437. }
  438. }
  439. #endif
  440. satd=od_satd(block,B_SZ,_data,_stride);
  441. if(satd<best_satd){
  442. next_best_satd=best_satd;
  443. best_satd=satd;
  444. best_mode=mode;
  445. }
  446. else if(satd<next_best_satd)next_best_satd=satd;
  447. }
  448. ctx->satd_avg+=(best_satd-ctx->satd_avg)/++(ctx->n);
  449. ctx->map[_bj*ctx->nxblocks+_bi]=(unsigned char)best_mode;
  450. ctx->weights[_bj*ctx->nxblocks+_bi]=next_best_satd-best_satd;
  451. }
  452. static int init_intra_plane_finish(void *_ctx){
  453. init_intra_maps_ctx *ctx;
  454. FILE *map_file;
  455. char *map_filename;
  456. FILE *weights_file;
  457. char *weights_filename;
  458. ctx=(init_intra_maps_ctx *)_ctx;
  459. map_filename=get_map_filename(ctx->name,
  460. ctx->pli,ctx->nxblocks,ctx->nyblocks);
  461. map_file=fopen(map_filename,"wb");
  462. if(map_file==NULL){
  463. fprintf(stderr,"Error opening output file '%s'.\n",map_filename);
  464. return EXIT_FAILURE;
  465. }
  466. if(fwrite(ctx->map,ctx->nxblocks*(size_t)ctx->nyblocks,1,map_file)<1){
  467. fprintf(stderr,"Error writing to output file '%s'.\n",map_filename);
  468. return EXIT_FAILURE;
  469. }
  470. fclose(map_file);
  471. free(map_filename);
  472. weights_filename=get_weights_filename(ctx->name,
  473. ctx->pli,ctx->nxblocks,ctx->nyblocks);
  474. weights_file=fopen(weights_filename,"wb");
  475. if(weights_file==NULL){
  476. fprintf(stderr,"Error opening output file '%s'.\n",weights_filename);
  477. return EXIT_FAILURE;
  478. }
  479. if(fwrite(ctx->weights,
  480. ctx->nxblocks*(size_t)ctx->nyblocks*sizeof(*ctx->weights),1,
  481. weights_file)<1){
  482. fprintf(stderr,"Error writing to output file '%s'.\n",weights_filename);
  483. return EXIT_FAILURE;
  484. }
  485. fclose(weights_file);
  486. free(weights_filename);
  487. free(ctx->weights);
  488. free(ctx->map);
  489. printf("Average SATD: %G\n",ctx->satd_avg);
  490. return EXIT_SUCCESS;
  491. }
  492. int main(int _argc,const char **_argv){
  493. init_intra_maps_ctx ctx;
  494. ctx.n=0;
  495. ctx.satd_avg=0;
  496. return apply_to_blocks(&ctx,init_intra_plane_start,init_intra_block,
  497. init_intra_plane_finish,_argc,_argv);
  498. }