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.
12 #include "./vpx_config.h"
13 #include "./vpx_scale_rtcd.h"
14 #include "vpx/vpx_integer.h"
15 #include "vpx_mem/vpx_mem.h"
16 #include "vpx_ports/mem.h"
17 #include "vpx_scale/yv12config.h"
18 #if CONFIG_VP9_HIGHBITDEPTH
19 #include "vp9/common/vp9_common.h"
22 static void extend_plane(uint8_t *const src
, int src_stride
,
23 int width
, int height
,
24 int extend_top
, int extend_left
,
25 int extend_bottom
, int extend_right
) {
27 const int linesize
= extend_left
+ extend_right
+ width
;
29 /* copy the left and right most columns out */
30 uint8_t *src_ptr1
= src
;
31 uint8_t *src_ptr2
= src
+ width
- 1;
32 uint8_t *dst_ptr1
= src
- extend_left
;
33 uint8_t *dst_ptr2
= src
+ width
;
35 for (i
= 0; i
< height
; ++i
) {
36 memset(dst_ptr1
, src_ptr1
[0], extend_left
);
37 memset(dst_ptr2
, src_ptr2
[0], extend_right
);
38 src_ptr1
+= src_stride
;
39 src_ptr2
+= src_stride
;
40 dst_ptr1
+= src_stride
;
41 dst_ptr2
+= src_stride
;
44 /* Now copy the top and bottom lines into each line of the respective
47 src_ptr1
= src
- extend_left
;
48 src_ptr2
= src
+ src_stride
* (height
- 1) - extend_left
;
49 dst_ptr1
= src
+ src_stride
* -extend_top
- extend_left
;
50 dst_ptr2
= src
+ src_stride
* height
- extend_left
;
52 for (i
= 0; i
< extend_top
; ++i
) {
53 memcpy(dst_ptr1
, src_ptr1
, linesize
);
54 dst_ptr1
+= src_stride
;
57 for (i
= 0; i
< extend_bottom
; ++i
) {
58 memcpy(dst_ptr2
, src_ptr2
, linesize
);
59 dst_ptr2
+= src_stride
;
63 #if CONFIG_VP9_HIGHBITDEPTH
64 static void extend_plane_high(uint8_t *const src8
, int src_stride
,
65 int width
, int height
,
66 int extend_top
, int extend_left
,
67 int extend_bottom
, int extend_right
) {
69 const int linesize
= extend_left
+ extend_right
+ width
;
70 uint16_t *src
= CONVERT_TO_SHORTPTR(src8
);
72 /* copy the left and right most columns out */
73 uint16_t *src_ptr1
= src
;
74 uint16_t *src_ptr2
= src
+ width
- 1;
75 uint16_t *dst_ptr1
= src
- extend_left
;
76 uint16_t *dst_ptr2
= src
+ width
;
78 for (i
= 0; i
< height
; ++i
) {
79 vpx_memset16(dst_ptr1
, src_ptr1
[0], extend_left
);
80 vpx_memset16(dst_ptr2
, src_ptr2
[0], extend_right
);
81 src_ptr1
+= src_stride
;
82 src_ptr2
+= src_stride
;
83 dst_ptr1
+= src_stride
;
84 dst_ptr2
+= src_stride
;
87 /* Now copy the top and bottom lines into each line of the respective
90 src_ptr1
= src
- extend_left
;
91 src_ptr2
= src
+ src_stride
* (height
- 1) - extend_left
;
92 dst_ptr1
= src
+ src_stride
* -extend_top
- extend_left
;
93 dst_ptr2
= src
+ src_stride
* height
- extend_left
;
95 for (i
= 0; i
< extend_top
; ++i
) {
96 memcpy(dst_ptr1
, src_ptr1
, linesize
* sizeof(uint16_t));
97 dst_ptr1
+= src_stride
;
100 for (i
= 0; i
< extend_bottom
; ++i
) {
101 memcpy(dst_ptr2
, src_ptr2
, linesize
* sizeof(uint16_t));
102 dst_ptr2
+= src_stride
;
107 void vp8_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG
*ybf
) {
108 const int uv_border
= ybf
->border
/ 2;
110 assert(ybf
->border
% 2 == 0);
111 assert(ybf
->y_height
- ybf
->y_crop_height
< 16);
112 assert(ybf
->y_width
- ybf
->y_crop_width
< 16);
113 assert(ybf
->y_height
- ybf
->y_crop_height
>= 0);
114 assert(ybf
->y_width
- ybf
->y_crop_width
>= 0);
116 #if CONFIG_VP9_HIGHBITDEPTH
117 if (ybf
->flags
& YV12_FLAG_HIGHBITDEPTH
) {
119 ybf
->y_buffer
, ybf
->y_stride
,
120 ybf
->y_crop_width
, ybf
->y_crop_height
,
121 ybf
->border
, ybf
->border
,
122 ybf
->border
+ ybf
->y_height
- ybf
->y_crop_height
,
123 ybf
->border
+ ybf
->y_width
- ybf
->y_crop_width
);
126 ybf
->u_buffer
, ybf
->uv_stride
,
127 ybf
->uv_crop_width
, ybf
->uv_crop_height
,
128 uv_border
, uv_border
,
129 uv_border
+ ybf
->uv_height
- ybf
->uv_crop_height
,
130 uv_border
+ ybf
->uv_width
- ybf
->uv_crop_width
);
133 ybf
->v_buffer
, ybf
->uv_stride
,
134 ybf
->uv_crop_width
, ybf
->uv_crop_height
,
135 uv_border
, uv_border
,
136 uv_border
+ ybf
->uv_height
- ybf
->uv_crop_height
,
137 uv_border
+ ybf
->uv_width
- ybf
->uv_crop_width
);
141 extend_plane(ybf
->y_buffer
, ybf
->y_stride
,
142 ybf
->y_crop_width
, ybf
->y_crop_height
,
143 ybf
->border
, ybf
->border
,
144 ybf
->border
+ ybf
->y_height
- ybf
->y_crop_height
,
145 ybf
->border
+ ybf
->y_width
- ybf
->y_crop_width
);
147 extend_plane(ybf
->u_buffer
, ybf
->uv_stride
,
148 ybf
->uv_crop_width
, ybf
->uv_crop_height
,
149 uv_border
, uv_border
,
150 uv_border
+ ybf
->uv_height
- ybf
->uv_crop_height
,
151 uv_border
+ ybf
->uv_width
- ybf
->uv_crop_width
);
153 extend_plane(ybf
->v_buffer
, ybf
->uv_stride
,
154 ybf
->uv_crop_width
, ybf
->uv_crop_height
,
155 uv_border
, uv_border
,
156 uv_border
+ ybf
->uv_height
- ybf
->uv_crop_height
,
157 uv_border
+ ybf
->uv_width
- ybf
->uv_crop_width
);
160 #if CONFIG_VP9 || CONFIG_VP10
161 static void extend_frame(YV12_BUFFER_CONFIG
*const ybf
, int ext_size
) {
162 const int c_w
= ybf
->uv_crop_width
;
163 const int c_h
= ybf
->uv_crop_height
;
164 const int ss_x
= ybf
->uv_width
< ybf
->y_width
;
165 const int ss_y
= ybf
->uv_height
< ybf
->y_height
;
166 const int c_et
= ext_size
>> ss_y
;
167 const int c_el
= ext_size
>> ss_x
;
168 const int c_eb
= c_et
+ ybf
->uv_height
- ybf
->uv_crop_height
;
169 const int c_er
= c_el
+ ybf
->uv_width
- ybf
->uv_crop_width
;
171 assert(ybf
->y_height
- ybf
->y_crop_height
< 16);
172 assert(ybf
->y_width
- ybf
->y_crop_width
< 16);
173 assert(ybf
->y_height
- ybf
->y_crop_height
>= 0);
174 assert(ybf
->y_width
- ybf
->y_crop_width
>= 0);
176 #if CONFIG_VP9_HIGHBITDEPTH
177 if (ybf
->flags
& YV12_FLAG_HIGHBITDEPTH
) {
178 extend_plane_high(ybf
->y_buffer
, ybf
->y_stride
,
179 ybf
->y_crop_width
, ybf
->y_crop_height
,
181 ext_size
+ ybf
->y_height
- ybf
->y_crop_height
,
182 ext_size
+ ybf
->y_width
- ybf
->y_crop_width
);
183 extend_plane_high(ybf
->u_buffer
, ybf
->uv_stride
,
184 c_w
, c_h
, c_et
, c_el
, c_eb
, c_er
);
185 extend_plane_high(ybf
->v_buffer
, ybf
->uv_stride
,
186 c_w
, c_h
, c_et
, c_el
, c_eb
, c_er
);
190 extend_plane(ybf
->y_buffer
, ybf
->y_stride
,
191 ybf
->y_crop_width
, ybf
->y_crop_height
,
193 ext_size
+ ybf
->y_height
- ybf
->y_crop_height
,
194 ext_size
+ ybf
->y_width
- ybf
->y_crop_width
);
196 extend_plane(ybf
->u_buffer
, ybf
->uv_stride
,
197 c_w
, c_h
, c_et
, c_el
, c_eb
, c_er
);
199 extend_plane(ybf
->v_buffer
, ybf
->uv_stride
,
200 c_w
, c_h
, c_et
, c_el
, c_eb
, c_er
);
203 void vp9_extend_frame_borders_c(YV12_BUFFER_CONFIG
*ybf
) {
204 extend_frame(ybf
, ybf
->border
);
207 void vp9_extend_frame_inner_borders_c(YV12_BUFFER_CONFIG
*ybf
) {
208 const int inner_bw
= (ybf
->border
> VP9INNERBORDERINPIXELS
) ?
209 VP9INNERBORDERINPIXELS
: ybf
->border
;
210 extend_frame(ybf
, inner_bw
);
213 #if CONFIG_VP9_HIGHBITDEPTH
214 void memcpy_short_addr(uint8_t *dst8
, const uint8_t *src8
, int num
) {
215 uint16_t *dst
= CONVERT_TO_SHORTPTR(dst8
);
216 uint16_t *src
= CONVERT_TO_SHORTPTR(src8
);
217 memcpy(dst
, src
, num
* sizeof(uint16_t));
219 #endif // CONFIG_VP9_HIGHBITDEPTH
220 #endif // CONFIG_VP9 || CONFIG_VP10
222 // Copies the source image into the destination image and updates the
223 // destination's UMV borders.
224 // Note: The frames are assumed to be identical in size.
225 void vp8_yv12_copy_frame_c(const YV12_BUFFER_CONFIG
*src_ybc
,
226 YV12_BUFFER_CONFIG
*dst_ybc
) {
228 const uint8_t *src
= src_ybc
->y_buffer
;
229 uint8_t *dst
= dst_ybc
->y_buffer
;
232 /* These assertions are valid in the codec, but the libvpx-tester uses
233 * this code slightly differently.
235 assert(src_ybc
->y_width
== dst_ybc
->y_width
);
236 assert(src_ybc
->y_height
== dst_ybc
->y_height
);
239 #if CONFIG_VP9_HIGHBITDEPTH
240 if (src_ybc
->flags
& YV12_FLAG_HIGHBITDEPTH
) {
241 assert(dst_ybc
->flags
& YV12_FLAG_HIGHBITDEPTH
);
242 for (row
= 0; row
< src_ybc
->y_height
; ++row
) {
243 memcpy_short_addr(dst
, src
, src_ybc
->y_width
);
244 src
+= src_ybc
->y_stride
;
245 dst
+= dst_ybc
->y_stride
;
248 src
= src_ybc
->u_buffer
;
249 dst
= dst_ybc
->u_buffer
;
251 for (row
= 0; row
< src_ybc
->uv_height
; ++row
) {
252 memcpy_short_addr(dst
, src
, src_ybc
->uv_width
);
253 src
+= src_ybc
->uv_stride
;
254 dst
+= dst_ybc
->uv_stride
;
257 src
= src_ybc
->v_buffer
;
258 dst
= dst_ybc
->v_buffer
;
260 for (row
= 0; row
< src_ybc
->uv_height
; ++row
) {
261 memcpy_short_addr(dst
, src
, src_ybc
->uv_width
);
262 src
+= src_ybc
->uv_stride
;
263 dst
+= dst_ybc
->uv_stride
;
266 vp8_yv12_extend_frame_borders_c(dst_ybc
);
269 assert(!(dst_ybc
->flags
& YV12_FLAG_HIGHBITDEPTH
));
273 for (row
= 0; row
< src_ybc
->y_height
; ++row
) {
274 memcpy(dst
, src
, src_ybc
->y_width
);
275 src
+= src_ybc
->y_stride
;
276 dst
+= dst_ybc
->y_stride
;
279 src
= src_ybc
->u_buffer
;
280 dst
= dst_ybc
->u_buffer
;
282 for (row
= 0; row
< src_ybc
->uv_height
; ++row
) {
283 memcpy(dst
, src
, src_ybc
->uv_width
);
284 src
+= src_ybc
->uv_stride
;
285 dst
+= dst_ybc
->uv_stride
;
288 src
= src_ybc
->v_buffer
;
289 dst
= dst_ybc
->v_buffer
;
291 for (row
= 0; row
< src_ybc
->uv_height
; ++row
) {
292 memcpy(dst
, src
, src_ybc
->uv_width
);
293 src
+= src_ybc
->uv_stride
;
294 dst
+= dst_ybc
->uv_stride
;
297 vp8_yv12_extend_frame_borders_c(dst_ybc
);
300 void vpx_yv12_copy_y_c(const YV12_BUFFER_CONFIG
*src_ybc
,
301 YV12_BUFFER_CONFIG
*dst_ybc
) {
303 const uint8_t *src
= src_ybc
->y_buffer
;
304 uint8_t *dst
= dst_ybc
->y_buffer
;
306 #if CONFIG_VP9_HIGHBITDEPTH
307 if (src_ybc
->flags
& YV12_FLAG_HIGHBITDEPTH
) {
308 const uint16_t *src16
= CONVERT_TO_SHORTPTR(src
);
309 uint16_t *dst16
= CONVERT_TO_SHORTPTR(dst
);
310 for (row
= 0; row
< src_ybc
->y_height
; ++row
) {
311 memcpy(dst16
, src16
, src_ybc
->y_width
* sizeof(uint16_t));
312 src16
+= src_ybc
->y_stride
;
313 dst16
+= dst_ybc
->y_stride
;
319 for (row
= 0; row
< src_ybc
->y_height
; ++row
) {
320 memcpy(dst
, src
, src_ybc
->y_width
);
321 src
+= src_ybc
->y_stride
;
322 dst
+= dst_ybc
->y_stride
;