Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 1 | /* |
Adrian Grange | a872b06 | 2016-03-24 11:38:32 -0700 | [diff] [blame] | 2 | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 3 | * |
Adrian Grange | a872b06 | 2016-03-24 11:38:32 -0700 | [diff] [blame] | 4 | * This source code is subject to the terms of the BSD 2 Clause License and |
| 5 | * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License |
| 6 | * was not distributed with this source code in the LICENSE file, you can |
| 7 | * obtain it at www.aomedia.org/license/software. If the Alliance for Open |
| 8 | * Media Patent License 1.0 was not distributed with this source code in the |
| 9 | * PATENTS file, you can obtain it at www.aomedia.org/license/patent. |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 10 | */ |
| 11 | |
Adrian Grange | cebe6f0 | 2016-03-25 12:11:05 -0700 | [diff] [blame^] | 12 | #include "aom_dsp/aom_dsp_common.h" |
| 13 | #include "aom_mem/aom_mem.h" |
Yaowu Xu | bf4202e | 2016-03-21 15:15:19 -0700 | [diff] [blame] | 14 | #include "aom_ports/mem.h" |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 15 | |
Yaowu Xu | cfea7dd | 2016-03-22 09:52:13 -0700 | [diff] [blame] | 16 | #include "av1/common/common.h" |
| 17 | #include "av1/encoder/extend.h" |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 18 | |
| 19 | static void copy_and_extend_plane(const uint8_t *src, int src_pitch, |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 20 | uint8_t *dst, int dst_pitch, int w, int h, |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 21 | int extend_top, int extend_left, |
| 22 | int extend_bottom, int extend_right) { |
| 23 | int i, linesize; |
| 24 | |
| 25 | // copy the left and right most columns out |
| 26 | const uint8_t *src_ptr1 = src; |
| 27 | const uint8_t *src_ptr2 = src + w - 1; |
| 28 | uint8_t *dst_ptr1 = dst - extend_left; |
| 29 | uint8_t *dst_ptr2 = dst + w; |
| 30 | |
| 31 | for (i = 0; i < h; i++) { |
| 32 | memset(dst_ptr1, src_ptr1[0], extend_left); |
| 33 | memcpy(dst_ptr1 + extend_left, src_ptr1, w); |
| 34 | memset(dst_ptr2, src_ptr2[0], extend_right); |
| 35 | src_ptr1 += src_pitch; |
| 36 | src_ptr2 += src_pitch; |
| 37 | dst_ptr1 += dst_pitch; |
| 38 | dst_ptr2 += dst_pitch; |
| 39 | } |
| 40 | |
| 41 | // Now copy the top and bottom lines into each line of the respective |
| 42 | // borders |
| 43 | src_ptr1 = dst - extend_left; |
| 44 | src_ptr2 = dst + dst_pitch * (h - 1) - extend_left; |
| 45 | dst_ptr1 = dst + dst_pitch * (-extend_top) - extend_left; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 46 | dst_ptr2 = dst + dst_pitch * (h)-extend_left; |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 47 | linesize = extend_left + extend_right + w; |
| 48 | |
| 49 | for (i = 0; i < extend_top; i++) { |
| 50 | memcpy(dst_ptr1, src_ptr1, linesize); |
| 51 | dst_ptr1 += dst_pitch; |
| 52 | } |
| 53 | |
| 54 | for (i = 0; i < extend_bottom; i++) { |
| 55 | memcpy(dst_ptr2, src_ptr2, linesize); |
| 56 | dst_ptr2 += dst_pitch; |
| 57 | } |
| 58 | } |
| 59 | |
Yaowu Xu | 3246fc0 | 2016-01-20 16:13:04 -0800 | [diff] [blame] | 60 | #if CONFIG_VPX_HIGHBITDEPTH |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 61 | static void highbd_copy_and_extend_plane(const uint8_t *src8, int src_pitch, |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 62 | uint8_t *dst8, int dst_pitch, int w, |
| 63 | int h, int extend_top, int extend_left, |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 64 | int extend_bottom, int extend_right) { |
| 65 | int i, linesize; |
| 66 | uint16_t *src = CONVERT_TO_SHORTPTR(src8); |
| 67 | uint16_t *dst = CONVERT_TO_SHORTPTR(dst8); |
| 68 | |
| 69 | // copy the left and right most columns out |
| 70 | const uint16_t *src_ptr1 = src; |
| 71 | const uint16_t *src_ptr2 = src + w - 1; |
| 72 | uint16_t *dst_ptr1 = dst - extend_left; |
| 73 | uint16_t *dst_ptr2 = dst + w; |
| 74 | |
| 75 | for (i = 0; i < h; i++) { |
Adrian Grange | cebe6f0 | 2016-03-25 12:11:05 -0700 | [diff] [blame^] | 76 | aom_memset16(dst_ptr1, src_ptr1[0], extend_left); |
hui su | 088b05f | 2015-08-12 10:41:51 -0700 | [diff] [blame] | 77 | memcpy(dst_ptr1 + extend_left, src_ptr1, w * sizeof(src_ptr1[0])); |
Adrian Grange | cebe6f0 | 2016-03-25 12:11:05 -0700 | [diff] [blame^] | 78 | aom_memset16(dst_ptr2, src_ptr2[0], extend_right); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 79 | src_ptr1 += src_pitch; |
| 80 | src_ptr2 += src_pitch; |
| 81 | dst_ptr1 += dst_pitch; |
| 82 | dst_ptr2 += dst_pitch; |
| 83 | } |
| 84 | |
| 85 | // Now copy the top and bottom lines into each line of the respective |
| 86 | // borders |
| 87 | src_ptr1 = dst - extend_left; |
| 88 | src_ptr2 = dst + dst_pitch * (h - 1) - extend_left; |
| 89 | dst_ptr1 = dst + dst_pitch * (-extend_top) - extend_left; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 90 | dst_ptr2 = dst + dst_pitch * (h)-extend_left; |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 91 | linesize = extend_left + extend_right + w; |
| 92 | |
| 93 | for (i = 0; i < extend_top; i++) { |
hui su | 088b05f | 2015-08-12 10:41:51 -0700 | [diff] [blame] | 94 | memcpy(dst_ptr1, src_ptr1, linesize * sizeof(src_ptr1[0])); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 95 | dst_ptr1 += dst_pitch; |
| 96 | } |
| 97 | |
| 98 | for (i = 0; i < extend_bottom; i++) { |
hui su | 088b05f | 2015-08-12 10:41:51 -0700 | [diff] [blame] | 99 | memcpy(dst_ptr2, src_ptr2, linesize * sizeof(src_ptr2[0])); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 100 | dst_ptr2 += dst_pitch; |
| 101 | } |
| 102 | } |
Yaowu Xu | 3246fc0 | 2016-01-20 16:13:04 -0800 | [diff] [blame] | 103 | #endif // CONFIG_VPX_HIGHBITDEPTH |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 104 | |
| 105 | void vp10_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src, |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 106 | YV12_BUFFER_CONFIG *dst) { |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 107 | // Extend src frame in buffer |
| 108 | // Altref filtering assumes 16 pixel extension |
| 109 | const int et_y = 16; |
| 110 | const int el_y = 16; |
| 111 | // Motion estimation may use src block variance with the block size up |
| 112 | // to 64x64, so the right and bottom need to be extended to 64 multiple |
| 113 | // or up to 16, whichever is greater. |
James Zern | 5e16d39 | 2015-08-17 18:19:22 -0700 | [diff] [blame] | 114 | const int er_y = |
| 115 | VPXMAX(src->y_width + 16, ALIGN_POWER_OF_TWO(src->y_width, 6)) - |
| 116 | src->y_crop_width; |
| 117 | const int eb_y = |
| 118 | VPXMAX(src->y_height + 16, ALIGN_POWER_OF_TWO(src->y_height, 6)) - |
| 119 | src->y_crop_height; |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 120 | const int uv_width_subsampling = (src->uv_width != src->y_width); |
| 121 | const int uv_height_subsampling = (src->uv_height != src->y_height); |
| 122 | const int et_uv = et_y >> uv_height_subsampling; |
| 123 | const int el_uv = el_y >> uv_width_subsampling; |
| 124 | const int eb_uv = eb_y >> uv_height_subsampling; |
| 125 | const int er_uv = er_y >> uv_width_subsampling; |
| 126 | |
Yaowu Xu | 3246fc0 | 2016-01-20 16:13:04 -0800 | [diff] [blame] | 127 | #if CONFIG_VPX_HIGHBITDEPTH |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 128 | if (src->flags & YV12_FLAG_HIGHBITDEPTH) { |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 129 | highbd_copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer, |
| 130 | dst->y_stride, src->y_crop_width, |
| 131 | src->y_crop_height, et_y, el_y, eb_y, er_y); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 132 | |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 133 | highbd_copy_and_extend_plane( |
| 134 | src->u_buffer, src->uv_stride, dst->u_buffer, dst->uv_stride, |
| 135 | src->uv_crop_width, src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 136 | |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 137 | highbd_copy_and_extend_plane( |
| 138 | src->v_buffer, src->uv_stride, dst->v_buffer, dst->uv_stride, |
| 139 | src->uv_crop_width, src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 140 | return; |
| 141 | } |
Yaowu Xu | 3246fc0 | 2016-01-20 16:13:04 -0800 | [diff] [blame] | 142 | #endif // CONFIG_VPX_HIGHBITDEPTH |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 143 | |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 144 | copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer, |
| 145 | dst->y_stride, src->y_crop_width, src->y_crop_height, |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 146 | et_y, el_y, eb_y, er_y); |
| 147 | |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 148 | copy_and_extend_plane(src->u_buffer, src->uv_stride, dst->u_buffer, |
| 149 | dst->uv_stride, src->uv_crop_width, src->uv_crop_height, |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 150 | et_uv, el_uv, eb_uv, er_uv); |
| 151 | |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 152 | copy_and_extend_plane(src->v_buffer, src->uv_stride, dst->v_buffer, |
| 153 | dst->uv_stride, src->uv_crop_width, src->uv_crop_height, |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 154 | et_uv, el_uv, eb_uv, er_uv); |
| 155 | } |
| 156 | |
| 157 | void vp10_copy_and_extend_frame_with_rect(const YV12_BUFFER_CONFIG *src, |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 158 | YV12_BUFFER_CONFIG *dst, int srcy, |
| 159 | int srcx, int srch, int srcw) { |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 160 | // If the side is not touching the bounder then don't extend. |
| 161 | const int et_y = srcy ? 0 : dst->border; |
| 162 | const int el_y = srcx ? 0 : dst->border; |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 163 | const int eb_y = srcy + srch != src->y_height |
| 164 | ? 0 |
| 165 | : dst->border + dst->y_height - src->y_height; |
| 166 | const int er_y = srcx + srcw != src->y_width |
| 167 | ? 0 |
| 168 | : dst->border + dst->y_width - src->y_width; |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 169 | const int src_y_offset = srcy * src->y_stride + srcx; |
| 170 | const int dst_y_offset = srcy * dst->y_stride + srcx; |
| 171 | |
| 172 | const int et_uv = ROUND_POWER_OF_TWO(et_y, 1); |
| 173 | const int el_uv = ROUND_POWER_OF_TWO(el_y, 1); |
| 174 | const int eb_uv = ROUND_POWER_OF_TWO(eb_y, 1); |
| 175 | const int er_uv = ROUND_POWER_OF_TWO(er_y, 1); |
| 176 | const int src_uv_offset = ((srcy * src->uv_stride) >> 1) + (srcx >> 1); |
| 177 | const int dst_uv_offset = ((srcy * dst->uv_stride) >> 1) + (srcx >> 1); |
| 178 | const int srch_uv = ROUND_POWER_OF_TWO(srch, 1); |
| 179 | const int srcw_uv = ROUND_POWER_OF_TWO(srcw, 1); |
| 180 | |
| 181 | copy_and_extend_plane(src->y_buffer + src_y_offset, src->y_stride, |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 182 | dst->y_buffer + dst_y_offset, dst->y_stride, srcw, srch, |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 183 | et_y, el_y, eb_y, er_y); |
| 184 | |
| 185 | copy_and_extend_plane(src->u_buffer + src_uv_offset, src->uv_stride, |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 186 | dst->u_buffer + dst_uv_offset, dst->uv_stride, srcw_uv, |
| 187 | srch_uv, et_uv, el_uv, eb_uv, er_uv); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 188 | |
| 189 | copy_and_extend_plane(src->v_buffer + src_uv_offset, src->uv_stride, |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 190 | dst->v_buffer + dst_uv_offset, dst->uv_stride, srcw_uv, |
| 191 | srch_uv, et_uv, el_uv, eb_uv, er_uv); |
Jingning Han | 3ee6db6 | 2015-08-05 19:00:31 -0700 | [diff] [blame] | 192 | } |