extend.c (6282B)
1 /* 2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved. 3 * 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. 10 */ 11 12 #include <assert.h> 13 14 #include "aom_dsp/aom_dsp_common.h" 15 #include "aom_mem/aom_mem.h" 16 #include "aom_ports/mem.h" 17 18 #include "av1/common/common.h" 19 #include "av1/encoder/extend.h" 20 21 static void copy_and_extend_plane(const uint8_t *src, int src_pitch, 22 uint8_t *dst, int dst_pitch, int w, int h, 23 int extend_top, int extend_left, 24 int extend_bottom, int extend_right, 25 int chroma_step) { 26 int i, linesize; 27 // copy the left and right most columns out 28 const uint8_t *src_ptr1 = src; 29 const uint8_t *src_ptr2 = src + (w - 1) * chroma_step; 30 uint8_t *dst_ptr1 = dst - extend_left; 31 uint8_t *dst_ptr2 = dst + w; 32 33 for (i = 0; i < h; i++) { 34 memset(dst_ptr1, src_ptr1[0], extend_left); 35 if (chroma_step == 1) { 36 memcpy(dst_ptr1 + extend_left, src_ptr1, w); 37 } else { 38 for (int j = 0; j < w; j++) { 39 dst_ptr1[extend_left + j] = src_ptr1[chroma_step * j]; 40 } 41 } 42 memset(dst_ptr2, src_ptr2[0], extend_right); 43 src_ptr1 += src_pitch; 44 src_ptr2 += src_pitch; 45 dst_ptr1 += dst_pitch; 46 dst_ptr2 += dst_pitch; 47 } 48 49 // Now copy the top and bottom lines into each line of the respective 50 // borders 51 src_ptr1 = dst - extend_left; 52 src_ptr2 = dst + dst_pitch * (h - 1) - extend_left; 53 dst_ptr1 = dst + dst_pitch * (-extend_top) - extend_left; 54 dst_ptr2 = dst + dst_pitch * (h)-extend_left; 55 linesize = extend_left + extend_right + w; 56 assert(linesize <= dst_pitch); 57 58 for (i = 0; i < extend_top; i++) { 59 memcpy(dst_ptr1, src_ptr1, linesize); 60 dst_ptr1 += dst_pitch; 61 } 62 63 for (i = 0; i < extend_bottom; i++) { 64 memcpy(dst_ptr2, src_ptr2, linesize); 65 dst_ptr2 += dst_pitch; 66 } 67 } 68 69 static void highbd_copy_and_extend_plane(const uint8_t *src8, int src_pitch, 70 uint8_t *dst8, int dst_pitch, int w, 71 int h, int extend_top, int extend_left, 72 int extend_bottom, int extend_right) { 73 int i, linesize; 74 uint16_t *src = CONVERT_TO_SHORTPTR(src8); 75 uint16_t *dst = CONVERT_TO_SHORTPTR(dst8); 76 77 // copy the left and right most columns out 78 const uint16_t *src_ptr1 = src; 79 const uint16_t *src_ptr2 = src + w - 1; 80 uint16_t *dst_ptr1 = dst - extend_left; 81 uint16_t *dst_ptr2 = dst + w; 82 83 for (i = 0; i < h; i++) { 84 aom_memset16(dst_ptr1, src_ptr1[0], extend_left); 85 memcpy(dst_ptr1 + extend_left, src_ptr1, w * sizeof(src_ptr1[0])); 86 aom_memset16(dst_ptr2, src_ptr2[0], extend_right); 87 src_ptr1 += src_pitch; 88 src_ptr2 += src_pitch; 89 dst_ptr1 += dst_pitch; 90 dst_ptr2 += dst_pitch; 91 } 92 93 // Now copy the top and bottom lines into each line of the respective 94 // borders 95 src_ptr1 = dst - extend_left; 96 src_ptr2 = dst + dst_pitch * (h - 1) - extend_left; 97 dst_ptr1 = dst + dst_pitch * (-extend_top) - extend_left; 98 dst_ptr2 = dst + dst_pitch * (h)-extend_left; 99 linesize = extend_left + extend_right + w; 100 assert(linesize <= dst_pitch); 101 102 for (i = 0; i < extend_top; i++) { 103 memcpy(dst_ptr1, src_ptr1, linesize * sizeof(src_ptr1[0])); 104 dst_ptr1 += dst_pitch; 105 } 106 107 for (i = 0; i < extend_bottom; i++) { 108 memcpy(dst_ptr2, src_ptr2, linesize * sizeof(src_ptr2[0])); 109 dst_ptr2 += dst_pitch; 110 } 111 } 112 113 void av1_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src, 114 YV12_BUFFER_CONFIG *dst) { 115 // Extend src frame in buffer 116 const int et_y = dst->border; 117 const int el_y = dst->border; 118 const int er_y = 119 AOMMAX(src->y_width + dst->border, ALIGN_POWER_OF_TWO(src->y_width, 6)) - 120 src->y_crop_width; 121 const int eb_y = AOMMAX(src->y_height + dst->border, 122 ALIGN_POWER_OF_TWO(src->y_height, 6)) - 123 src->y_crop_height; 124 const int uv_width_subsampling = src->subsampling_x; 125 const int uv_height_subsampling = src->subsampling_y; 126 const int et_uv = et_y >> uv_height_subsampling; 127 const int el_uv = el_y >> uv_width_subsampling; 128 const int eb_uv = eb_y >> uv_height_subsampling; 129 const int er_uv = er_y >> uv_width_subsampling; 130 131 if (src->flags & YV12_FLAG_HIGHBITDEPTH) { 132 highbd_copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer, 133 dst->y_stride, src->y_crop_width, 134 src->y_crop_height, et_y, el_y, eb_y, er_y); 135 if (!src->monochrome) { 136 highbd_copy_and_extend_plane( 137 src->u_buffer, src->uv_stride, dst->u_buffer, dst->uv_stride, 138 src->uv_crop_width, src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv); 139 highbd_copy_and_extend_plane( 140 src->v_buffer, src->uv_stride, dst->v_buffer, dst->uv_stride, 141 src->uv_crop_width, src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv); 142 } 143 return; 144 } 145 146 copy_and_extend_plane(src->y_buffer, src->y_stride, dst->y_buffer, 147 dst->y_stride, src->y_crop_width, src->y_crop_height, 148 et_y, el_y, eb_y, er_y, 1); 149 if (!src->monochrome) { 150 // detect nv12 format 151 const int chroma_step = src->v_buffer ? 1 : 2; 152 const uint8_t *src_v_buffer = 153 src->v_buffer ? src->v_buffer : src->u_buffer + 1; 154 copy_and_extend_plane(src->u_buffer, src->uv_stride, dst->u_buffer, 155 dst->uv_stride, src->uv_crop_width, 156 src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv, 157 chroma_step); 158 copy_and_extend_plane(src_v_buffer, src->uv_stride, dst->v_buffer, 159 dst->uv_stride, src->uv_crop_width, 160 src->uv_crop_height, et_uv, el_uv, eb_uv, er_uv, 161 chroma_step); 162 } 163 }