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

Audio

开发平台:

Visual C++

  1. /*****************************************************************************
  2.  * x264: h264 encoder
  3.  *****************************************************************************
  4.  * Copyright (C) 2005 x264 project
  5.  *
  6.  * Author: Tuukka Toivonen <tuukkat@ee.oulu.fi>
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  21.  *****************************************************************************/
  22. /*
  23.  * Some explanation of the symbols used:
  24.  * Red/pink: intra block
  25.  * Blue: inter block
  26.  * Green: skip block
  27.  * Yellow: B-block (not visualized properly yet)
  28.  *
  29.  * Motion vectors have black dot at their target (ie. at the MB center),
  30.  * instead of arrowhead. The black dot is enclosed in filled diamond with radius
  31.  * depending on reference frame number (one frame back = zero width, normal case).
  32.  *
  33.  * The intra blocks have generally lines drawn perpendicular
  34.  * to the prediction direction, so for example, if there is a pink block
  35.  * with horizontal line at the top of it, it is interpolated by assuming
  36.  * luma to be vertically constant.
  37.  * DC predicted blocks have both horizontal and vertical lines,
  38.  * pink blocks with a diagonal line are predicted using the planar function.
  39.  */
  40. #ifdef HAVE_STDINT_H
  41. #include <stdint.h>
  42. #else
  43. #include <inttypes.h>
  44. #endif
  45. #include <stddef.h>                 /* NULL */
  46. #include <stdio.h>                  /* getchar */
  47. #include "common.h"
  48. #include "visualize.h"
  49. #include "display.h"
  50. typedef struct {
  51.     int     i_type;
  52.     int     i_partition;
  53.     int     i_sub_partition[4];
  54.     int     i_intra16x16_pred_mode;
  55.     int     intra4x4_pred_mode[4][4];
  56.     int8_t  ref[2][4][4];                  /* [list][y][x] */
  57.     int16_t mv[2][4][4][2];                /* [list][y][x][mvxy] */
  58. } visualize_t;
  59. /* {{{ [fold] char *get_string(const stringlist_t *sl, int entries, int code) */
  60. /* Return string from stringlist corresponding to the given code */
  61. #define GET_STRING(sl, code) get_string((sl), sizeof(sl)/sizeof(*(sl)), code)
  62. typedef struct {
  63.     int code;
  64.     char *string;
  65. } stringlist_t;
  66. static char *get_string(const stringlist_t *sl, int entries, int code)
  67. {
  68.     int i;
  69.     for (i=0; i<entries; i++) {
  70.         if (sl[i].code==code) break;
  71.     }
  72.     return (i>=entries) ? "?" : sl[i].string;
  73. }
  74. /* }}} */
  75. /* {{{ [fold] void mv(int x0, int y0, int16_t dmv[2], int ref, int zoom, char *col) */
  76. /* Plot motion vector */
  77. static void mv(int x0, int y0, int16_t dmv[2], int ref, int zoom, char *col)
  78. {
  79.     int dx = dmv[0];
  80.     int dy = dmv[1];
  81.     int i;
  82.     dx = (dx * zoom + 2) >> 2;                     /* Quarter pixel accurate MVs */
  83.     dy = (dy * zoom + 2) >> 2;
  84.     disp_line(0, x0, y0, x0+dx, y0+dy);
  85.     for (i=1; i<ref; i++){
  86.         disp_line(0, x0, y0-i, x0+i, y0);
  87.         disp_line(0, x0+i, y0, x0, y0+i);
  88.         disp_line(0, x0, y0+i, x0-i, y0);
  89.         disp_line(0, x0-i, y0, x0, y0-i);
  90.     }
  91.     disp_setcolor("black");
  92.     disp_point(0, x0, y0);
  93.     disp_setcolor(col);
  94. }
  95. /* }}} */
  96. /* {{{ [fold] void x264_visualize_init( x264_t *h ) */
  97. void x264_visualize_init( x264_t *h )
  98. {
  99.     int mb = h->sps->i_mb_width * h->sps->i_mb_height;
  100.     h->visualize = x264_malloc(mb * sizeof(visualize_t));
  101. }
  102. /* }}} */
  103. /* {{{ [fold] void x264_visualize_mb( x264_t *h ) */
  104. void x264_visualize_mb( x264_t *h )
  105. {
  106.     visualize_t *v = (visualize_t*)h->visualize + h->mb.i_mb_xy;
  107.     int i, l, x, y;
  108.     /* Save all data for the MB what we need for drawing the visualization */
  109.     v->i_type = h->mb.i_type;
  110.     v->i_partition = h->mb.i_partition;
  111.     for (i=0; i<4; i++) v->i_sub_partition[i] = h->mb.i_sub_partition[i];
  112.     for (y=0; y<4; y++) for (x=0; x<4; x++)
  113.         v->intra4x4_pred_mode[y][x] = h->mb.cache.intra4x4_pred_mode[X264_SCAN8_0+y*8+x];
  114.     for (l=0; l<2; l++) for (y=0; y<4; y++) for (x=0; x<4; x++) {
  115.         for (i=0; i<2; i++) {
  116.             v->mv[l][y][x][i] = h->mb.cache.mv[l][X264_SCAN8_0+y*8+x][i];
  117.         }
  118.         v->ref[l][y][x] = h->mb.cache.ref[l][X264_SCAN8_0+y*8+x];
  119.     }
  120.     v->i_intra16x16_pred_mode = h->mb.i_intra16x16_pred_mode;
  121. }
  122. /* }}} */
  123. /* {{{ [fold] void x264_visualize_close( x264_t *h ) */
  124. void x264_visualize_close( x264_t *h )
  125. {
  126.     x264_free(h->visualize);
  127. }
  128. /* }}} */
  129. /* {{{ [fold] void x264_visualize_show( x264_t *h ) */
  130. /* Display visualization (block types, MVs) of the encoded frame */
  131. /* FIXME: B-type MBs not handled yet properly */
  132. void x264_visualize_show( x264_t *h )
  133. {
  134.     int mb_xy;
  135.     static const stringlist_t mb_types[] = {
  136.         /* Block types marked as NULL will not be drawn */
  137.         { I_4x4   , "red" },
  138.         { I_8x8   , "#ff5640" },
  139.         { I_16x16 , "#ff8060" },
  140.         { I_PCM   , "violet" },
  141.         { P_L0    , "SlateBlue" },
  142.         { P_8x8   , "blue" },
  143.         { P_SKIP  , "green" },
  144.         { B_DIRECT, "yellow" },
  145.         { B_L0_L0 , "yellow" },
  146.         { B_L0_L1 , "yellow" },
  147.         { B_L0_BI , "yellow" },
  148.         { B_L1_L0 , "yellow" },
  149.         { B_L1_L1 , "yellow" },
  150.         { B_L1_BI , "yellow" },
  151.         { B_BI_L0 , "yellow" },
  152.         { B_BI_L1 , "yellow" },
  153.         { B_BI_BI , "yellow" },
  154.         { B_8x8   , "yellow" },
  155.         { B_SKIP  , "yellow" },
  156.     };
  157.     static const int waitkey = 1;     /* Wait for enter after each frame */
  158.     static const int drawbox = 1;     /* Draw box around each block */
  159.     static const int borders = 0;     /* Display extrapolated borders outside frame */
  160.     static const int zoom = 2;        /* Zoom factor */
  161.     static const int pad = 32;
  162.     uint8_t *const frame = h->fdec->plane[0];
  163.     const int width = h->param.i_width;
  164.     const int height = h->param.i_height;
  165.     const int stride = h->fdec->i_stride[0];
  166.     if (borders) {
  167.         disp_gray_zoom(0, frame - pad*stride - pad, width+2*pad, height+2*pad, stride, "fdec", zoom);
  168.     } else {
  169.         disp_gray_zoom(0, frame, width, height, stride, "fdec", zoom);
  170.     }
  171.     for( mb_xy = 0; mb_xy < h->sps->i_mb_width * h->sps->i_mb_height; mb_xy++ )
  172.     {
  173.         visualize_t *const v = (visualize_t*)h->visualize + mb_xy;
  174.         const int mb_y = mb_xy / h->sps->i_mb_width;
  175.         const int mb_x = mb_xy % h->sps->i_mb_width;
  176.         char *const col = GET_STRING(mb_types, v->i_type);
  177.         int x = mb_x*16*zoom;
  178.         int y = mb_y*16*zoom;
  179.         int l = 0;
  180.         unsigned int i, j;
  181.         if (col==NULL) continue;
  182.         if (borders) {
  183.             x += pad*zoom;
  184.             y += pad*zoom;
  185.         }
  186.         disp_setcolor(col);
  187.         if (drawbox) disp_rect(0, x, y, x+16*zoom-1, y+16*zoom-1);
  188.         if (v->i_type==P_L0 || v->i_type==P_8x8 || v->i_type==P_SKIP) {
  189.             /* Predicted (inter) mode, with motion vector */
  190.             if (v->i_partition==D_16x16 || v->i_type==P_SKIP) {
  191.                 mv(x+8*zoom, y+8*zoom, v->mv[l][0][0], v->ref[l][0][0], zoom, col);
  192.             }
  193.             if (v->i_partition==D_16x8) {
  194.                 if (drawbox) disp_rect(0, x, y, x+16*zoom, y+8*zoom);
  195.                 mv(x+8*zoom, y+4*zoom, v->mv[l][0][0], v->ref[l][0][0], zoom, col);
  196.                 if (drawbox) disp_rect(0, x, y+8*zoom, x+16*zoom, y+16*zoom);
  197.                 mv(x+8*zoom, y+12*zoom, v->mv[l][2][0], v->ref[l][2][0], zoom, col);
  198.             }
  199.             if (v->i_partition==D_8x16) {
  200.                 if (drawbox) disp_rect(0, x,          y, x+8*zoom,  y+16*zoom);
  201.                 mv(x+4*zoom, y+8*zoom, v->mv[l][0][0], v->ref[l][0][0], zoom, col);
  202.                 if (drawbox) disp_rect(0, x+8*zoom,   y, x+16*zoom, y+16*zoom);
  203.                 mv(x+12*zoom, y+8*zoom, v->mv[l][0][2], v->ref[l][0][2], zoom, col);
  204.             }
  205.             if (v->i_partition==D_8x8) {
  206.                 for (i=0; i<2; i++) for (j=0; j<2; j++) {
  207.                     int sp = v->i_sub_partition[i*2+j];
  208.                     const int x0 = x + j*8*zoom;
  209.                     const int y0 = y + i*8*zoom;
  210.                     l = x264_mb_partition_listX_table[0][sp] ? 0 : 1; /* FIXME: not tested if this works */
  211.                     if (IS_SUB8x8(sp)) {
  212.                         if (drawbox) disp_rect(0, x0, y0, x0+8*zoom, y0+8*zoom);
  213.                         mv(x0+4*zoom, y0+4*zoom, v->mv[l][2*i][2*j], v->ref[l][2*i][2*j], zoom, col);
  214.                     }
  215.                     if (IS_SUB8x4(sp)) {
  216.                         if (drawbox) disp_rect(0, x0, y0, x0+8*zoom, y0+4*zoom);
  217.                         if (drawbox) disp_rect(0, x0, y0+4*zoom, x0+8*zoom, y0+8*zoom);
  218.                         mv(x0+4*zoom, y0+2*zoom, v->mv[l][2*i][2*j], v->ref[l][2*i][2*j], zoom, col);
  219.                         mv(x0+4*zoom, y0+6*zoom, v->mv[l][2*i+1][2*j], v->ref[l][2*i+1][2*j], zoom, col);
  220.                     }
  221.                     if (IS_SUB4x8(sp)) {
  222.                         if (drawbox) disp_rect(0, x0, y0, x0+4*zoom, y0+8*zoom);
  223.                         if (drawbox) disp_rect(0, x0+4*zoom, y0, x0+8*zoom, y0+8*zoom);
  224.                         mv(x0+2*zoom, y0+4*zoom, v->mv[l][2*i][2*j], v->ref[l][2*i][2*j], zoom, col);
  225.                         mv(x0+6*zoom, y0+4*zoom, v->mv[l][2*i][2*j+1], v->ref[l][2*i][2*j+1], zoom, col);
  226.                     }
  227.                     if (IS_SUB4x4(sp)) {
  228.                         if (drawbox) disp_rect(0, x0, y0, x0+4*zoom, y0+4*zoom);
  229.                         if (drawbox) disp_rect(0, x0+4*zoom, y0, x0+8*zoom, y0+4*zoom);
  230.                         if (drawbox) disp_rect(0, x0, y0+4*zoom, x0+4*zoom, y0+8*zoom);
  231.                         if (drawbox) disp_rect(0, x0+4*zoom, y0+4*zoom, x0+8*zoom, y0+8*zoom);
  232.                         mv(x0+2*zoom, y0+2*zoom, v->mv[l][2*i][2*j], v->ref[l][2*i][2*j], zoom, col);
  233.                         mv(x0+6*zoom, y0+2*zoom, v->mv[l][2*i][2*j+1], v->ref[l][2*i][2*j+1], zoom, col);
  234.                         mv(x0+2*zoom, y0+6*zoom, v->mv[l][2*i+1][2*j], v->ref[l][2*i+1][2*j], zoom, col);
  235.                         mv(x0+6*zoom, y0+6*zoom, v->mv[l][2*i+1][2*j+1], v->ref[l][2*i+1][2*j+1], zoom, col);
  236.                     }
  237.                 }
  238.             }
  239.         }
  240.         if (IS_INTRA(v->i_type) || v->i_type==I_PCM) {
  241.             /* Intra coded */
  242.             if (v->i_type==I_16x16) {
  243.                 switch (v->i_intra16x16_pred_mode) {
  244.                 case I_PRED_16x16_V:
  245.                     disp_line(0, x+2*zoom, y+2*zoom, x+14*zoom, y+2*zoom);
  246.                     break;
  247.                 case I_PRED_16x16_H:
  248.                     disp_line(0, x+2*zoom, y+2*zoom, x+2*zoom, y+14*zoom);
  249.                     break;
  250.                 case I_PRED_16x16_DC:
  251.                 case I_PRED_16x16_DC_LEFT:
  252.                 case I_PRED_16x16_DC_TOP:
  253.                 case I_PRED_16x16_DC_128:
  254.                     disp_line(0, x+2*zoom, y+2*zoom, x+14*zoom, y+2*zoom);
  255.                     disp_line(0, x+2*zoom, y+2*zoom, x+2*zoom, y+14*zoom);
  256.                     break;
  257.                 case I_PRED_16x16_P:
  258.                     disp_line(0, x+2*zoom, y+2*zoom, x+8*zoom, y+8*zoom);
  259.                     break;
  260.                 }
  261.             }
  262.             if (v->i_type==I_4x4 || v->i_type==I_8x8) {
  263.                 const int di = v->i_type==I_8x8 ? 2 : 1;
  264.                 const int zoom2 = zoom * di;
  265.                 for (i=0; i<4; i+=di) for (j=0; j<4; j+=di) {
  266.                     const int x0 = x + j*4*zoom;
  267.                     const int y0 = y + i*4*zoom;
  268.                     if (drawbox) disp_rect(0, x0, y0, x0+4*zoom2, y0+4*zoom2);
  269.                     switch (v->intra4x4_pred_mode[i][j]) {
  270.                     case I_PRED_4x4_V: /* Vertical */
  271.                         disp_line(0, x0+0*zoom2, y0+1*zoom2, x0+4*zoom2, y0+1*zoom2);
  272.                         break;
  273.                     case I_PRED_4x4_H: /* Horizontal */
  274.                         disp_line(0, x0+1*zoom2, y0+0*zoom2, x0+1*zoom2, y0+4*zoom2);
  275.                         break;
  276.                     case I_PRED_4x4_DC: /* DC, average from top and left sides */
  277.                     case I_PRED_4x4_DC_LEFT:
  278.                     case I_PRED_4x4_DC_TOP:
  279.                     case I_PRED_4x4_DC_128:
  280.                         disp_line(0, x0+1*zoom2, y0+1*zoom2, x0+4*zoom2, y0+1*zoom2);
  281.                         disp_line(0, x0+1*zoom2, y0+1*zoom2, x0+1*zoom2, y0+4*zoom2);
  282.                         break;
  283.                     case I_PRED_4x4_DDL: /* Topright-bottomleft */
  284.                         disp_line(0, x0+0*zoom2, y0+0*zoom2, x0+4*zoom2, y0+4*zoom2);
  285.                         break;
  286.                     case I_PRED_4x4_DDR: /* Topleft-bottomright */
  287.                         disp_line(0, x0+0*zoom2, y0+4*zoom2, x0+4*zoom2, y0+0*zoom2);
  288.                         break;
  289.                     case I_PRED_4x4_VR: /* Mix of topleft-bottomright and vertical */
  290.                         disp_line(0, x0+0*zoom2, y0+2*zoom2, x0+4*zoom2, y0+1*zoom2);
  291.                         break;
  292.                     case I_PRED_4x4_HD: /* Mix of topleft-bottomright and horizontal */
  293.                         disp_line(0, x0+2*zoom2, y0+0*zoom2, x0+1*zoom2, y0+4*zoom2);
  294.                         break;
  295.                     case I_PRED_4x4_VL: /* Mix of topright-bottomleft and vertical */
  296.                         disp_line(0, x0+0*zoom2, y0+1*zoom2, x0+4*zoom2, y0+2*zoom2);
  297.                         break;
  298.                     case I_PRED_4x4_HU: /* Mix of topright-bottomleft and horizontal */
  299.                         disp_line(0, x0+1*zoom2, y0+0*zoom2, x0+2*zoom2, y0+4*zoom2);
  300.                         break;
  301.                     }
  302.                 }
  303.             }
  304.         }
  305.     }
  306.     disp_sync();
  307.     if (waitkey) getchar();
  308. }
  309. /* }}} */
  310. //EOF