/src/libvpx/vp9/encoder/vp9_frame_scale.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  *  Copyright (c) 2017 The WebM project authors. All Rights Reserved. | 
| 3 |  |  * | 
| 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. | 
| 9 |  |  */ | 
| 10 |  |  | 
| 11 |  | #include "./vp9_rtcd.h" | 
| 12 |  | #include "./vpx_config.h" | 
| 13 |  | #include "./vpx_dsp_rtcd.h" | 
| 14 |  | #include "./vpx_scale_rtcd.h" | 
| 15 |  | #include "vp9/common/vp9_blockd.h" | 
| 16 |  | #include "vp9/encoder/vp9_encoder.h" | 
| 17 |  | #include "vpx/vpx_codec.h" | 
| 18 |  | #include "vpx_dsp/vpx_filter.h" | 
| 19 |  | #include "vpx_scale/yv12config.h" | 
| 20 |  |  | 
| 21 |  | void vp9_scale_and_extend_frame_c(const YV12_BUFFER_CONFIG *src, | 
| 22 |  |                                   YV12_BUFFER_CONFIG *dst, | 
| 23 | 0 |                                   INTERP_FILTER filter_type, int phase_scaler) { | 
| 24 | 0 |   const int src_w = src->y_crop_width; | 
| 25 | 0 |   const int src_h = src->y_crop_height; | 
| 26 | 0 |   const uint8_t *const srcs[3] = { src->y_buffer, src->u_buffer, | 
| 27 | 0 |                                    src->v_buffer }; | 
| 28 | 0 |   const int src_strides[3] = { src->y_stride, src->uv_stride, src->uv_stride }; | 
| 29 | 0 |   uint8_t *const dsts[3] = { dst->y_buffer, dst->u_buffer, dst->v_buffer }; | 
| 30 | 0 |   const int dst_strides[3] = { dst->y_stride, dst->uv_stride, dst->uv_stride }; | 
| 31 | 0 |   const InterpKernel *const kernel = vp9_filter_kernels[filter_type]; | 
| 32 | 0 |   int x, y, i; | 
| 33 |  | 
 | 
| 34 | 0 | #if HAVE_SSSE3 || HAVE_NEON | 
| 35 |  |   // TODO(linfengz): The 4:3 specialized C code is disabled by default since | 
| 36 |  |   // it's much slower than the general version which calls vpx_scaled_2d() even | 
| 37 |  |   // if vpx_scaled_2d() is not optimized. It will only be enabled as a reference | 
| 38 |  |   // for the platforms which have faster optimization. | 
| 39 | 0 |   if (4 * dst->y_crop_width == 3 * src_w && | 
| 40 | 0 |       4 * dst->y_crop_height == 3 * src_h) { | 
| 41 |  |     // Specialize 4 to 3 scaling. | 
| 42 |  |     // Example pixel locations. | 
| 43 |  |     // (O: Original pixel. S: Scaled pixel. X: Overlapped pixel.) | 
| 44 |  |     //      phase_scaler = 0               |      phase_scaler = 8 | 
| 45 |  |     //                                     | | 
| 46 |  |     //      X     O S   O   S O     X      |      O     O     O     O     O | 
| 47 |  |     //                                     | | 
| 48 |  |     //                                     | | 
| 49 |  |     //                                     |         S       S       S | 
| 50 |  |     //                                     | | 
| 51 |  |     //                                     | | 
| 52 |  |     //      O     O     O     O     O      |      O     O     O     O     O | 
| 53 |  |     //                                     | | 
| 54 |  |     //      S       S       S       S      | | 
| 55 |  |     //                                     | | 
| 56 |  |     //                                     | | 
| 57 |  |     //                                     |         S       S       S | 
| 58 |  |     //      O     O     O     O     O      |      O     O     O     O     O | 
| 59 |  |     //                                     | | 
| 60 |  |     //                                     | | 
| 61 |  |     //                                     | | 
| 62 |  |     //      S       S       S       S      | | 
| 63 |  |     //                                     | | 
| 64 |  |     //      O     O     O     O     O      |      O     O     O     O     O | 
| 65 |  |     //                                     |         S       S       S | 
| 66 |  |     //                                     | | 
| 67 |  |     //                                     | | 
| 68 |  |     //                                     | | 
| 69 |  |     //                                     | | 
| 70 |  |     //      X     O S   O   S O     X      |      O     O     O     O     O | 
| 71 |  | 
 | 
| 72 | 0 |     const int dst_ws[3] = { dst->y_crop_width, dst->uv_crop_width, | 
| 73 | 0 |                             dst->uv_crop_width }; | 
| 74 | 0 |     const int dst_hs[3] = { dst->y_crop_height, dst->uv_crop_height, | 
| 75 | 0 |                             dst->uv_crop_height }; | 
| 76 | 0 |     for (i = 0; i < MAX_MB_PLANE; ++i) { | 
| 77 | 0 |       const int dst_w = dst_ws[i]; | 
| 78 | 0 |       const int dst_h = dst_hs[i]; | 
| 79 | 0 |       const int src_stride = src_strides[i]; | 
| 80 | 0 |       const int dst_stride = dst_strides[i]; | 
| 81 | 0 |       for (y = 0; y < dst_h; y += 3) { | 
| 82 | 0 |         for (x = 0; x < dst_w; x += 3) { | 
| 83 | 0 |           const uint8_t *src_ptr = srcs[i] + 4 * y / 3 * src_stride + 4 * x / 3; | 
| 84 | 0 |           uint8_t *dst_ptr = dsts[i] + y * dst_stride + x; | 
| 85 |  |  | 
| 86 |  |           // Must call c function because its optimization doesn't support 3x3. | 
| 87 | 0 |           vpx_scaled_2d_c(src_ptr, src_stride, dst_ptr, dst_stride, kernel, | 
| 88 | 0 |                           phase_scaler, 64 / 3, phase_scaler, 64 / 3, 3, 3); | 
| 89 | 0 |         } | 
| 90 | 0 |       } | 
| 91 | 0 |     } | 
| 92 | 0 |   } else | 
| 93 | 0 | #endif | 
| 94 | 0 |   { | 
| 95 | 0 |     const int dst_w = dst->y_crop_width; | 
| 96 | 0 |     const int dst_h = dst->y_crop_height; | 
| 97 |  |  | 
| 98 |  |     // The issue b/311394513 reveals a corner case bug. vpx_scaled_2d() requires | 
| 99 |  |     // both x_step_q4 and y_step_q4 are less than or equal to 64. Otherwise, it | 
| 100 |  |     // needs to call vp9_scale_and_extend_frame_nonnormative() that supports | 
| 101 |  |     // arbitrary scaling. | 
| 102 | 0 |     const int x_step_q4 = 16 * src_w / dst_w; | 
| 103 | 0 |     const int y_step_q4 = 16 * src_h / dst_h; | 
| 104 | 0 |     if (x_step_q4 > 64 || y_step_q4 > 64) { | 
| 105 |  |       // This function is only called while cm->bit_depth is VPX_BITS_8. | 
| 106 | 0 | #if CONFIG_VP9_HIGHBITDEPTH | 
| 107 | 0 |       vp9_scale_and_extend_frame_nonnormative(src, dst, (int)VPX_BITS_8); | 
| 108 |  | #else | 
| 109 |  |       vp9_scale_and_extend_frame_nonnormative(src, dst); | 
| 110 |  | #endif  // CONFIG_VP9_HIGHBITDEPTH | 
| 111 | 0 |       return; | 
| 112 | 0 |     } | 
| 113 |  |  | 
| 114 | 0 |     for (i = 0; i < MAX_MB_PLANE; ++i) { | 
| 115 | 0 |       const int factor = (i == 0 || i == 3 ? 1 : 2); | 
| 116 | 0 |       const int src_stride = src_strides[i]; | 
| 117 | 0 |       const int dst_stride = dst_strides[i]; | 
| 118 | 0 |       for (y = 0; y < dst_h; y += 16) { | 
| 119 | 0 |         const int y_q4 = y * (16 / factor) * src_h / dst_h + phase_scaler; | 
| 120 | 0 |         for (x = 0; x < dst_w; x += 16) { | 
| 121 | 0 |           const int x_q4 = x * (16 / factor) * src_w / dst_w + phase_scaler; | 
| 122 | 0 |           const uint8_t *src_ptr = srcs[i] + | 
| 123 | 0 |                                    (y / factor) * src_h / dst_h * src_stride + | 
| 124 | 0 |                                    (x / factor) * src_w / dst_w; | 
| 125 | 0 |           uint8_t *dst_ptr = dsts[i] + (y / factor) * dst_stride + (x / factor); | 
| 126 |  | 
 | 
| 127 | 0 |           vpx_scaled_2d(src_ptr, src_stride, dst_ptr, dst_stride, kernel, | 
| 128 | 0 |                         x_q4 & 0xf, 16 * src_w / dst_w, y_q4 & 0xf, | 
| 129 | 0 |                         16 * src_h / dst_h, 16 / factor, 16 / factor); | 
| 130 | 0 |         } | 
| 131 | 0 |       } | 
| 132 | 0 |     } | 
| 133 | 0 |   } | 
| 134 |  |  | 
| 135 | 0 |   vpx_extend_frame_borders(dst); | 
| 136 | 0 | } |