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
copy_and_extend_plane(const uint8_t * src,int src_pitch,uint8_t * dst,int dst_pitch,int w,int h,int extend_top,int extend_left,int extend_bottom,int extend_right,int chroma_step)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
highbd_copy_and_extend_plane(const uint8_t * src8,int src_pitch,uint8_t * dst8,int dst_pitch,int w,int h,int extend_top,int extend_left,int extend_bottom,int extend_right)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
av1_copy_and_extend_frame(const YV12_BUFFER_CONFIG * src,YV12_BUFFER_CONFIG * dst)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 }
164