Home | History | Annotate | Download | only in generic
      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 "./vpx_config.h"
     12 #include "vpx_scale/yv12config.h"
     13 #include "vpx_mem/vpx_mem.h"
     14 
     15 /****************************************************************************
     16 *  Exports
     17 ****************************************************************************/
     18 
     19 /****************************************************************************
     20  *
     21  ****************************************************************************/
     22 int
     23 vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
     24   if (ybf) {
     25     vpx_free(ybf->buffer_alloc);
     26 
     27     /* buffer_alloc isn't accessed by most functions.  Rather y_buffer,
     28       u_buffer and v_buffer point to buffer_alloc and are used.  Clear out
     29       all of this so that a freed pointer isn't inadvertently used */
     30     vpx_memset(ybf, 0, sizeof(YV12_BUFFER_CONFIG));
     31   } else {
     32     return -1;
     33   }
     34 
     35   return 0;
     36 }
     37 
     38 int vp8_yv12_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
     39                                   int width, int height, int border) {
     40   if (ybf) {
     41     int aligned_width = (width + 15) & ~15;
     42     int aligned_height = (height + 15) & ~15;
     43     int y_stride = ((aligned_width + 2 * border) + 31) & ~31;
     44     int yplane_size = (aligned_height + 2 * border) * y_stride;
     45     int uv_width = aligned_width >> 1;
     46     int uv_height = aligned_height >> 1;
     47     /** There is currently a bunch of code which assumes
     48       *  uv_stride == y_stride/2, so enforce this here. */
     49     int uv_stride = y_stride >> 1;
     50     int uvplane_size = (uv_height + border) * uv_stride;
     51     const int frame_size = yplane_size + 2 * uvplane_size;
     52 
     53     if (!ybf->buffer_alloc) {
     54       ybf->buffer_alloc = vpx_memalign(32, frame_size);
     55       ybf->buffer_alloc_sz = frame_size;
     56     }
     57 
     58     if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size)
     59       return -1;
     60 
     61     /* Only support allocating buffers that have a border that's a multiple
     62      * of 32. The border restriction is required to get 16-byte alignment of
     63      * the start of the chroma rows without introducing an arbitrary gap
     64      * between planes, which would break the semantics of things like
     65      * vpx_img_set_rect(). */
     66     if (border & 0x1f)
     67       return -3;
     68 
     69     ybf->y_crop_width = width;
     70     ybf->y_crop_height = height;
     71     ybf->y_width  = aligned_width;
     72     ybf->y_height = aligned_height;
     73     ybf->y_stride = y_stride;
     74 
     75     ybf->uv_width = uv_width;
     76     ybf->uv_height = uv_height;
     77     ybf->uv_stride = uv_stride;
     78 
     79     ybf->alpha_width = 0;
     80     ybf->alpha_height = 0;
     81     ybf->alpha_stride = 0;
     82 
     83     ybf->border = border;
     84     ybf->frame_size = frame_size;
     85 
     86     ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border;
     87     ybf->u_buffer = ybf->buffer_alloc + yplane_size + (border / 2  * uv_stride) + border / 2;
     88     ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size + (border / 2  * uv_stride) + border / 2;
     89     ybf->alpha_buffer = NULL;
     90 
     91     ybf->corrupted = 0; /* assume not currupted by errors */
     92     return 0;
     93   }
     94   return -2;
     95 }
     96 
     97 int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
     98                                 int width, int height, int border) {
     99   if (ybf) {
    100     vp8_yv12_de_alloc_frame_buffer(ybf);
    101     return vp8_yv12_realloc_frame_buffer(ybf, width, height, border);
    102   }
    103   return -2;
    104 }
    105 
    106 #if CONFIG_VP9
    107 // TODO(jkoleszar): Maybe replace this with struct vpx_image
    108 
    109 int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
    110   if (ybf) {
    111     vpx_free(ybf->buffer_alloc);
    112 
    113     /* buffer_alloc isn't accessed by most functions.  Rather y_buffer,
    114       u_buffer and v_buffer point to buffer_alloc and are used.  Clear out
    115       all of this so that a freed pointer isn't inadvertently used */
    116     vpx_memset(ybf, 0, sizeof(YV12_BUFFER_CONFIG));
    117   } else {
    118     return -1;
    119   }
    120 
    121   return 0;
    122 }
    123 
    124 int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
    125                              int width, int height,
    126                              int ss_x, int ss_y, int border) {
    127   if (ybf) {
    128     const int aligned_width = (width + 7) & ~7;
    129     const int aligned_height = (height + 7) & ~7;
    130     const int y_stride = ((aligned_width + 2 * border) + 31) & ~31;
    131     const int yplane_size = (aligned_height + 2 * border) * y_stride;
    132     const int uv_width = aligned_width >> ss_x;
    133     const int uv_height = aligned_height >> ss_y;
    134     const int uv_stride = y_stride >> ss_x;
    135     const int uv_border_w = border >> ss_x;
    136     const int uv_border_h = border >> ss_y;
    137     const int uvplane_size = (uv_height + 2 * uv_border_h) * uv_stride;
    138 #if CONFIG_ALPHA
    139     const int alpha_width = aligned_width;
    140     const int alpha_height = aligned_height;
    141     const int alpha_stride = y_stride;
    142     const int alpha_border_w = border;
    143     const int alpha_border_h = border;
    144     const int alpha_plane_size = (alpha_height + 2 * alpha_border_h) *
    145                                  alpha_stride;
    146     const int frame_size = yplane_size + 2 * uvplane_size +
    147                            alpha_plane_size;
    148 #else
    149     const int frame_size = yplane_size + 2 * uvplane_size;
    150 #endif
    151     if (frame_size > ybf->buffer_alloc_sz) {
    152       // Allocation to hold larger frame, or first allocation.
    153       if (ybf->buffer_alloc)
    154         vpx_free(ybf->buffer_alloc);
    155       ybf->buffer_alloc = vpx_memalign(32, frame_size);
    156       ybf->buffer_alloc_sz = frame_size;
    157     }
    158 
    159     if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size)
    160       return -1;
    161 
    162     /* Only support allocating buffers that have a border that's a multiple
    163      * of 32. The border restriction is required to get 16-byte alignment of
    164      * the start of the chroma rows without introducing an arbitrary gap
    165      * between planes, which would break the semantics of things like
    166      * vpx_img_set_rect(). */
    167     if (border & 0x1f)
    168       return -3;
    169 
    170     ybf->y_crop_width = width;
    171     ybf->y_crop_height = height;
    172     ybf->y_width  = aligned_width;
    173     ybf->y_height = aligned_height;
    174     ybf->y_stride = y_stride;
    175 
    176     ybf->uv_crop_width = (width + ss_x) >> ss_x;
    177     ybf->uv_crop_height = (height + ss_y) >> ss_y;
    178     ybf->uv_width = uv_width;
    179     ybf->uv_height = uv_height;
    180     ybf->uv_stride = uv_stride;
    181 
    182     ybf->border = border;
    183     ybf->frame_size = frame_size;
    184 
    185     ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border;
    186     ybf->u_buffer = ybf->buffer_alloc + yplane_size +
    187                     (uv_border_h * uv_stride) + uv_border_w;
    188     ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size +
    189                     (uv_border_h * uv_stride) + uv_border_w;
    190 
    191 #if CONFIG_ALPHA
    192     ybf->alpha_width = alpha_width;
    193     ybf->alpha_height = alpha_height;
    194     ybf->alpha_stride = alpha_stride;
    195     ybf->alpha_buffer = ybf->buffer_alloc + yplane_size + 2 * uvplane_size +
    196                         (alpha_border_h * alpha_stride) + alpha_border_w;
    197 #endif
    198     ybf->corrupted = 0; /* assume not corrupted by errors */
    199     return 0;
    200   }
    201   return -2;
    202 }
    203 
    204 int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
    205                            int width, int height,
    206                            int ss_x, int ss_y, int border) {
    207   if (ybf) {
    208     vp9_free_frame_buffer(ybf);
    209     return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border);
    210   }
    211   return -2;
    212 }
    213 #endif
    214