11b362b15af34006e6a11974088a46d42b903418eJohann/*
21b362b15af34006e6a11974088a46d42b903418eJohann *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
31b362b15af34006e6a11974088a46d42b903418eJohann *
41b362b15af34006e6a11974088a46d42b903418eJohann *  Use of this source code is governed by a BSD-style license
51b362b15af34006e6a11974088a46d42b903418eJohann *  that can be found in the LICENSE file in the root of the source
61b362b15af34006e6a11974088a46d42b903418eJohann *  tree. An additional intellectual property rights grant can be found
71b362b15af34006e6a11974088a46d42b903418eJohann *  in the file PATENTS.  All contributing project authors may
81b362b15af34006e6a11974088a46d42b903418eJohann *  be found in the AUTHORS file in the root of the source tree.
91b362b15af34006e6a11974088a46d42b903418eJohann */
101b362b15af34006e6a11974088a46d42b903418eJohann
11ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "./vpx_config.h"
121b362b15af34006e6a11974088a46d42b903418eJohann#include "vpx_scale/yv12config.h"
131b362b15af34006e6a11974088a46d42b903418eJohann#include "vpx_mem/vpx_mem.h"
141b362b15af34006e6a11974088a46d42b903418eJohann
151b362b15af34006e6a11974088a46d42b903418eJohann/****************************************************************************
161b362b15af34006e6a11974088a46d42b903418eJohann*  Exports
171b362b15af34006e6a11974088a46d42b903418eJohann****************************************************************************/
181b362b15af34006e6a11974088a46d42b903418eJohann
191b362b15af34006e6a11974088a46d42b903418eJohann/****************************************************************************
201b362b15af34006e6a11974088a46d42b903418eJohann *
211b362b15af34006e6a11974088a46d42b903418eJohann ****************************************************************************/
221b362b15af34006e6a11974088a46d42b903418eJohannint
231b362b15af34006e6a11974088a46d42b903418eJohannvp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
241b362b15af34006e6a11974088a46d42b903418eJohann  if (ybf) {
251b362b15af34006e6a11974088a46d42b903418eJohann    vpx_free(ybf->buffer_alloc);
261b362b15af34006e6a11974088a46d42b903418eJohann
271b362b15af34006e6a11974088a46d42b903418eJohann    /* buffer_alloc isn't accessed by most functions.  Rather y_buffer,
281b362b15af34006e6a11974088a46d42b903418eJohann      u_buffer and v_buffer point to buffer_alloc and are used.  Clear out
291b362b15af34006e6a11974088a46d42b903418eJohann      all of this so that a freed pointer isn't inadvertently used */
301b362b15af34006e6a11974088a46d42b903418eJohann    vpx_memset(ybf, 0, sizeof(YV12_BUFFER_CONFIG));
311b362b15af34006e6a11974088a46d42b903418eJohann  } else {
321b362b15af34006e6a11974088a46d42b903418eJohann    return -1;
331b362b15af34006e6a11974088a46d42b903418eJohann  }
341b362b15af34006e6a11974088a46d42b903418eJohann
351b362b15af34006e6a11974088a46d42b903418eJohann  return 0;
361b362b15af34006e6a11974088a46d42b903418eJohann}
371b362b15af34006e6a11974088a46d42b903418eJohann
38ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangint vp8_yv12_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
39ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                  int width, int height, int border) {
401b362b15af34006e6a11974088a46d42b903418eJohann  if (ybf) {
41ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    int aligned_width = (width + 15) & ~15;
42ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    int aligned_height = (height + 15) & ~15;
43ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    int y_stride = ((aligned_width + 2 * border) + 31) & ~31;
44ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    int yplane_size = (aligned_height + 2 * border) * y_stride;
45ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    int uv_width = aligned_width >> 1;
46ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    int uv_height = aligned_height >> 1;
471b362b15af34006e6a11974088a46d42b903418eJohann    /** There is currently a bunch of code which assumes
481b362b15af34006e6a11974088a46d42b903418eJohann      *  uv_stride == y_stride/2, so enforce this here. */
491b362b15af34006e6a11974088a46d42b903418eJohann    int uv_stride = y_stride >> 1;
501b362b15af34006e6a11974088a46d42b903418eJohann    int uvplane_size = (uv_height + border) * uv_stride;
51ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int frame_size = yplane_size + 2 * uvplane_size;
521b362b15af34006e6a11974088a46d42b903418eJohann
53ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (!ybf->buffer_alloc) {
54ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ybf->buffer_alloc = vpx_memalign(32, frame_size);
55ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ybf->buffer_alloc_sz = frame_size;
56ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
571b362b15af34006e6a11974088a46d42b903418eJohann
58ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size)
59ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return -1;
60ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
61ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    /* Only support allocating buffers that have a border that's a multiple
62ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang     * of 32. The border restriction is required to get 16-byte alignment of
63f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang     * the start of the chroma rows without introducing an arbitrary gap
64ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang     * between planes, which would break the semantics of things like
65ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang     * vpx_img_set_rect(). */
66ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (border & 0x1f)
671b362b15af34006e6a11974088a46d42b903418eJohann      return -3;
681b362b15af34006e6a11974088a46d42b903418eJohann
69ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->y_crop_width = width;
70ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->y_crop_height = height;
71ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->y_width  = aligned_width;
72ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->y_height = aligned_height;
731b362b15af34006e6a11974088a46d42b903418eJohann    ybf->y_stride = y_stride;
741b362b15af34006e6a11974088a46d42b903418eJohann
751b362b15af34006e6a11974088a46d42b903418eJohann    ybf->uv_width = uv_width;
761b362b15af34006e6a11974088a46d42b903418eJohann    ybf->uv_height = uv_height;
771b362b15af34006e6a11974088a46d42b903418eJohann    ybf->uv_stride = uv_stride;
781b362b15af34006e6a11974088a46d42b903418eJohann
79ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->alpha_width = 0;
80ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->alpha_height = 0;
81ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->alpha_stride = 0;
821b362b15af34006e6a11974088a46d42b903418eJohann
83ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->border = border;
84ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->frame_size = frame_size;
851b362b15af34006e6a11974088a46d42b903418eJohann
861b362b15af34006e6a11974088a46d42b903418eJohann    ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border;
871b362b15af34006e6a11974088a46d42b903418eJohann    ybf->u_buffer = ybf->buffer_alloc + yplane_size + (border / 2  * uv_stride) + border / 2;
881b362b15af34006e6a11974088a46d42b903418eJohann    ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size + (border / 2  * uv_stride) + border / 2;
89ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->alpha_buffer = NULL;
901b362b15af34006e6a11974088a46d42b903418eJohann
911b362b15af34006e6a11974088a46d42b903418eJohann    ybf->corrupted = 0; /* assume not currupted by errors */
92ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return 0;
93ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
94ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return -2;
95ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
96ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
97ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangint vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
98ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                int width, int height, int border) {
99ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (ybf) {
100ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    vp8_yv12_de_alloc_frame_buffer(ybf);
101ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return vp8_yv12_realloc_frame_buffer(ybf, width, height, border);
102ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
103ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return -2;
104ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
105ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
106ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#if CONFIG_VP9
107ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang// TODO(jkoleszar): Maybe replace this with struct vpx_image
108ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
109ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangint vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
110ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (ybf) {
111ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    vpx_free(ybf->buffer_alloc);
112ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
113ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    /* buffer_alloc isn't accessed by most functions.  Rather y_buffer,
114ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      u_buffer and v_buffer point to buffer_alloc and are used.  Clear out
115ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      all of this so that a freed pointer isn't inadvertently used */
116ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    vpx_memset(ybf, 0, sizeof(YV12_BUFFER_CONFIG));
1171b362b15af34006e6a11974088a46d42b903418eJohann  } else {
118ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return -1;
1191b362b15af34006e6a11974088a46d42b903418eJohann  }
1201b362b15af34006e6a11974088a46d42b903418eJohann
1211b362b15af34006e6a11974088a46d42b903418eJohann  return 0;
1221b362b15af34006e6a11974088a46d42b903418eJohann}
123ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
124ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangint vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
125ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                             int width, int height,
126ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                             int ss_x, int ss_y, int border) {
127ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (ybf) {
128ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int aligned_width = (width + 7) & ~7;
129ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int aligned_height = (height + 7) & ~7;
130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int y_stride = ((aligned_width + 2 * border) + 31) & ~31;
131ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int yplane_size = (aligned_height + 2 * border) * y_stride;
132ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int uv_width = aligned_width >> ss_x;
133ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int uv_height = aligned_height >> ss_y;
134ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int uv_stride = y_stride >> ss_x;
135ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int uv_border_w = border >> ss_x;
136ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int uv_border_h = border >> ss_y;
137ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int uvplane_size = (uv_height + 2 * uv_border_h) * uv_stride;
138ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#if CONFIG_ALPHA
139ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int alpha_width = aligned_width;
140ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int alpha_height = aligned_height;
141ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int alpha_stride = y_stride;
142ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int alpha_border_w = border;
143ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int alpha_border_h = border;
144ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int alpha_plane_size = (alpha_height + 2 * alpha_border_h) *
145ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                                 alpha_stride;
146ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int frame_size = yplane_size + 2 * uvplane_size +
147ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                           alpha_plane_size;
148ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#else
149ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    const int frame_size = yplane_size + 2 * uvplane_size;
150ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif
151ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (!ybf->buffer_alloc) {
152ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ybf->buffer_alloc = vpx_memalign(32, frame_size);
153ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      ybf->buffer_alloc_sz = frame_size;
154ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    }
155ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
156ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size)
157ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return -1;
158ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
159ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    /* Only support allocating buffers that have a border that's a multiple
160ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang     * of 32. The border restriction is required to get 16-byte alignment of
161f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang     * the start of the chroma rows without introducing an arbitrary gap
162ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang     * between planes, which would break the semantics of things like
163ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang     * vpx_img_set_rect(). */
164ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    if (border & 0x1f)
165ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang      return -3;
166ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
167ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->y_crop_width = width;
168ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->y_crop_height = height;
169ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->y_width  = aligned_width;
170ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->y_height = aligned_height;
171ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->y_stride = y_stride;
172ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
17391037db265ecdd914a26e056cf69207b4f50924ehkuang    ybf->uv_crop_width = (width + ss_x) >> ss_x;
17491037db265ecdd914a26e056cf69207b4f50924ehkuang    ybf->uv_crop_height = (height + ss_y) >> ss_y;
175ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->uv_width = uv_width;
176ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->uv_height = uv_height;
177ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->uv_stride = uv_stride;
178ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
179ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->border = border;
180ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->frame_size = frame_size;
181ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
182ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border;
183ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->u_buffer = ybf->buffer_alloc + yplane_size +
184ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                    (uv_border_h * uv_stride) + uv_border_w;
185ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size +
186ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                    (uv_border_h * uv_stride) + uv_border_w;
187ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
188ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#if CONFIG_ALPHA
189ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->alpha_width = alpha_width;
190ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->alpha_height = alpha_height;
191ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->alpha_stride = alpha_stride;
192ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    ybf->alpha_buffer = ybf->buffer_alloc + yplane_size + 2 * uvplane_size +
193ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                        (alpha_border_h * alpha_stride) + alpha_border_w;
194ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif
1951184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    ybf->corrupted = 0; /* assume not corrupted by errors */
196ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return 0;
197ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
198ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return -2;
199ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
200ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
201ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangint vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
202ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                           int width, int height,
203ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                           int ss_x, int ss_y, int border) {
204ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (ybf) {
205ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    vp9_free_frame_buffer(ybf);
206ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border);
207ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
208ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return -2;
209ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
210ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#endif
211