2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
15 #include "./vpx_config.h"
16 #include "./vpx_scale_rtcd.h"
17 #include "./vp9_rtcd.h"
19 #include "vpx_scale/vpx_scale.h"
20 #include "vpx_scale/yv12config.h"
22 #include "vp9/common/vp9_onyxc_int.h"
23 #include "vp9/common/vp9_postproc.h"
24 #include "vp9/common/vp9_systemdependent.h"
25 #include "vp9/common/vp9_textblit.h"
27 #define RGB_TO_YUV(t) \
28 ( (0.257*(float)(t >> 16)) + (0.504*(float)(t >> 8 & 0xff)) + \
29 (0.098*(float)(t & 0xff)) + 16), \
30 (-(0.148*(float)(t >> 16)) - (0.291*(float)(t >> 8 & 0xff)) + \
31 (0.439*(float)(t & 0xff)) + 128), \
32 ( (0.439*(float)(t >> 16)) - (0.368*(float)(t >> 8 & 0xff)) - \
33 (0.071*(float)(t & 0xff)) + 128)
35 /* global constants */
36 #if 0 && CONFIG_POSTPROC_VISUALIZER
37 static const unsigned char MB_PREDICTION_MODE_colors[MB_MODE_COUNT][3] = {
38 { RGB_TO_YUV(0x98FB98) }, /* PaleGreen */
39 { RGB_TO_YUV(0x00FF00) }, /* Green */
40 { RGB_TO_YUV(0xADFF2F) }, /* GreenYellow */
41 { RGB_TO_YUV(0x8F0000) }, /* Dark Red */
42 { RGB_TO_YUV(0x008F8F) }, /* Dark Cyan */
43 { RGB_TO_YUV(0x008F8F) }, /* Dark Cyan */
44 { RGB_TO_YUV(0x008F8F) }, /* Dark Cyan */
45 { RGB_TO_YUV(0x8F0000) }, /* Dark Red */
46 { RGB_TO_YUV(0x8F0000) }, /* Dark Red */
47 { RGB_TO_YUV(0x228B22) }, /* ForestGreen */
48 { RGB_TO_YUV(0x006400) }, /* DarkGreen */
49 { RGB_TO_YUV(0x98F5FF) }, /* Cadet Blue */
50 { RGB_TO_YUV(0x6CA6CD) }, /* Sky Blue */
51 { RGB_TO_YUV(0x00008B) }, /* Dark blue */
52 { RGB_TO_YUV(0x551A8B) }, /* Purple */
53 { RGB_TO_YUV(0xFF0000) } /* Red */
54 { RGB_TO_YUV(0xCC33FF) }, /* Magenta */
57 static const unsigned char B_PREDICTION_MODE_colors[INTRA_MODES][3] = {
58 { RGB_TO_YUV(0x6633ff) }, /* Purple */
59 { RGB_TO_YUV(0xcc33ff) }, /* Magenta */
60 { RGB_TO_YUV(0xff33cc) }, /* Pink */
61 { RGB_TO_YUV(0xff3366) }, /* Coral */
62 { RGB_TO_YUV(0x3366ff) }, /* Blue */
63 { RGB_TO_YUV(0xed00f5) }, /* Dark Blue */
64 { RGB_TO_YUV(0x2e00b8) }, /* Dark Purple */
65 { RGB_TO_YUV(0xff6633) }, /* Orange */
66 { RGB_TO_YUV(0x33ccff) }, /* Light Blue */
67 { RGB_TO_YUV(0x8ab800) }, /* Green */
68 { RGB_TO_YUV(0xffcc33) }, /* Light Orange */
69 { RGB_TO_YUV(0x33ffcc) }, /* Aqua */
70 { RGB_TO_YUV(0x66ff33) }, /* Light Green */
71 { RGB_TO_YUV(0xccff33) }, /* Yellow */
74 static const unsigned char MV_REFERENCE_FRAME_colors[MAX_REF_FRAMES][3] = {
75 { RGB_TO_YUV(0x00ff00) }, /* Blue */
76 { RGB_TO_YUV(0x0000ff) }, /* Green */
77 { RGB_TO_YUV(0xffff00) }, /* Yellow */
78 { RGB_TO_YUV(0xff0000) }, /* Red */
82 static const short kernel5[] = {
86 const short vp9_rv[] = {
87 8, 5, 2, 2, 8, 12, 4, 9, 8, 3,
88 0, 3, 9, 0, 0, 0, 8, 3, 14, 4,
89 10, 1, 11, 14, 1, 14, 9, 6, 12, 11,
90 8, 6, 10, 0, 0, 8, 9, 0, 3, 14,
91 8, 11, 13, 4, 2, 9, 0, 3, 9, 6,
92 1, 2, 3, 14, 13, 1, 8, 2, 9, 7,
93 3, 3, 1, 13, 13, 6, 6, 5, 2, 7,
94 11, 9, 11, 8, 7, 3, 2, 0, 13, 13,
95 14, 4, 12, 5, 12, 10, 8, 10, 13, 10,
96 4, 14, 4, 10, 0, 8, 11, 1, 13, 7,
97 7, 14, 6, 14, 13, 2, 13, 5, 4, 4,
98 0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
99 8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
100 3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
101 3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
102 13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
103 5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
104 9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
105 4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
106 3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
107 11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
108 5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
109 0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
110 10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
111 4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
112 0, 10, 0, 5, 13, 2, 12, 7, 11, 13,
113 8, 0, 4, 10, 7, 2, 7, 2, 2, 5,
114 3, 4, 7, 3, 3, 14, 14, 5, 9, 13,
115 3, 14, 3, 6, 3, 0, 11, 8, 13, 1,
116 13, 1, 12, 0, 10, 9, 7, 6, 2, 8,
117 5, 2, 13, 7, 1, 13, 14, 7, 6, 7,
118 9, 6, 10, 11, 7, 8, 7, 5, 14, 8,
119 4, 4, 0, 8, 7, 10, 0, 8, 14, 11,
120 3, 12, 5, 7, 14, 3, 14, 5, 2, 6,
121 11, 12, 12, 8, 0, 11, 13, 1, 2, 0,
122 5, 10, 14, 7, 8, 0, 4, 11, 0, 8,
123 0, 3, 10, 5, 8, 0, 11, 6, 7, 8,
124 10, 7, 13, 9, 2, 5, 1, 5, 10, 2,
125 4, 3, 5, 6, 10, 8, 9, 4, 11, 14,
126 3, 8, 3, 7, 8, 5, 11, 4, 12, 3,
127 11, 9, 14, 8, 14, 13, 4, 3, 1, 2,
128 14, 6, 5, 4, 4, 11, 4, 6, 2, 1,
129 5, 8, 8, 12, 13, 5, 14, 10, 12, 13,
130 0, 9, 5, 5, 11, 10, 13, 9, 10, 13,
133 void vp9_post_proc_down_and_across_c(const uint8_t *src_ptr,
135 int src_pixels_per_line,
136 int dst_pixels_per_line,
140 uint8_t const *p_src;
146 int pitch = src_pixels_per_line;
148 (void)dst_pixels_per_line;
150 for (row = 0; row < rows; row++) {
151 /* post_proc_down for one row */
155 for (col = 0; col < cols; col++) {
159 for (i = -2; i <= 2; i++) {
160 if (abs(v - p_src[col + i * pitch]) > flimit)
161 goto down_skip_convolve;
163 kernel += kernel5[2 + i] * p_src[col + i * pitch];
171 /* now post_proc_across */
175 for (i = 0; i < 8; i++)
178 for (col = 0; col < cols; col++) {
184 for (i = -2; i <= 2; i++) {
185 if (abs(v - p_src[col + i]) > flimit)
186 goto across_skip_convolve;
188 kernel += kernel5[2 + i] * p_src[col + i];
191 d[col & 7] = (kernel >> 3);
192 across_skip_convolve:
195 p_dst[col - 2] = d[(col - 2) & 7];
198 /* handle the last two pixels */
199 p_dst[col - 2] = d[(col - 2) & 7];
200 p_dst[col - 1] = d[(col - 1) & 7];
209 static int q2mbl(int x) {
212 x = 50 + (x - 50) * 10 / 8;
216 void vp9_mbpost_proc_across_ip_c(uint8_t *src, int pitch,
217 int rows, int cols, int flimit) {
224 for (r = 0; r < rows; r++) {
228 for (i = -8; i <= 6; i++) {
229 sumsq += s[i] * s[i];
234 for (c = 0; c < cols + 8; c++) {
235 int x = s[c + 7] - s[c - 8];
236 int y = s[c + 7] + s[c - 8];
243 if (sumsq * 15 - sum * sum < flimit) {
244 d[c & 15] = (8 + sum + s[c]) >> 4;
247 s[c - 8] = d[(c - 8) & 15];
254 void vp9_mbpost_proc_down_c(uint8_t *dst, int pitch,
255 int rows, int cols, int flimit) {
257 const short *rv3 = &vp9_rv[63 & rand()]; // NOLINT
259 for (c = 0; c < cols; c++) {
260 uint8_t *s = &dst[c];
264 const short *rv2 = rv3 + ((c * 17) & 127);
266 for (i = -8; i <= 6; i++) {
267 sumsq += s[i * pitch] * s[i * pitch];
271 for (r = 0; r < rows + 8; r++) {
272 sumsq += s[7 * pitch] * s[ 7 * pitch] - s[-8 * pitch] * s[-8 * pitch];
273 sum += s[7 * pitch] - s[-8 * pitch];
276 if (sumsq * 15 - sum * sum < flimit) {
277 d[r & 15] = (rv2[r & 127] + sum + s[0]) >> 4;
280 s[-8 * pitch] = d[(r - 8) & 15];
286 static void deblock_and_de_macro_block(YV12_BUFFER_CONFIG *source,
287 YV12_BUFFER_CONFIG *post,
291 double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
292 int ppl = (int)(level + .5);
293 (void) low_var_thresh;
296 vp9_post_proc_down_and_across(source->y_buffer, post->y_buffer,
297 source->y_stride, post->y_stride,
298 source->y_height, source->y_width, ppl);
300 vp9_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height,
301 post->y_width, q2mbl(q));
303 vp9_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height,
304 post->y_width, q2mbl(q));
306 vp9_post_proc_down_and_across(source->u_buffer, post->u_buffer,
307 source->uv_stride, post->uv_stride,
308 source->uv_height, source->uv_width, ppl);
309 vp9_post_proc_down_and_across(source->v_buffer, post->v_buffer,
310 source->uv_stride, post->uv_stride,
311 source->uv_height, source->uv_width, ppl);
314 void vp9_deblock(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
316 const int ppl = (int)(6.0e-05 * q * q * q - 0.0067 * q * q + 0.306 * q
320 const uint8_t *const srcs[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
322 const int src_strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
324 const int src_widths[4] = {src->y_width, src->uv_width, src->uv_width,
326 const int src_heights[4] = {src->y_height, src->uv_height, src->uv_height,
329 uint8_t *const dsts[4] = {dst->y_buffer, dst->u_buffer, dst->v_buffer,
331 const int dst_strides[4] = {dst->y_stride, dst->uv_stride, dst->uv_stride,
334 for (i = 0; i < MAX_MB_PLANE; ++i)
335 vp9_post_proc_down_and_across(srcs[i], dsts[i],
336 src_strides[i], dst_strides[i],
337 src_heights[i], src_widths[i], ppl);
340 void vp9_denoise(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
342 const int ppl = (int)(6.0e-05 * q * q * q - 0.0067 * q * q + 0.306 * q
346 const uint8_t *const srcs[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
348 const int src_strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
350 const int src_widths[4] = {src->y_width, src->uv_width, src->uv_width,
352 const int src_heights[4] = {src->y_height, src->uv_height, src->uv_height,
355 uint8_t *const dsts[4] = {dst->y_buffer, dst->u_buffer, dst->v_buffer,
357 const int dst_strides[4] = {dst->y_stride, dst->uv_stride, dst->uv_stride,
360 for (i = 0; i < MAX_MB_PLANE; ++i) {
361 const int src_stride = src_strides[i];
362 const uint8_t *const src = srcs[i] + 2 * src_stride + 2;
363 const int src_width = src_widths[i] - 4;
364 const int src_height = src_heights[i] - 4;
366 const int dst_stride = dst_strides[i];
367 uint8_t *const dst = dsts[i] + 2 * dst_stride + 2;
369 vp9_post_proc_down_and_across(src, dst, src_stride, dst_stride,
370 src_height, src_width, ppl);
374 static double gaussian(double sigma, double mu, double x) {
375 return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
376 (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
379 static void fillrd(struct postproc_state *state, int q, int a) {
383 int ai = a, qi = q, i;
385 vp9_clear_system_state();
387 sigma = ai + .5 + .6 * (63 - qi) / 63.0;
389 /* set up a lookup table of 256 entries that matches
390 * a gaussian distribution with sigma determined by q.
398 for (i = -32; i < 32; i++) {
399 int a = (int)(0.5 + 256 * gaussian(sigma, 0, i));
402 for (j = 0; j < a; j++) {
403 char_dist[next + j] = (char) i;
410 for (; next < 256; next++)
414 for (i = 0; i < 3072; i++) {
415 state->noise[i] = char_dist[rand() & 0xff]; // NOLINT
418 for (i = 0; i < 16; i++) {
419 state->blackclamp[i] = -char_dist[0];
420 state->whiteclamp[i] = -char_dist[0];
421 state->bothclamp[i] = -2 * char_dist[0];
425 state->last_noise = a;
428 void vp9_plane_add_noise_c(uint8_t *start, char *noise,
432 unsigned int width, unsigned int height, int pitch) {
435 for (i = 0; i < height; i++) {
436 uint8_t *pos = start + i * pitch;
437 char *ref = (char *)(noise + (rand() & 0xff)); // NOLINT
439 for (j = 0; j < width; j++) {
440 if (pos[j] < blackclamp[0])
441 pos[j] = blackclamp[0];
443 if (pos[j] > 255 + whiteclamp[0])
444 pos[j] = 255 + whiteclamp[0];
451 /* Blend the macro block with a solid colored square. Leave the
452 * edges unblended to give distinction to macro blocks in areas
453 * filled with the same color block.
455 void vp9_blend_mb_inner_c(uint8_t *y, uint8_t *u, uint8_t *v,
456 int y1, int u1, int v1, int alpha, int stride) {
458 int y1_const = y1 * ((1 << 16) - alpha);
459 int u1_const = u1 * ((1 << 16) - alpha);
460 int v1_const = v1 * ((1 << 16) - alpha);
463 for (i = 0; i < 12; i++) {
464 for (j = 0; j < 12; j++) {
465 y[j] = (y[j] * alpha + y1_const) >> 16;
475 for (i = 0; i < 6; i++) {
476 for (j = 0; j < 6; j++) {
477 u[j] = (u[j] * alpha + u1_const) >> 16;
478 v[j] = (v[j] * alpha + v1_const) >> 16;
485 /* Blend only the edge of the macro block. Leave center
486 * unblended to allow for other visualizations to be layered.
488 void vp9_blend_mb_outer_c(uint8_t *y, uint8_t *u, uint8_t *v,
489 int y1, int u1, int v1, int alpha, int stride) {
491 int y1_const = y1 * ((1 << 16) - alpha);
492 int u1_const = u1 * ((1 << 16) - alpha);
493 int v1_const = v1 * ((1 << 16) - alpha);
495 for (i = 0; i < 2; i++) {
496 for (j = 0; j < 16; j++) {
497 y[j] = (y[j] * alpha + y1_const) >> 16;
502 for (i = 0; i < 12; i++) {
503 y[0] = (y[0] * alpha + y1_const) >> 16;
504 y[1] = (y[1] * alpha + y1_const) >> 16;
505 y[14] = (y[14] * alpha + y1_const) >> 16;
506 y[15] = (y[15] * alpha + y1_const) >> 16;
510 for (i = 0; i < 2; i++) {
511 for (j = 0; j < 16; j++) {
512 y[j] = (y[j] * alpha + y1_const) >> 16;
519 for (j = 0; j < 8; j++) {
520 u[j] = (u[j] * alpha + u1_const) >> 16;
521 v[j] = (v[j] * alpha + v1_const) >> 16;
526 for (i = 0; i < 6; i++) {
527 u[0] = (u[0] * alpha + u1_const) >> 16;
528 v[0] = (v[0] * alpha + v1_const) >> 16;
530 u[7] = (u[7] * alpha + u1_const) >> 16;
531 v[7] = (v[7] * alpha + v1_const) >> 16;
537 for (j = 0; j < 8; j++) {
538 u[j] = (u[j] * alpha + u1_const) >> 16;
539 v[j] = (v[j] * alpha + v1_const) >> 16;
543 void vp9_blend_b_c(uint8_t *y, uint8_t *u, uint8_t *v,
544 int y1, int u1, int v1, int alpha, int stride) {
546 int y1_const = y1 * ((1 << 16) - alpha);
547 int u1_const = u1 * ((1 << 16) - alpha);
548 int v1_const = v1 * ((1 << 16) - alpha);
550 for (i = 0; i < 4; i++) {
551 for (j = 0; j < 4; j++) {
552 y[j] = (y[j] * alpha + y1_const) >> 16;
559 for (i = 0; i < 2; i++) {
560 for (j = 0; j < 2; j++) {
561 u[j] = (u[j] * alpha + u1_const) >> 16;
562 v[j] = (v[j] * alpha + v1_const) >> 16;
569 static void constrain_line(int x0, int *x1, int y0, int *y1,
570 int width, int height) {
580 *y1 = ((width - x0) * dy) / dx + y0;
588 *y1 = ((0 - x0) * dy) / dx + y0;
596 *x1 = ((height - y0) * dx) / dy + x0;
604 *x1 = ((0 - y0) * dx) / dy + x0;
608 int vp9_post_proc_frame(struct VP9Common *cm,
609 YV12_BUFFER_CONFIG *dest, vp9_ppflags_t *ppflags) {
610 const int q = MIN(63, cm->lf.filter_level * 10 / 6);
611 const int flags = ppflags->post_proc_flag;
612 YV12_BUFFER_CONFIG *const ppbuf = &cm->post_proc_buffer;
613 struct postproc_state *const ppstate = &cm->postproc_state;
615 if (!cm->frame_to_show)
619 *dest = *cm->frame_to_show;
623 vp9_clear_system_state();
625 if (flags & VP9D_DEMACROBLOCK) {
626 deblock_and_de_macro_block(cm->frame_to_show, ppbuf,
627 q + (ppflags->deblocking_level - 5) * 10, 1, 0);
628 } else if (flags & VP9D_DEBLOCK) {
629 vp9_deblock(cm->frame_to_show, ppbuf, q);
631 vp8_yv12_copy_frame(cm->frame_to_show, ppbuf);
634 if (flags & VP9D_ADDNOISE) {
635 const int noise_level = ppflags->noise_level;
636 if (ppstate->last_q != q ||
637 ppstate->last_noise != noise_level) {
638 fillrd(ppstate, 63 - q, noise_level);
641 vp9_plane_add_noise(ppbuf->y_buffer, ppstate->noise, ppstate->blackclamp,
642 ppstate->whiteclamp, ppstate->bothclamp,
643 ppbuf->y_width, ppbuf->y_height, ppbuf->y_stride);
646 #if 0 && CONFIG_POSTPROC_VISUALIZER
647 if (flags & VP9D_DEBUG_TXT_FRAME_INFO) {
649 snprintf(message, sizeof(message) -1,
650 "F%1dG%1dQ%3dF%3dP%d_s%dx%d",
651 (cm->frame_type == KEY_FRAME),
652 cm->refresh_golden_frame,
656 cm->mb_cols, cm->mb_rows);
657 vp9_blit_text(message, ppbuf->y_buffer, ppbuf->y_stride);
660 if (flags & VP9D_DEBUG_TXT_MBLK_MODES) {
663 int mb_rows = ppbuf->y_height >> 4;
664 int mb_cols = ppbuf->y_width >> 4;
666 MODE_INFO *mi = cm->mi;
668 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
670 /* vp9_filter each macro block */
671 for (i = 0; i < mb_rows; i++) {
672 for (j = 0; j < mb_cols; j++) {
675 snprintf(zz, sizeof(zz) - 1, "%c", mi[mb_index].mbmi.mode + 'a');
677 vp9_blit_text(zz, y_ptr, post->y_stride);
682 mb_index++; /* border */
683 y_ptr += post->y_stride * 16 - post->y_width;
687 if (flags & VP9D_DEBUG_TXT_DC_DIFF) {
690 int mb_rows = ppbuf->y_height >> 4;
691 int mb_cols = ppbuf->y_width >> 4;
693 MODE_INFO *mi = cm->mi;
695 y_ptr = post->y_buffer + 4 * post->y_stride + 4;
697 /* vp9_filter each macro block */
698 for (i = 0; i < mb_rows; i++) {
699 for (j = 0; j < mb_cols; j++) {
701 int dc_diff = !(mi[mb_index].mbmi.mode != I4X4_PRED &&
702 mi[mb_index].mbmi.mode != SPLITMV &&
703 mi[mb_index].mbmi.skip);
705 if (cm->frame_type == KEY_FRAME)
706 snprintf(zz, sizeof(zz) - 1, "a");
708 snprintf(zz, sizeof(zz) - 1, "%c", dc_diff + '0');
710 vp9_blit_text(zz, y_ptr, post->y_stride);
715 mb_index++; /* border */
716 y_ptr += post->y_stride * 16 - post->y_width;
720 if (flags & VP9D_DEBUG_TXT_RATE_INFO) {
722 snprintf(message, sizeof(message),
723 "Bitrate: %10.2f framerate: %10.2f ",
724 cm->bitrate, cm->framerate);
725 vp9_blit_text(message, ppbuf->y_buffer, ppbuf->y_stride);
728 /* Draw motion vectors */
729 if ((flags & VP9D_DEBUG_DRAW_MV) && ppflags->display_mv_flag) {
730 int width = ppbuf->y_width;
731 int height = ppbuf->y_height;
732 uint8_t *y_buffer = ppbuf->y_buffer;
733 int y_stride = ppbuf->y_stride;
734 MODE_INFO *mi = cm->mi;
737 for (y0 = 0; y0 < height; y0 += 16) {
738 for (x0 = 0; x0 < width; x0 += 16) {
741 if (!(ppflags->display_mv_flag & (1 << mi->mbmi.mode))) {
746 if (mi->mbmi.mode == SPLITMV) {
747 switch (mi->mbmi.partitioning) {
748 case PARTITIONING_16X8 : { /* mv_top_bottom */
749 union b_mode_info *bmi = &mi->bmi[0];
750 MV *mv = &bmi->mv.as_mv;
752 x1 = x0 + 8 + (mv->col >> 3);
753 y1 = y0 + 4 + (mv->row >> 3);
755 constrain_line(x0 + 8, &x1, y0 + 4, &y1, width, height);
756 vp9_blit_line(x0 + 8, x1, y0 + 4, y1, y_buffer, y_stride);
760 x1 = x0 + 8 + (mv->col >> 3);
761 y1 = y0 + 12 + (mv->row >> 3);
763 constrain_line(x0 + 8, &x1, y0 + 12, &y1, width, height);
764 vp9_blit_line(x0 + 8, x1, y0 + 12, y1, y_buffer, y_stride);
768 case PARTITIONING_8X16 : { /* mv_left_right */
769 union b_mode_info *bmi = &mi->bmi[0];
770 MV *mv = &bmi->mv.as_mv;
772 x1 = x0 + 4 + (mv->col >> 3);
773 y1 = y0 + 8 + (mv->row >> 3);
775 constrain_line(x0 + 4, &x1, y0 + 8, &y1, width, height);
776 vp9_blit_line(x0 + 4, x1, y0 + 8, y1, y_buffer, y_stride);
780 x1 = x0 + 12 + (mv->col >> 3);
781 y1 = y0 + 8 + (mv->row >> 3);
783 constrain_line(x0 + 12, &x1, y0 + 8, &y1, width, height);
784 vp9_blit_line(x0 + 12, x1, y0 + 8, y1, y_buffer, y_stride);
788 case PARTITIONING_8X8 : { /* mv_quarters */
789 union b_mode_info *bmi = &mi->bmi[0];
790 MV *mv = &bmi->mv.as_mv;
792 x1 = x0 + 4 + (mv->col >> 3);
793 y1 = y0 + 4 + (mv->row >> 3);
795 constrain_line(x0 + 4, &x1, y0 + 4, &y1, width, height);
796 vp9_blit_line(x0 + 4, x1, y0 + 4, y1, y_buffer, y_stride);
800 x1 = x0 + 12 + (mv->col >> 3);
801 y1 = y0 + 4 + (mv->row >> 3);
803 constrain_line(x0 + 12, &x1, y0 + 4, &y1, width, height);
804 vp9_blit_line(x0 + 12, x1, y0 + 4, y1, y_buffer, y_stride);
808 x1 = x0 + 4 + (mv->col >> 3);
809 y1 = y0 + 12 + (mv->row >> 3);
811 constrain_line(x0 + 4, &x1, y0 + 12, &y1, width, height);
812 vp9_blit_line(x0 + 4, x1, y0 + 12, y1, y_buffer, y_stride);
816 x1 = x0 + 12 + (mv->col >> 3);
817 y1 = y0 + 12 + (mv->row >> 3);
819 constrain_line(x0 + 12, &x1, y0 + 12, &y1, width, height);
820 vp9_blit_line(x0 + 12, x1, y0 + 12, y1, y_buffer, y_stride);
823 case PARTITIONING_4X4:
825 union b_mode_info *bmi = mi->bmi;
828 for (by0 = y0; by0 < (y0 + 16); by0 += 4) {
829 for (bx0 = x0; bx0 < (x0 + 16); bx0 += 4) {
830 MV *mv = &bmi->mv.as_mv;
832 x1 = bx0 + 2 + (mv->col >> 3);
833 y1 = by0 + 2 + (mv->row >> 3);
835 constrain_line(bx0 + 2, &x1, by0 + 2, &y1, width, height);
836 vp9_blit_line(bx0 + 2, x1, by0 + 2, y1, y_buffer, y_stride);
843 } else if (is_inter_mode(mi->mbmi.mode)) {
844 MV *mv = &mi->mbmi.mv.as_mv;
845 const int lx0 = x0 + 8;
846 const int ly0 = y0 + 8;
848 x1 = lx0 + (mv->col >> 3);
849 y1 = ly0 + (mv->row >> 3);
851 if (x1 != lx0 && y1 != ly0) {
852 constrain_line(lx0, &x1, ly0 - 1, &y1, width, height);
853 vp9_blit_line(lx0, x1, ly0 - 1, y1, y_buffer, y_stride);
855 constrain_line(lx0, &x1, ly0 + 1, &y1, width, height);
856 vp9_blit_line(lx0, x1, ly0 + 1, y1, y_buffer, y_stride);
858 vp9_blit_line(lx0, x1, ly0, y1, y_buffer, y_stride);
868 /* Color in block modes */
869 if ((flags & VP9D_DEBUG_CLR_BLK_MODES)
870 && (ppflags->display_mb_modes_flag || ppflags->display_b_modes_flag)) {
872 int width = ppbuf->y_width;
873 int height = ppbuf->y_height;
874 uint8_t *y_ptr = ppbuf->y_buffer;
875 uint8_t *u_ptr = ppbuf->u_buffer;
876 uint8_t *v_ptr = ppbuf->v_buffer;
877 int y_stride = ppbuf->y_stride;
878 MODE_INFO *mi = cm->mi;
880 for (y = 0; y < height; y += 16) {
881 for (x = 0; x < width; x += 16) {
882 int Y = 0, U = 0, V = 0;
884 if (mi->mbmi.mode == I4X4_PRED &&
885 ((ppflags->display_mb_modes_flag & I4X4_PRED) ||
886 ppflags->display_b_modes_flag)) {
888 uint8_t *yl, *ul, *vl;
889 union b_mode_info *bmi = mi->bmi;
892 ul = u_ptr + (x >> 1);
893 vl = v_ptr + (x >> 1);
895 for (by = 0; by < 16; by += 4) {
896 for (bx = 0; bx < 16; bx += 4) {
897 if ((ppflags->display_b_modes_flag & (1 << mi->mbmi.mode))
898 || (ppflags->display_mb_modes_flag & I4X4_PRED)) {
899 Y = B_PREDICTION_MODE_colors[bmi->as_mode][0];
900 U = B_PREDICTION_MODE_colors[bmi->as_mode][1];
901 V = B_PREDICTION_MODE_colors[bmi->as_mode][2];
903 vp9_blend_b(yl + bx, ul + (bx >> 1), vl + (bx >> 1), Y, U, V,
913 } else if (ppflags->display_mb_modes_flag & (1 << mi->mbmi.mode)) {
914 Y = MB_PREDICTION_MODE_colors[mi->mbmi.mode][0];
915 U = MB_PREDICTION_MODE_colors[mi->mbmi.mode][1];
916 V = MB_PREDICTION_MODE_colors[mi->mbmi.mode][2];
918 vp9_blend_mb_inner(y_ptr + x, u_ptr + (x >> 1), v_ptr + (x >> 1),
919 Y, U, V, 0xc000, y_stride);
924 y_ptr += y_stride * 16;
925 u_ptr += y_stride * 4;
926 v_ptr += y_stride * 4;
932 /* Color in frame reference blocks */
933 if ((flags & VP9D_DEBUG_CLR_FRM_REF_BLKS) &&
934 ppflags->display_ref_frame_flag) {
936 int width = ppbuf->y_width;
937 int height = ppbuf->y_height;
938 uint8_t *y_ptr = ppbuf->y_buffer;
939 uint8_t *u_ptr = ppbuf->u_buffer;
940 uint8_t *v_ptr = ppbuf->v_buffer;
941 int y_stride = ppbuf->y_stride;
942 MODE_INFO *mi = cm->mi;
944 for (y = 0; y < height; y += 16) {
945 for (x = 0; x < width; x += 16) {
946 int Y = 0, U = 0, V = 0;
948 if (ppflags->display_ref_frame_flag & (1 << mi->mbmi.ref_frame)) {
949 Y = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][0];
950 U = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][1];
951 V = MV_REFERENCE_FRAME_colors[mi->mbmi.ref_frame][2];
953 vp9_blend_mb_outer(y_ptr + x, u_ptr + (x >> 1), v_ptr + (x >> 1),
954 Y, U, V, 0xc000, y_stride);
959 y_ptr += y_stride * 16;
960 u_ptr += y_stride * 4;
961 v_ptr += y_stride * 4;
970 /* handle problem with extending borders */
971 dest->y_width = cm->width;
972 dest->y_height = cm->height;
973 dest->uv_width = dest->y_width >> cm->subsampling_x;
974 dest->uv_height = dest->y_height >> cm->subsampling_y;