cfl_stats.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. #ifdef HAVE_CONFIG_H
  2. #include "config.h"
  3. #endif
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include "od_defs.h"
  7. #include "od_filter.h"
  8. #include "od_intra.h"
  9. #include "image_tools.h"
  10. #include "stats_tools.h"
  11. #include "../src/dct.h"
  12. #include "../src/intra.h"
  13. #define PRINT_PROGRESS (0)
  14. #define DEBUG_CFL_PRED (0)
  15. #define OUTPUT_PLANES (0)
  16. #if B_SZ_LOG!=3
  17. # error "Only B_SZ=8 currently supported."
  18. #endif
  19. typedef struct cfl_stats_ctx cfl_stats_ctx;
  20. struct cfl_stats_ctx {
  21. int n;
  22. int curr_pli;
  23. image_data img[3];
  24. intra_stats gb_fdp[2];
  25. intra_stats gb_cfl[2];
  26. intra_stats st_fdp[2];
  27. intra_stats st_cfl[2];
  28. };
  29. static void cfl_stats_ctx_init(cfl_stats_ctx *_this){
  30. int i;
  31. _this->n=0;
  32. for (i=0;i<2;i++) {
  33. intra_stats_init(&_this->gb_fdp[i],B_SZ_LOG-1);
  34. intra_stats_init(&_this->gb_cfl[i],B_SZ_LOG-1);
  35. intra_stats_init(&_this->st_fdp[i],B_SZ_LOG-1);
  36. intra_stats_init(&_this->st_cfl[i],B_SZ_LOG-1);
  37. }
  38. }
  39. static void cfl_stats_ctx_clear(cfl_stats_ctx *_this){
  40. int i;
  41. for (i=0;i<2;i++) {
  42. intra_stats_clear(&_this->gb_fdp[i]);
  43. intra_stats_clear(&_this->gb_cfl[i]);
  44. intra_stats_clear(&_this->st_fdp[i]);
  45. intra_stats_clear(&_this->st_cfl[i]);
  46. }
  47. }
  48. static void cfl_stats_ctx_combine(cfl_stats_ctx *_a,cfl_stats_ctx *_b) {
  49. int i;
  50. if (_b->n==0) {
  51. return;
  52. }
  53. for (i=0;i<2;i++) {
  54. intra_stats_combine(&_a->gb_fdp[i],&_b->gb_fdp[i]);
  55. intra_stats_combine(&_a->gb_cfl[i],&_b->gb_cfl[i]);
  56. }
  57. _a->n+=_b->n;
  58. }
  59. static void od_pre_block(void *_ctx,const unsigned char *_data,int _stride,
  60. int _bi,int _bj){
  61. cfl_stats_ctx *ctx;
  62. #if PRINT_PROGRESS
  63. if(_bi==0&&_bj==0){
  64. fprintf(stdout,"in od_pre_block\n");
  65. }
  66. #endif
  67. ctx=(cfl_stats_ctx *)_ctx;
  68. image_data_pre_block(&ctx->img[ctx->curr_pli],_data,_stride,_bi,_bj);
  69. }
  70. static void od_fdct_block(void *_ctx,const unsigned char *_data,int _stride,
  71. int _bi,int _bj){
  72. cfl_stats_ctx *ctx;
  73. (void)_data;
  74. (void)_stride;
  75. #if PRINT_PROGRESS
  76. if(_bi==0&&_bj==0){
  77. fprintf(stdout,"in od_fdct_block\n");
  78. }
  79. #endif
  80. ctx=(cfl_stats_ctx *)_ctx;
  81. image_data_fdct_block(&ctx->img[ctx->curr_pli],_bi,_bj);
  82. }
  83. #if TF_BLOCKS
  84. static void od_tf_block(void *_ctx,const unsigned char *_data,int _stride,
  85. int _bi,int _bj){
  86. cfl_stats_ctx *ctx;
  87. (void)_data;
  88. (void)_stride;
  89. #if PRINT_PROGRESS
  90. if(_bi==0&&_bj==0){
  91. fprintf(stdout,"in od_tf_block\n");
  92. }
  93. #endif
  94. ctx=(cfl_stats_ctx *)_ctx;
  95. image_data_tf_block(&ctx->img[ctx->curr_pli],_bi,_bj);
  96. }
  97. #endif
  98. static void od_mode_block(void *_ctx,const unsigned char *_data,int _stride,
  99. int _bi,int _bj){
  100. cfl_stats_ctx *ctx;
  101. (void)_data;
  102. (void)_stride;
  103. ctx=(cfl_stats_ctx *)_ctx;
  104. if (ctx->curr_pli==0) {
  105. od_coeff block[5*B_SZ_MAX*B_SZ_MAX];
  106. #if PRINT_PROGRESS
  107. if(_bi==0&&_bj==0){
  108. fprintf(stdout,"in od_mode_block\n");
  109. }
  110. #endif
  111. image_data_load_block(&ctx->img[0],_bi,_bj,block);
  112. ctx->img[0].mode[ctx->img[0].nxblocks*_bj+_bi]=
  113. od_select_mode_satd(block,NULL,ctx->img[0].b_sz_log);
  114. }
  115. }
  116. static void od_fdp_pred_block(void *_ctx,const unsigned char *_data,
  117. int _stride,int _bi,int _bj){
  118. cfl_stats_ctx *ctx;
  119. (void)_data;
  120. (void)_stride;
  121. ctx=(cfl_stats_ctx *)_ctx;
  122. if (ctx->curr_pli>0) {
  123. #if PRINT_PROGRESS
  124. if(_bi==0&&_bj==0){
  125. fprintf(stdout,"in od_fdp_pred_block\n");
  126. }
  127. #endif
  128. ctx->img[ctx->curr_pli].mode[ctx->img[ctx->curr_pli].nxblocks*_bj+_bi]=
  129. ctx->img[0].mode[ctx->img[0].nxblocks*_bj+_bi];
  130. image_data_pred_block(&ctx->img[ctx->curr_pli],_bi,_bj);
  131. }
  132. }
  133. static void od_fdp_stats_block(void *_ctx,const unsigned char *_data,
  134. int _stride,int _bi,int _bj){
  135. cfl_stats_ctx *ctx;
  136. (void)_data;
  137. (void)_stride;
  138. ctx=(cfl_stats_ctx *)_ctx;
  139. if (ctx->curr_pli>0) {
  140. #if PRINT_PROGRESS
  141. if(_bi==0&&_bj==0){
  142. fprintf(stdout,"in od_fdp_stats_block\n");
  143. }
  144. #endif
  145. image_data_stats_block(&ctx->img[ctx->curr_pli],_data,_stride,_bi,_bj,
  146. &ctx->st_fdp[ctx->curr_pli-1]);
  147. }
  148. }
  149. static void od_cfl_pred_block(void *_ctx,const unsigned char *_data,
  150. int _stride,int _bi,int _bj){
  151. cfl_stats_ctx *ctx;
  152. (void)_data;
  153. (void)_stride;
  154. ctx=(cfl_stats_ctx *)_ctx;
  155. if (ctx->curr_pli>0) {
  156. image_data *img;
  157. image_data *img0;
  158. int b_sz;
  159. int mode;
  160. od_coeff p[B_SZ_MAX*B_SZ_MAX];
  161. od_coeff c[2*B_SZ_MAX*2*B_SZ_MAX];
  162. od_coeff l[2*B_SZ_MAX*2*B_SZ_MAX];
  163. unsigned char bsize[8*8];
  164. int bx;
  165. int by;
  166. int i;
  167. int j;
  168. double *pred;
  169. #if PRINT_PROGRESS
  170. if(_bi==0&&_bj==0){
  171. fprintf(stdout,"in od_cfl_pred_block\n");
  172. }
  173. #endif
  174. img=&ctx->img[ctx->curr_pli];
  175. img0=&ctx->img[0];
  176. b_sz=1<<img->b_sz_log;
  177. for (i=0;i<8*8;i++) {
  178. bsize[i]=B_SZ_LOG-OD_LOG_BSIZE0;
  179. }
  180. mode=img->mode[img->nxblocks*_bj+_bi]=
  181. ctx->img[0].mode[ctx->img[0].nxblocks*_bj+_bi];
  182. for (by=0;by<2;by++) {
  183. for (bx=0;bx<2;bx++) {
  184. od_coeff *fdct;
  185. fdct=&img->fdct[img->fdct_stride*b_sz*(_bj+by)+b_sz*(_bi+bx)];
  186. for (j=0;j<b_sz;j++) {
  187. for (i=0;i<b_sz;i++) {
  188. c[(by*b_sz+j)*2*b_sz+bx*b_sz+i]=fdct[img->fdct_stride*j+i];
  189. }
  190. }
  191. fdct=&img0->fdct[img0->fdct_stride*2*b_sz*(_bj+by)+2*b_sz*(_bi+bx)];
  192. od_resample_luma_coeffs(&l[by*b_sz*2*b_sz+bx*b_sz],2*b_sz,fdct,img0->fdct_stride,1,1,0,1);
  193. }
  194. }
  195. od_chroma_pred(p,c,l,2*b_sz,1,1,
  196. img->b_sz_log-OD_LOG_BSIZE0,1,1,bsize,8,OD_INTRA_CHROMA_WEIGHTS_Q8[mode]);
  197. pred=&img->pred[img->pred_stride*b_sz*_bj+b_sz*_bi];
  198. for (j=0;j<b_sz;j++) {
  199. for (i=0;i<b_sz;i++) {
  200. pred[img->pred_stride*j+i]=p[b_sz*j+i];
  201. }
  202. }
  203. #if DEBUG_CFL_PRED
  204. if (ctx->curr_pli>0) {
  205. if (_bi==0&&_bj==0) {
  206. od_coeff *block;
  207. fprintf(stderr,"%i %i\n",_bi,_bj);
  208. fprintf(stderr,"luma (time)\n");
  209. block=&img0->pre[img0->pre_stride*b_sz*(2*_bj+1)+b_sz*(2*_bi+1)];
  210. for (j=0;j<4*b_sz;j++) {
  211. if (j==2*b_sz) {
  212. for (i=0;i<4*b_sz;i++) {
  213. fprintf(stderr,"%s-----",i==2*b_sz?"+":"");
  214. }
  215. fprintf(stderr,"\n");
  216. }
  217. for (i=0;i<4*b_sz;i++) {
  218. fprintf(stderr,"%s%4i ",i==2*b_sz?"|":"",block[j*img0->pre_stride+i]);
  219. }
  220. fprintf(stderr,"\n");
  221. }
  222. fprintf(stderr,"luma (freq)\n");
  223. block=&img0->fdct[img0->fdct_stride*2*b_sz*_bj+2*b_sz*_bi];
  224. for (j=0;j<4*b_sz;j++) {
  225. if (j==2*b_sz) {
  226. for (i=0;i<4*b_sz;i++) {
  227. fprintf(stderr,"%s-----",i==2*b_sz?"+":"");
  228. }
  229. fprintf(stderr,"\n");
  230. }
  231. for (i=0;i<4*b_sz;i++) {
  232. fprintf(stderr,"%s%4i ",i==2*b_sz?"|":"",block[j*img0->fdct_stride+i]);
  233. }
  234. fprintf(stderr,"\n");
  235. }
  236. fprintf(stderr,"luma (resampled)\n");
  237. for (j=0;j<2*b_sz;j++) {
  238. if (j==b_sz) {
  239. for (i=0;i<2*b_sz;i++) {
  240. fprintf(stderr,"%s-----",i==b_sz?"+":"");
  241. }
  242. fprintf(stderr,"\n");
  243. }
  244. for (i=0;i<2*b_sz;i++) {
  245. fprintf(stderr,"%s%4i ",i==b_sz?"|":"",l[j*2*b_sz+i]);
  246. }
  247. fprintf(stderr,"\n");
  248. }
  249. fprintf(stderr,"chroma %i\n",ctx->curr_pli);
  250. for (j=0;j<2*b_sz;j++) {
  251. if (j==b_sz) {
  252. for (i=0;i<2*b_sz;i++) {
  253. fprintf(stderr,"%s-----",i==b_sz?"+":"");
  254. }
  255. fprintf(stderr,"\n");
  256. }
  257. for (i=0;i<2*b_sz;i++) {
  258. fprintf(stderr,"%s%4i ",i==b_sz?"|":"",c[j*2*b_sz+i]);
  259. }
  260. fprintf(stderr,"\n");
  261. }
  262. fprintf(stderr,"pred\n");
  263. for (j=0;j<b_sz;j++) {
  264. for (i=0;i<b_sz;i++) {
  265. fprintf(stderr,"%4i ",p[b_sz*j+i]);
  266. }
  267. fprintf(stderr,"\n");
  268. }
  269. }
  270. }
  271. #endif
  272. }
  273. }
  274. static void od_cfl_stats_block(void *_ctx,const unsigned char *_data,
  275. int _stride,int _bi,int _bj){
  276. cfl_stats_ctx *ctx;
  277. (void)_data;
  278. (void)_stride;
  279. ctx=(cfl_stats_ctx *)_ctx;
  280. if (ctx->curr_pli>0) {
  281. #if PRINT_PROGRESS
  282. if(_bi==0&&_bj==0){
  283. fprintf(stdout,"in od_cfl_stats_block\n");
  284. }
  285. #endif
  286. image_data_stats_block(&ctx->img[ctx->curr_pli],_data,_stride,_bi,_bj,
  287. &ctx->st_cfl[ctx->curr_pli-1]);
  288. }
  289. }
  290. static int stats_start(void *_ctx,const char *_name,
  291. const video_input_info *_info,int _pli,int _nxblocks,int _nyblocks){
  292. cfl_stats_ctx *ctx;
  293. ctx=(cfl_stats_ctx *)_ctx;
  294. ctx->curr_pli=_pli;
  295. image_data_init(&ctx->img[_pli],_name,B_SZ_LOG-(_pli!=0),_nxblocks,_nyblocks);
  296. if (_pli==0) {
  297. fprintf(stdout,"%s\n",_name);
  298. ctx->n++;
  299. }
  300. if (_pli>0) {
  301. intra_stats_reset(&ctx->st_fdp[_pli-1]);
  302. intra_stats_reset(&ctx->st_cfl[_pli-1]);
  303. }
  304. return EXIT_SUCCESS;
  305. }
  306. static int stats_finish(void *_ctx){
  307. int i;
  308. cfl_stats_ctx *ctx;
  309. ctx=(cfl_stats_ctx *)_ctx;
  310. if (ctx->curr_pli==2) {
  311. double *od_scale;
  312. od_scale=OD_SCALE[B_SZ_LOG-1-OD_LOG_BSIZE0];
  313. for (i=0;i<2;i++) {
  314. char label[128];
  315. sprintf(label,"Frequency-Domain Predictors (plane %i)",i+1);
  316. intra_stats_combine(&ctx->gb_fdp[i],&ctx->st_fdp[i]);
  317. intra_stats_correct(&ctx->st_fdp[i]);
  318. intra_stats_print(&ctx->st_fdp[i],label,od_scale);
  319. sprintf(label,"Chroma-from-Luma Predictors (plane %i)",i+1);
  320. intra_stats_combine(&ctx->gb_cfl[i],&ctx->st_cfl[i]);
  321. intra_stats_correct(&ctx->st_cfl[i]);
  322. intra_stats_print(&ctx->st_cfl[i],label,od_scale);
  323. }
  324. for (i=0;i<3;i++) {
  325. image_data_clear(&ctx->img[i]);
  326. }
  327. }
  328. return EXIT_SUCCESS;
  329. }
  330. const block_func BLOCKS[]={
  331. od_pre_block,
  332. od_fdct_block,
  333. #if TF_BLOCKS
  334. od_tf_block,
  335. #endif
  336. od_mode_block,
  337. od_fdp_pred_block,
  338. od_fdp_stats_block,
  339. od_cfl_pred_block,
  340. od_cfl_stats_block,
  341. };
  342. const int NBLOCKS=sizeof(BLOCKS)/sizeof(*BLOCKS);
  343. /* There is a bug in get_intra_dims where chroma blocks do not line up under
  344. luma blocks. */
  345. static void cfl_get_intra_dims(const video_input_info *_info,int _pli,
  346. int _padding,int *_x0,int *_y0,int *_nxblocks,int *_nyblocks){
  347. int xshift;
  348. int yshift;
  349. int padding;
  350. xshift=_pli!=0&&!(_info->pixel_fmt&1);
  351. yshift=_pli!=0&&!(_info->pixel_fmt&2);
  352. OD_ASSERT(xshift==yshift);
  353. padding=_padding<<B_SZ_LOG;
  354. /*An offset of 1 would be fine to provide enough context for VP8-style intra
  355. prediction, but for frequency-domain prediction, we'll want a full block,
  356. plus overlap.*/
  357. *_x0=(_info->pic_x>>xshift)+(padding>>1+xshift);
  358. *_y0=(_info->pic_y>>yshift)+(padding>>1+yshift);
  359. /*We take an extra block off the end to give enough context for above-right
  360. intra prediction.*/
  361. *_nxblocks=_info->pic_w-padding>>B_SZ_LOG;
  362. *_nyblocks=_info->pic_h-padding>>B_SZ_LOG;
  363. }
  364. static int cfl_apply_to_blocks(void *_ctx,int _ctx_sz,int _plmask,int _padding,
  365. plane_start_func _start,int _nfuncs,const block_func *_funcs,
  366. plane_finish_func _finish,int _argc,const char *_argv[]){
  367. int ai;
  368. #pragma omp parallel for schedule(dynamic)
  369. for(ai=1;ai<_argc;ai++){
  370. FILE *fin;
  371. video_input vid;
  372. video_input_info info;
  373. video_input_ycbcr ycbcr;
  374. int pli;
  375. int tid;
  376. unsigned char *ctx;
  377. fin=fopen(_argv[ai],"rb");
  378. if(fin==NULL){
  379. fprintf(stderr,"Could not open '%s' for reading.\n",_argv[ai]);
  380. continue;
  381. }
  382. if(video_input_open(&vid,fin)<0){
  383. fprintf(stderr,"Error reading video info from '%s'.\n",_argv[ai]);
  384. continue;
  385. }
  386. video_input_get_info(&vid,&info);
  387. if(video_input_fetch_frame(&vid,ycbcr,NULL)<0){
  388. fprintf(stderr,"Error reading first frame from '%s'.\n",_argv[ai]);
  389. continue;
  390. }
  391. tid=OD_OMP_GET_THREAD;
  392. ctx=((unsigned char *)_ctx)+tid*_ctx_sz;
  393. #if OUTPUT_PLANES
  394. {
  395. char *names[]={"y","cb","cr"};
  396. for (pli=0;pli<3;pli++) {
  397. int w;
  398. int h;
  399. int u;
  400. int v;
  401. int x0;
  402. int y0;
  403. const unsigned char *data;
  404. w=info.pic_w>>(pli!=0);
  405. h=info.pic_h>>(pli!=0);
  406. x0=info.pic_x>>(pli!=0);
  407. y0=info.pic_y>>(pli!=0);
  408. data=ycbcr[pli].data;
  409. fprintf(stderr,"%s=[",names[pli]);
  410. for (v=0;v<h;v++) {
  411. for (u=0;u<w;u++) {
  412. if (u>0) {
  413. fprintf(stderr,",");
  414. }
  415. fprintf(stderr,"%i",data[(v+y0)*w+u+x0]);
  416. }
  417. if (v<h) {
  418. fprintf(stderr,";");
  419. }
  420. }
  421. fprintf(stderr,"];\n");
  422. }
  423. }
  424. #endif
  425. for(pli=0;pli<3;pli++){
  426. if(_plmask&1<<pli){
  427. int x0;
  428. int y0;
  429. int nxblocks;
  430. int nyblocks;
  431. cfl_get_intra_dims(&info,pli,_padding,&x0,&y0,&nxblocks,&nyblocks);
  432. if(_start!=NULL){
  433. (*_start)(ctx,_argv[ai],&info,pli,nxblocks,nyblocks);
  434. }
  435. if(_funcs!=NULL){
  436. int f;
  437. for(f=0;f<_nfuncs;f++){
  438. if(_funcs[f]!=NULL){
  439. const unsigned char *data;
  440. int stride;
  441. int bj;
  442. int bi;
  443. data=ycbcr[pli].data;
  444. stride=ycbcr[pli].stride;
  445. for(bj=0;bj<nyblocks;bj++){
  446. int y;
  447. y=y0+(bj<<B_SZ_LOG-(pli!=0));
  448. for(bi=0;bi<nxblocks;bi++){
  449. int x;
  450. x=x0+(bi<<B_SZ_LOG-(pli!=0));
  451. (*_funcs[f])(ctx,&data[stride*y+x],stride,bi,bj);
  452. }
  453. }
  454. }
  455. }
  456. }
  457. if(_finish!=NULL){
  458. (*_finish)(ctx);
  459. }
  460. }
  461. }
  462. video_input_close(&vid);
  463. }
  464. return EXIT_SUCCESS;
  465. }
  466. #define PADDING (4)
  467. #if PADDING<3
  468. # error "PADDING must be at least 3 luma blocks"
  469. #endif
  470. int main(int _argc,const char *_argv[]) {
  471. cfl_stats_ctx ctx[NUM_PROCS];
  472. int i;
  473. ne_filter_params_init();
  474. for (i=0;i<OD_NBSIZES;i++) {
  475. od_scale_init(OD_SCALE[i],OD_LOG_BSIZE0+i);
  476. }
  477. for (i=0;i<NUM_PROCS;i++) {
  478. cfl_stats_ctx_init(&ctx[i]);
  479. }
  480. od_intra_init();
  481. OD_OMP_SET_THREADS(NUM_PROCS);
  482. cfl_apply_to_blocks(ctx,sizeof(*ctx),0x7,PADDING,stats_start,NBLOCKS,BLOCKS,
  483. stats_finish,_argc,_argv);
  484. for (i=1;i<NUM_PROCS;i++) {
  485. cfl_stats_ctx_combine(&ctx[0],&ctx[i]);
  486. }
  487. printf("Processed %i image(s)\n",ctx[0].n);
  488. if (ctx[0].n>0) {
  489. double *od_scale;
  490. od_scale=OD_SCALE[B_SZ_LOG-1-OD_LOG_BSIZE0];
  491. for (i=0;i<2;i++) {
  492. char label[128];
  493. sprintf(label,"Frequency-Domain Predictors (plane %i)",i+1);
  494. intra_stats_correct(&ctx[0].gb_fdp[i]);
  495. intra_stats_print(&ctx[0].gb_fdp[i],label,od_scale);
  496. sprintf(label,"Chroma-from-Luma Predictors (plane %i)",i+1);
  497. intra_stats_correct(&ctx[0].gb_cfl[i]);
  498. intra_stats_print(&ctx[0].gb_cfl[i],label,od_scale);
  499. }
  500. }
  501. for (i=0;i<NUM_PROCS;i++) {
  502. cfl_stats_ctx_clear(&ctx[i]);
  503. }
  504. od_intra_clear();
  505. return EXIT_SUCCESS;
  506. }