yv12extend.c revision 91037db265ecdd914a26e056cf69207b4f50924e
1/*
2 *  Copyright (c) 2010 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 <assert.h>
12#include "./vpx_config.h"
13#include "vpx_scale/yv12config.h"
14#include "vpx_mem/vpx_mem.h"
15#include "vpx_scale/vpx_scale.h"
16
17/****************************************************************************
18*  Exports
19****************************************************************************/
20
21/****************************************************************************
22 *
23 ****************************************************************************/
24static void extend_plane(uint8_t *s,       /* source */
25                         int sp,           /* source pitch */
26                         int w,            /* width */
27                         int h,            /* height */
28                         int et,           /* extend top border */
29                         int el,           /* extend left border */
30                         int eb,           /* extend bottom border */
31                         int er) {         /* extend right border */
32  int i;
33  uint8_t *src_ptr1, *src_ptr2;
34  uint8_t *dest_ptr1, *dest_ptr2;
35  int linesize;
36
37  /* copy the left and right most columns out */
38  src_ptr1 = s;
39  src_ptr2 = s + w - 1;
40  dest_ptr1 = s - el;
41  dest_ptr2 = s + w;
42
43  for (i = 0; i < h; i++) {
44    vpx_memset(dest_ptr1, src_ptr1[0], el);
45    vpx_memset(dest_ptr2, src_ptr2[0], er);
46    src_ptr1  += sp;
47    src_ptr2  += sp;
48    dest_ptr1 += sp;
49    dest_ptr2 += sp;
50  }
51
52  /* Now copy the top and bottom lines into each line of the respective
53   * borders
54   */
55  src_ptr1 = s - el;
56  src_ptr2 = s + sp * (h - 1) - el;
57  dest_ptr1 = s + sp * (-et) - el;
58  dest_ptr2 = s + sp * (h) - el;
59  linesize = el + er + w;
60
61  for (i = 0; i < et; i++) {
62    vpx_memcpy(dest_ptr1, src_ptr1, linesize);
63    dest_ptr1 += sp;
64  }
65
66  for (i = 0; i < eb; i++) {
67    vpx_memcpy(dest_ptr2, src_ptr2, linesize);
68    dest_ptr2 += sp;
69  }
70}
71
72void
73vp8_yv12_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf) {
74  assert(ybf->y_height - ybf->y_crop_height < 16);
75  assert(ybf->y_width - ybf->y_crop_width < 16);
76  assert(ybf->y_height - ybf->y_crop_height >= 0);
77  assert(ybf->y_width - ybf->y_crop_width >= 0);
78
79  extend_plane(ybf->y_buffer, ybf->y_stride,
80               ybf->y_crop_width, ybf->y_crop_height,
81               ybf->border, ybf->border,
82               ybf->border + ybf->y_height - ybf->y_crop_height,
83               ybf->border + ybf->y_width - ybf->y_crop_width);
84
85  extend_plane(ybf->u_buffer, ybf->uv_stride,
86               (ybf->y_crop_width + 1) / 2, (ybf->y_crop_height + 1) / 2,
87               ybf->border / 2, ybf->border / 2,
88               (ybf->border + ybf->y_height - ybf->y_crop_height + 1) / 2,
89               (ybf->border + ybf->y_width - ybf->y_crop_width + 1) / 2);
90
91  extend_plane(ybf->v_buffer, ybf->uv_stride,
92               (ybf->y_crop_width + 1) / 2, (ybf->y_crop_height + 1) / 2,
93               ybf->border / 2, ybf->border / 2,
94               (ybf->border + ybf->y_height - ybf->y_crop_height + 1) / 2,
95               (ybf->border + ybf->y_width - ybf->y_crop_width + 1) / 2);
96}
97
98#if CONFIG_VP9
99static void extend_frame(YV12_BUFFER_CONFIG *ybf,
100                        int subsampling_x, int subsampling_y,
101                        int ext_size) {
102  const int c_w = (ybf->y_crop_width + subsampling_x) >> subsampling_x;
103  const int c_h = (ybf->y_crop_height + subsampling_y) >> subsampling_y;
104  const int c_et = ext_size >> subsampling_y;
105  const int c_el = ext_size >> subsampling_x;
106  const int c_eb = (ext_size + ybf->y_height - ybf->y_crop_height +
107                    subsampling_y) >> subsampling_y;
108  const int c_er = (ext_size + ybf->y_width - ybf->y_crop_width +
109                    subsampling_x) >> subsampling_x;
110
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);
115
116  extend_plane(ybf->y_buffer, ybf->y_stride,
117               ybf->y_crop_width, ybf->y_crop_height,
118               ext_size, ext_size,
119               ext_size + ybf->y_height - ybf->y_crop_height,
120               ext_size + ybf->y_width - ybf->y_crop_width);
121
122  extend_plane(ybf->u_buffer, ybf->uv_stride,
123               c_w, c_h, c_et, c_el, c_eb, c_er);
124
125  extend_plane(ybf->v_buffer, ybf->uv_stride,
126               c_w, c_h, c_et, c_el, c_eb, c_er);
127}
128
129
130void vp9_extend_frame_borders_c(YV12_BUFFER_CONFIG *ybf,
131                                int subsampling_x, int subsampling_y) {
132  extend_frame(ybf, subsampling_x, subsampling_y, ybf->border);
133}
134
135void vp9_extend_frame_inner_borders_c(YV12_BUFFER_CONFIG *ybf,
136                                      int subsampling_x, int subsampling_y) {
137  const int inner_bw = ybf->border > VP9INNERBORDERINPIXLES ?
138                       VP9INNERBORDERINPIXLES : ybf->border;
139  extend_frame(ybf, subsampling_x, subsampling_y, inner_bw);
140}
141#endif
142
143/****************************************************************************
144 *
145 *  ROUTINE       : vp8_yv12_copy_frame
146 *
147 *  INPUTS        :
148 *
149 *  OUTPUTS       : None.
150 *
151 *  RETURNS       : void
152 *
153 *  FUNCTION      : Copies the source image into the destination image and
154 *                  updates the destination's UMV borders.
155 *
156 *  SPECIAL NOTES : The frames are assumed to be identical in size.
157 *
158 ****************************************************************************/
159void
160vp8_yv12_copy_frame_c(YV12_BUFFER_CONFIG *src_ybc,
161                      YV12_BUFFER_CONFIG *dst_ybc) {
162  int row;
163  unsigned char *source, *dest;
164
165#if 0
166  /* These assertions are valid in the codec, but the libvpx-tester uses
167   * this code slightly differently.
168   */
169  assert(src_ybc->y_width == dst_ybc->y_width);
170  assert(src_ybc->y_height == dst_ybc->y_height);
171#endif
172
173  source = src_ybc->y_buffer;
174  dest = dst_ybc->y_buffer;
175
176  for (row = 0; row < src_ybc->y_height; row++) {
177    vpx_memcpy(dest, source, src_ybc->y_width);
178    source += src_ybc->y_stride;
179    dest   += dst_ybc->y_stride;
180  }
181
182  source = src_ybc->u_buffer;
183  dest = dst_ybc->u_buffer;
184
185  for (row = 0; row < src_ybc->uv_height; row++) {
186    vpx_memcpy(dest, source, src_ybc->uv_width);
187    source += src_ybc->uv_stride;
188    dest   += dst_ybc->uv_stride;
189  }
190
191  source = src_ybc->v_buffer;
192  dest = dst_ybc->v_buffer;
193
194  for (row = 0; row < src_ybc->uv_height; row++) {
195    vpx_memcpy(dest, source, src_ybc->uv_width);
196    source += src_ybc->uv_stride;
197    dest   += dst_ybc->uv_stride;
198  }
199
200  vp8_yv12_extend_frame_borders_c(dst_ybc);
201}
202
203void vp8_yv12_copy_y_c(YV12_BUFFER_CONFIG *src_ybc,
204                       YV12_BUFFER_CONFIG *dst_ybc) {
205  int row;
206  unsigned char *source, *dest;
207
208
209  source = src_ybc->y_buffer;
210  dest = dst_ybc->y_buffer;
211
212  for (row = 0; row < src_ybc->y_height; row++) {
213    vpx_memcpy(dest, source, src_ybc->y_width);
214    source += src_ybc->y_stride;
215    dest   += dst_ybc->y_stride;
216  }
217}
218