51
52
int16_t mv[2][4][4][2]; /* [list][y][x][mvxy] */
54
/* {{{ [fold] char *get_string(const stringlist_t *sl, int entries, int code) */
55
55
/* Return string from stringlist corresponding to the given code */
56
56
#define GET_STRING(sl, code) get_string((sl), sizeof(sl)/sizeof(*(sl)), code)
63
static char *get_string(const stringlist_t *sl, int entries, int code)
64
static char *get_string( const stringlist_t *sl, int entries, int code )
67
for (i=0; i<entries; i++) {
68
if (sl[i].code==code) break;
70
return (i>=entries) ? "?" : sl[i].string;
66
for( int i = 0; i < entries; i++ )
67
if( sl[i].code == code )
73
/* {{{ [fold] void mv(int x0, int y0, int16_t dmv[2], int ref, int zoom, char *col) */
74
72
/* Plot motion vector */
75
static void mv(int x0, int y0, int16_t dmv[2], int ref, int zoom, char *col)
73
static void mv( int x0, int y0, int16_t dmv[2], int ref, int zoom, char *col )
81
dx = (dx * zoom + 2) >> 2; /* Quarter pixel accurate MVs */
78
dx = (dx * zoom + 2) >> 2;
82
79
dy = (dy * zoom + 2) >> 2;
83
disp_line(0, x0, y0, x0+dx, y0+dy);
84
for (i=1; i<ref; i++){
85
disp_line(0, x0, y0-i, x0+i, y0);
86
disp_line(0, x0+i, y0, x0, y0+i);
87
disp_line(0, x0, y0+i, x0-i, y0);
88
disp_line(0, x0-i, y0, x0, y0-i);
80
disp_line( 0, x0, y0, x0+dx, y0+dy );
81
for( int i = 1; i < ref; i++ )
83
disp_line( 0, x0 , y0-i, x0+i, y0 );
84
disp_line( 0, x0+i, y0 , x0 , y0+i );
85
disp_line( 0, x0 , y0+i, x0-i, y0 );
86
disp_line( 0, x0-i, y0 , x0 , y0-i );
90
disp_setcolor("black");
91
disp_point(0, x0, y0);
88
disp_setcolor( "black" );
89
disp_point( 0, x0, y0 );
96
/* {{{ [fold] void x264_visualize_init( x264_t *h ) */
97
93
int x264_visualize_init( x264_t *h )
99
int mb = h->sps->i_mb_width * h->sps->i_mb_height;
100
CHECKED_MALLOC( h->visualize, mb * sizeof(visualize_t) );
95
CHECKED_MALLOC( h->visualize, h->mb.i_mb_width * h->mb.i_mb_height * sizeof(visualize_t) );
106
/* {{{ [fold] void x264_visualize_mb( x264_t *h ) */
107
101
void x264_visualize_mb( x264_t *h )
109
103
visualize_t *v = (visualize_t*)h->visualize + h->mb.i_mb_xy;
112
/* Save all data for the MB what we need for drawing the visualization */
105
/* Save all data for the MB that we need for drawing the visualization */
113
106
v->i_type = h->mb.i_type;
114
107
v->i_partition = h->mb.i_partition;
115
for (i=0; i<4; i++) v->i_sub_partition[i] = h->mb.i_sub_partition[i];
116
for (y=0; y<4; y++) for (x=0; x<4; x++)
117
v->intra4x4_pred_mode[y][x] = h->mb.cache.intra4x4_pred_mode[X264_SCAN8_0+y*8+x];
118
for (l=0; l<2; l++) for (y=0; y<4; y++) for (x=0; x<4; x++) {
119
for (i=0; i<2; i++) {
120
v->mv[l][y][x][i] = h->mb.cache.mv[l][X264_SCAN8_0+y*8+x][i];
122
v->ref[l][y][x] = h->mb.cache.ref[l][X264_SCAN8_0+y*8+x];
108
for( int i = 0; i < 4; i++ )
109
v->i_sub_partition[i] = h->mb.i_sub_partition[i];
110
for( int y = 0; y < 4; y++ )
111
for( int x = 0; x < 4; x++ )
112
v->intra4x4_pred_mode[y][x] = h->mb.cache.intra4x4_pred_mode[X264_SCAN8_0+y*8+x];
113
for( int l = 0; l < 2; l++ )
114
for( int y = 0; y < 4; y++ )
115
for( int x = 0; x < 4; x++ )
117
for( int i = 0; i < 2; i++ )
118
v->mv[l][y][x][i] = h->mb.cache.mv[l][X264_SCAN8_0+y*8+x][i];
119
v->ref[l][y][x] = h->mb.cache.ref[l][X264_SCAN8_0+y*8+x];
124
121
v->i_intra16x16_pred_mode = h->mb.i_intra16x16_pred_mode;
127
/* {{{ [fold] void x264_visualize_close( x264_t *h ) */
128
124
void x264_visualize_close( x264_t *h )
130
126
x264_free(h->visualize);
133
/* {{{ [fold] void x264_visualize_show( x264_t *h ) */
134
129
/* Display visualization (block types, MVs) of the encoded frame */
135
130
/* FIXME: B-type MBs not handled yet properly */
136
131
void x264_visualize_show( x264_t *h )
139
static const stringlist_t mb_types[] = {
133
static const stringlist_t mb_types[] =
140
135
/* Block types marked as NULL will not be drawn */
141
136
{ I_4x4 , "red" },
142
137
{ I_8x8 , "#ff5640" },
165
160
static const int zoom = 2; /* Zoom factor */
167
162
static const int pad = 32;
168
uint8_t *const frame = h->fdec->plane[0];
163
pixel *const frame = h->fdec->plane[0];
169
164
const int width = h->param.i_width;
170
165
const int height = h->param.i_height;
171
166
const int stride = h->fdec->i_stride[0];
174
disp_gray_zoom(0, frame - pad*stride - pad, width+2*pad, height+2*pad, stride, "fdec", zoom);
176
disp_gray_zoom(0, frame, width, height, stride, "fdec", zoom);
169
disp_gray_zoom( 0, frame - pad*stride - pad, width+2*pad, height+2*pad, stride, "fdec", zoom );
171
disp_gray_zoom( 0, frame, width, height, stride, "fdec", zoom );
179
for( mb_xy = 0; mb_xy < h->sps->i_mb_width * h->sps->i_mb_height; mb_xy++ )
173
for( int mb_xy = 0; mb_xy < h->mb.i_mb_width * h->mb.i_mb_height; mb_xy++ )
181
175
visualize_t *const v = (visualize_t*)h->visualize + mb_xy;
182
const int mb_y = mb_xy / h->sps->i_mb_width;
183
const int mb_x = mb_xy % h->sps->i_mb_width;
184
char *const col = GET_STRING(mb_types, v->i_type);
176
const int mb_y = mb_xy / h->mb.i_mb_width;
177
const int mb_x = mb_xy % h->mb.i_mb_width;
178
char *const col = GET_STRING( mb_types, v->i_type );
185
179
int x = mb_x*16*zoom;
186
180
int y = mb_y*16*zoom;
190
if (col==NULL) continue;
196
if (drawbox) disp_rect(0, x, y, x+16*zoom-1, y+16*zoom-1);
198
if (v->i_type==P_L0 || v->i_type==P_8x8 || v->i_type==P_SKIP) {
192
disp_setcolor( col );
193
if( drawbox ) disp_rect( 0, x, y, x+16*zoom-1, y+16*zoom-1 );
195
if( v->i_type==P_L0 || v->i_type==P_8x8 || v->i_type==P_SKIP )
200
197
/* Predicted (inter) mode, with motion vector */
201
if (v->i_partition==D_16x16 || v->i_type==P_SKIP) {
202
mv(x+8*zoom, y+8*zoom, v->mv[l][0][0], v->ref[l][0][0], zoom, col);
204
if (v->i_partition==D_16x8) {
205
if (drawbox) disp_rect(0, x, y, x+16*zoom, y+8*zoom);
206
mv(x+8*zoom, y+4*zoom, v->mv[l][0][0], v->ref[l][0][0], zoom, col);
207
if (drawbox) disp_rect(0, x, y+8*zoom, x+16*zoom, y+16*zoom);
208
mv(x+8*zoom, y+12*zoom, v->mv[l][2][0], v->ref[l][2][0], zoom, col);
210
if (v->i_partition==D_8x16) {
211
if (drawbox) disp_rect(0, x, y, x+8*zoom, y+16*zoom);
212
mv(x+4*zoom, y+8*zoom, v->mv[l][0][0], v->ref[l][0][0], zoom, col);
213
if (drawbox) disp_rect(0, x+8*zoom, y, x+16*zoom, y+16*zoom);
214
mv(x+12*zoom, y+8*zoom, v->mv[l][0][2], v->ref[l][0][2], zoom, col);
216
if (v->i_partition==D_8x8) {
217
for (i=0; i<2; i++) for (j=0; j<2; j++) {
218
int sp = v->i_sub_partition[i*2+j];
219
const int x0 = x + j*8*zoom;
220
const int y0 = y + i*8*zoom;
221
l = x264_mb_partition_listX_table[0][sp] ? 0 : 1; /* FIXME: not tested if this works */
223
if (drawbox) disp_rect(0, x0, y0, x0+8*zoom, y0+8*zoom);
224
mv(x0+4*zoom, y0+4*zoom, v->mv[l][2*i][2*j], v->ref[l][2*i][2*j], zoom, col);
227
if (drawbox) disp_rect(0, x0, y0, x0+8*zoom, y0+4*zoom);
228
if (drawbox) disp_rect(0, x0, y0+4*zoom, x0+8*zoom, y0+8*zoom);
229
mv(x0+4*zoom, y0+2*zoom, v->mv[l][2*i][2*j], v->ref[l][2*i][2*j], zoom, col);
230
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);
233
if (drawbox) disp_rect(0, x0, y0, x0+4*zoom, y0+8*zoom);
234
if (drawbox) disp_rect(0, x0+4*zoom, y0, x0+8*zoom, y0+8*zoom);
235
mv(x0+2*zoom, y0+4*zoom, v->mv[l][2*i][2*j], v->ref[l][2*i][2*j], zoom, col);
236
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);
239
if (drawbox) disp_rect(0, x0, y0, x0+4*zoom, y0+4*zoom);
240
if (drawbox) disp_rect(0, x0+4*zoom, y0, x0+8*zoom, y0+4*zoom);
241
if (drawbox) disp_rect(0, x0, y0+4*zoom, x0+4*zoom, y0+8*zoom);
242
if (drawbox) disp_rect(0, x0+4*zoom, y0+4*zoom, x0+8*zoom, y0+8*zoom);
243
mv(x0+2*zoom, y0+2*zoom, v->mv[l][2*i][2*j], v->ref[l][2*i][2*j], zoom, col);
244
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);
245
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);
246
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);
198
if( v->i_partition == D_16x16 || v->i_type == P_SKIP )
199
mv( x+8*zoom, y+8*zoom, v->mv[l][0][0], v->ref[l][0][0], zoom, col );
200
else if (v->i_partition == D_16x8)
202
if( drawbox ) disp_rect( 0, x, y, x+16*zoom, y+8*zoom );
203
mv( x+8*zoom, y+4*zoom, v->mv[l][0][0], v->ref[l][0][0], zoom, col );
204
if( drawbox ) disp_rect( 0, x, y+8*zoom, x+16*zoom, y+16*zoom );
205
mv( x+8*zoom, y+12*zoom, v->mv[l][2][0], v->ref[l][2][0], zoom, col );
207
else if( v->i_partition==D_8x16 )
209
if( drawbox ) disp_rect( 0, x, y, x+8*zoom, y+16*zoom );
210
mv( x+4*zoom, y+8*zoom, v->mv[l][0][0], v->ref[l][0][0], zoom, col );
211
if( drawbox ) disp_rect( 0, x+8*zoom, y, x+16*zoom, y+16*zoom );
212
mv( x+12*zoom, y+8*zoom, v->mv[l][0][2], v->ref[l][0][2], zoom, col );
214
else if( v->i_partition==D_8x8 )
216
for( int i = 0; i < 2; i++ )
217
for( int j = 0; j < 2; j++ )
219
int sp = v->i_sub_partition[i*2+j];
220
const int x0 = x + j*8*zoom;
221
const int y0 = y + i*8*zoom;
222
l = x264_mb_partition_listX_table[0][sp] ? 0 : 1; /* FIXME: not tested if this works */
225
if( drawbox ) disp_rect( 0, x0, y0, x0+8*zoom, y0+8*zoom );
226
mv( x0+4*zoom, y0+4*zoom, v->mv[l][2*i][2*j], v->ref[l][2*i][2*j], zoom, col );
228
else if( IS_SUB8x4(sp) )
230
if( drawbox ) disp_rect( 0, x0, y0, x0+8*zoom, y0+4*zoom );
231
if( drawbox ) disp_rect( 0, x0, y0+4*zoom, x0+8*zoom, y0+8*zoom );
232
mv( x0+4*zoom, y0+2*zoom, v->mv[l][2*i][2*j], v->ref[l][2*i][2*j], zoom, col );
233
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 );
235
else if( IS_SUB4x8(sp) )
237
if( drawbox ) disp_rect( 0, x0, y0, x0+4*zoom, y0+8*zoom );
238
if( drawbox ) disp_rect( 0, x0+4*zoom, y0, x0+8*zoom, y0+8*zoom );
239
mv( x0+2*zoom, y0+4*zoom, v->mv[l][2*i][2*j], v->ref[l][2*i][2*j], zoom, col );
240
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 );
242
else if( IS_SUB4x4(sp) )
244
if( drawbox ) disp_rect( 0, x0, y0, x0+4*zoom, y0+4*zoom );
245
if( drawbox ) disp_rect( 0, x0+4*zoom, y0, x0+8*zoom, y0+4*zoom );
246
if( drawbox ) disp_rect( 0, x0, y0+4*zoom, x0+4*zoom, y0+8*zoom );
247
if( drawbox ) disp_rect( 0, x0+4*zoom, y0+4*zoom, x0+8*zoom, y0+8*zoom );
248
mv( x0+2*zoom, y0+2*zoom, v->mv[l][2*i][2*j], v->ref[l][2*i][2*j], zoom, col );
249
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 );
250
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 );
251
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 );
252
if (IS_INTRA(v->i_type) || v->i_type==I_PCM) {
257
if( IS_INTRA(v->i_type) || v->i_type == I_PCM )
253
259
/* Intra coded */
254
if (v->i_type==I_16x16) {
260
if( v->i_type == I_16x16 )
255
262
switch (v->i_intra16x16_pred_mode) {
256
263
case I_PRED_16x16_V:
257
disp_line(0, x+2*zoom, y+2*zoom, x+14*zoom, y+2*zoom);
264
disp_line( 0, x+2*zoom, y+2*zoom, x+14*zoom, y+2*zoom );
259
266
case I_PRED_16x16_H:
260
disp_line(0, x+2*zoom, y+2*zoom, x+2*zoom, y+14*zoom);
267
disp_line( 0, x+2*zoom, y+2*zoom, x+2*zoom, y+14*zoom );
262
269
case I_PRED_16x16_DC:
263
270
case I_PRED_16x16_DC_LEFT:
264
271
case I_PRED_16x16_DC_TOP:
265
272
case I_PRED_16x16_DC_128:
266
disp_line(0, x+2*zoom, y+2*zoom, x+14*zoom, y+2*zoom);
267
disp_line(0, x+2*zoom, y+2*zoom, x+2*zoom, y+14*zoom);
273
disp_line( 0, x+2*zoom, y+2*zoom, x+14*zoom, y+2*zoom );
274
disp_line( 0, x+2*zoom, y+2*zoom, x+2*zoom, y+14*zoom );
269
276
case I_PRED_16x16_P:
270
disp_line(0, x+2*zoom, y+2*zoom, x+8*zoom, y+8*zoom);
277
disp_line( 0, x+2*zoom, y+2*zoom, x+8*zoom, y+8*zoom );
274
if (v->i_type==I_4x4 || v->i_type==I_8x8) {
275
const int di = v->i_type==I_8x8 ? 2 : 1;
281
if( v->i_type==I_4x4 || v->i_type==I_8x8 )
283
const int di = v->i_type == I_8x8 ? 2 : 1;
276
284
const int zoom2 = zoom * di;
277
for (i=0; i<4; i+=di) for (j=0; j<4; j+=di) {
278
const int x0 = x + j*4*zoom;
279
const int y0 = y + i*4*zoom;
280
if (drawbox) disp_rect(0, x0, y0, x0+4*zoom2, y0+4*zoom2);
281
switch (v->intra4x4_pred_mode[i][j]) {
282
case I_PRED_4x4_V: /* Vertical */
283
disp_line(0, x0+0*zoom2, y0+1*zoom2, x0+4*zoom2, y0+1*zoom2);
285
case I_PRED_4x4_H: /* Horizontal */
286
disp_line(0, x0+1*zoom2, y0+0*zoom2, x0+1*zoom2, y0+4*zoom2);
288
case I_PRED_4x4_DC: /* DC, average from top and left sides */
289
case I_PRED_4x4_DC_LEFT:
290
case I_PRED_4x4_DC_TOP:
291
case I_PRED_4x4_DC_128:
292
disp_line(0, x0+1*zoom2, y0+1*zoom2, x0+4*zoom2, y0+1*zoom2);
293
disp_line(0, x0+1*zoom2, y0+1*zoom2, x0+1*zoom2, y0+4*zoom2);
295
case I_PRED_4x4_DDL: /* Topright-bottomleft */
296
disp_line(0, x0+0*zoom2, y0+0*zoom2, x0+4*zoom2, y0+4*zoom2);
298
case I_PRED_4x4_DDR: /* Topleft-bottomright */
299
disp_line(0, x0+0*zoom2, y0+4*zoom2, x0+4*zoom2, y0+0*zoom2);
301
case I_PRED_4x4_VR: /* Mix of topleft-bottomright and vertical */
302
disp_line(0, x0+0*zoom2, y0+2*zoom2, x0+4*zoom2, y0+1*zoom2);
304
case I_PRED_4x4_HD: /* Mix of topleft-bottomright and horizontal */
305
disp_line(0, x0+2*zoom2, y0+0*zoom2, x0+1*zoom2, y0+4*zoom2);
307
case I_PRED_4x4_VL: /* Mix of topright-bottomleft and vertical */
308
disp_line(0, x0+0*zoom2, y0+1*zoom2, x0+4*zoom2, y0+2*zoom2);
310
case I_PRED_4x4_HU: /* Mix of topright-bottomleft and horizontal */
311
disp_line(0, x0+1*zoom2, y0+0*zoom2, x0+2*zoom2, y0+4*zoom2);
285
for( int i = 0; i < 4; i += di )
286
for( int j = 0; j < 4; j += di )
288
const int x0 = x + j*4*zoom;
289
const int y0 = y + i*4*zoom;
290
if( drawbox ) disp_rect( 0, x0, y0, x0+4*zoom2, y0+4*zoom2 );
291
switch( v->intra4x4_pred_mode[i][j] )
293
case I_PRED_4x4_V: /* Vertical */
294
disp_line( 0, x0+0*zoom2, y0+1*zoom2, x0+4*zoom2, y0+1*zoom2 );
296
case I_PRED_4x4_H: /* Horizontal */
297
disp_line( 0, x0+1*zoom2, y0+0*zoom2, x0+1*zoom2, y0+4*zoom2 );
299
case I_PRED_4x4_DC: /* DC, average from top and left sides */
300
case I_PRED_4x4_DC_LEFT:
301
case I_PRED_4x4_DC_TOP:
302
case I_PRED_4x4_DC_128:
303
disp_line( 0, x0+1*zoom2, y0+1*zoom2, x0+4*zoom2, y0+1*zoom2 );
304
disp_line( 0, x0+1*zoom2, y0+1*zoom2, x0+1*zoom2, y0+4*zoom2 );
306
case I_PRED_4x4_DDL: /* Topright-bottomleft */
307
disp_line( 0, x0+0*zoom2, y0+0*zoom2, x0+4*zoom2, y0+4*zoom2 );
309
case I_PRED_4x4_DDR: /* Topleft-bottomright */
310
disp_line( 0, x0+0*zoom2, y0+4*zoom2, x0+4*zoom2, y0+0*zoom2 );
312
case I_PRED_4x4_VR: /* Mix of topleft-bottomright and vertical */
313
disp_line( 0, x0+0*zoom2, y0+2*zoom2, x0+4*zoom2, y0+1*zoom2 );
315
case I_PRED_4x4_HD: /* Mix of topleft-bottomright and horizontal */
316
disp_line( 0, x0+2*zoom2, y0+0*zoom2, x0+1*zoom2, y0+4*zoom2 );
318
case I_PRED_4x4_VL: /* Mix of topright-bottomleft and vertical */
319
disp_line( 0, x0+0*zoom2, y0+1*zoom2, x0+4*zoom2, y0+2*zoom2 );
321
case I_PRED_4x4_HU: /* Mix of topright-bottomleft and horizontal */
322
disp_line( 0, x0+1*zoom2, y0+0*zoom2, x0+2*zoom2, y0+4*zoom2 );
320
if (waitkey) getchar();