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 <assert.h>
     12 
     13 #include "./vpx_config.h"
     14 #include "vpx_scale/yv12config.h"
     15 #include "vpx_mem/vpx_mem.h"
     16 
     17 #include "trace_conf.h"
     18 
     19 /****************************************************************************
     20 *  Exports
     21 ****************************************************************************/
     22 
     23 /****************************************************************************
     24  *
     25  ****************************************************************************/
     26 #define yv12_align_addr(addr, align) \
     27     (void*)(((size_t)(addr) + ((align) - 1)) & (size_t)-(align))
     28 
     29 int
     30 vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
     31   if (ybf) {
     32     // If libvpx is using frame buffer callbacks then buffer_alloc_sz must
     33     // not be set.
     34     if (ybf->buffer_alloc_sz > 0) {
     35       vpx_free(ybf->buffer_alloc);
     36     }
     37 
     38     /* buffer_alloc isn't accessed by most functions.  Rather y_buffer,
     39       u_buffer and v_buffer point to buffer_alloc and are used.  Clear out
     40       all of this so that a freed pointer isn't inadvertently used */
     41     vpx_memset(ybf, 0, sizeof(YV12_BUFFER_CONFIG));
     42   } else {
     43     return -1;
     44   }
     45 
     46   return 0;
     47 }
     48 
     49 int vp8_yv12_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
     50                                   int width, int height, int border) {
     51   if (ybf) {
     52     int aligned_width = (width + 15) & ~15;
     53     int aligned_height = (height + 15) & ~15;
     54     int y_stride = ((aligned_width + 2 * border) + 31) & ~31;
     55     int yplane_size = (aligned_height + 2 * border) * y_stride;
     56     int uv_width = aligned_width >> 1;
     57     int uv_height = aligned_height >> 1;
     58     /** There is currently a bunch of code which assumes
     59       *  uv_stride == y_stride/2, so enforce this here. */
     60     int uv_stride = y_stride >> 1;
     61     int uvplane_size = (uv_height + border) * uv_stride;
     62     const int frame_size = yplane_size + 2 * uvplane_size;
     63 
     64     if (!ybf->buffer_alloc) {
     65       ybf->buffer_alloc = (uint8_t *)vpx_memalign(32, frame_size);
     66       ybf->buffer_alloc_sz = frame_size;
     67     }
     68 
     69     if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size)
     70       return -1;
     71 
     72     /* Only support allocating buffers that have a border that's a multiple
     73      * of 32. The border restriction is required to get 16-byte alignment of
     74      * the start of the chroma rows without introducing an arbitrary gap
     75      * between planes, which would break the semantics of things like
     76      * vpx_img_set_rect(). */
     77     if (border & 0x1f)
     78       return -3;
     79 
     80     ybf->y_crop_width = width;
     81     ybf->y_crop_height = height;
     82     ybf->y_width  = aligned_width;
     83     ybf->y_height = aligned_height;
     84     ybf->y_stride = y_stride;
     85 
     86     ybf->uv_width = uv_width;
     87     ybf->uv_height = uv_height;
     88     ybf->uv_stride = uv_stride;
     89 
     90     ybf->alpha_width = 0;
     91     ybf->alpha_height = 0;
     92     ybf->alpha_stride = 0;
     93 
     94     ybf->border = border;
     95     ybf->frame_size = frame_size;
     96 
     97     ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border;
     98     ybf->u_buffer = ybf->buffer_alloc + yplane_size + (border / 2  * uv_stride) + border / 2;
     99     ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size + (border / 2  * uv_stride) + border / 2;
    100     ybf->alpha_buffer = NULL;
    101 
    102     ybf->corrupted = 0; /* assume not currupted by errors */
    103     return 0;
    104   }
    105   return -2;
    106 }
    107 
    108 int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
    109                                 int width, int height, int border) {
    110   if (ybf) {
    111     vp8_yv12_de_alloc_frame_buffer(ybf);
    112     return vp8_yv12_realloc_frame_buffer(ybf, width, height, border);
    113   }
    114   return -2;
    115 }
    116 
    117 #if CONFIG_VP9
    118 // TODO(jkoleszar): Maybe replace this with struct vpx_image
    119 
    120 int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) {
    121   if (ybf) {
    122     if (ybf->buffer_alloc_sz > 0) {
    123       vpx_free(ybf->buffer_alloc);
    124     }
    125 
    126     /* buffer_alloc isn't accessed by most functions.  Rather y_buffer,
    127       u_buffer and v_buffer point to buffer_alloc and are used.  Clear out
    128       all of this so that a freed pointer isn't inadvertently used */
    129     vpx_memset(ybf, 0, sizeof(YV12_BUFFER_CONFIG));
    130   } else {
    131     return -1;
    132   }
    133 
    134   return 0;
    135 }
    136 
    137 int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
    138                              int width, int height,
    139                              int ss_x, int ss_y, int border,
    140                              vpx_codec_frame_buffer_t *fb,
    141                              vpx_get_frame_buffer_cb_fn_t cb,
    142                              void *cb_priv) {
    143   if (ybf) {
    144     const int aligned_width = (width + 7) & ~7;
    145     //int aligned_height = (height + 7) & ~7;
    146     int aligned_height = (height + 31) & ~31;
    147     int y_stride = ((aligned_width + 2 * border) + 31) & ~31;
    148     int yplane_size = (aligned_height + 2 * border) * y_stride;
    149 
    150     const int uv_width = aligned_width >> ss_x;
    151     int uv_height = aligned_height >> ss_y;
    152     int uv_stride = y_stride >> ss_x;
    153     const int uv_border_w = border >> ss_x;
    154     const int uv_border_h = border >> ss_y;
    155     int uvplane_size = (uv_height + 2 * uv_border_h) * uv_stride;
    156 #if CONFIG_ALPHA
    157     const int alpha_width = aligned_width;
    158     int alpha_height = aligned_height;
    159     int alpha_stride = y_stride;
    160     const int alpha_border_w = border;
    161     const int alpha_border_h = border;
    162     int alpha_plane_size = (alpha_height + 2 * alpha_border_h) *
    163                                  alpha_stride;
    164     int frame_size = yplane_size + 2 * uvplane_size +
    165                            alpha_plane_size;
    166 #else
    167     int frame_size = yplane_size + 2 * uvplane_size;
    168 #endif
    169     if (cb != NULL) {
    170       const int align_addr_extra_size = 0; //31;
    171       const size_t external_frame_size = frame_size + align_addr_extra_size;
    172 
    173       assert(fb != NULL);
    174 
    175       // Allocation to hold larger frame, or first allocation.
    176       if (cb(cb_priv, external_frame_size, fb) < 0)
    177         return -1;
    178 
    179       if (fb->data == NULL || fb->size < external_frame_size)
    180         return -1;
    181 
    182       // This memset is needed for fixing valgrind error from C loop filter
    183       // due to access uninitialized memory in frame border. It could be
    184       // removed if border is totally removed.
    185       //vpx_memset(fb->data, 0, fb->size);
    186 
    187       ybf->buffer_alloc = (uint8_t *)yv12_align_addr(fb->data, 32);
    188 
    189       // extra info from external buffer
    190       ybf->fb_index = fb->fb_index;
    191       if (fb->fb_stride > 0) {
    192         if ((fb->fb_stride >= y_stride) && (fb->fb_height_stride >= aligned_height)) {
    193             // re-calculate stride/size stuff
    194             y_stride = fb->fb_stride;
    195             // external height is 32-bit align, align here either
    196             aligned_height = (aligned_height + 31) & ~31;
    197             aligned_height = fb->fb_height_stride;
    198 
    199             yplane_size = (aligned_height + 2 * border) * y_stride;
    200 
    201             uv_stride = y_stride >> ss_x;
    202             uv_height = aligned_height >> ss_y;
    203             uvplane_size = (uv_height + 2 * uv_border_h) * uv_stride;
    204 #if CONFIG_ALPHA
    205             alpha_stride = y_stride;
    206             alpha_height = aligned_height;
    207             alpha_plane_size = (alpha_height + 2 * alpha_border_h) *
    208                                     alpha_stride;
    209             frame_size = yplane_size + 2 * uvplane_size +
    210                          alpha_plane_size;
    211 #else
    212             frame_size = yplane_size + 2 * uvplane_size;
    213 #endif
    214         } else {
    215             LOGD("buffer stride get from external should not less than calculated!");
    216             return -1;
    217         }
    218       }
    219     } else if (frame_size > ybf->buffer_alloc_sz) {
    220       // Allocation to hold larger frame, or first allocation.
    221       if (ybf->buffer_alloc)
    222         vpx_free(ybf->buffer_alloc);
    223       ybf->buffer_alloc = (uint8_t *)vpx_memalign(32, frame_size);
    224       if (!ybf->buffer_alloc)
    225         return -1;
    226 
    227       ybf->buffer_alloc_sz = frame_size;
    228 
    229       // This memset is needed for fixing valgrind error from C loop filter
    230       // due to access uninitialized memory in frame border. It could be
    231       // removed if border is totally removed.
    232       //vpx_memset(ybf->buffer_alloc, 0, ybf->buffer_alloc_sz);
    233     }
    234 
    235     /* Only support allocating buffers that have a border that's a multiple
    236      * of 32. The border restriction is required to get 16-byte alignment of
    237      * the start of the chroma rows without introducing an arbitrary gap
    238      * between planes, which would break the semantics of things like
    239      * vpx_img_set_rect(). */
    240     if (border & 0x1f)
    241       return -3;
    242 
    243     ybf->y_crop_width = width;
    244     ybf->y_crop_height = height;
    245     ybf->y_width  = aligned_width;
    246     ybf->y_height = aligned_height;
    247     ybf->y_stride = y_stride;
    248 
    249     ybf->uv_crop_width = (width + ss_x) >> ss_x;
    250     ybf->uv_crop_height = (height + ss_y) >> ss_y;
    251     ybf->uv_width = uv_width;
    252     ybf->uv_height = uv_height;
    253     ybf->uv_stride = uv_stride;
    254 
    255     ybf->border = border;
    256     ybf->frame_size = frame_size;
    257 
    258     ybf->y_buffer = ybf->buffer_alloc + (border * y_stride) + border;
    259     ybf->v_buffer = ybf->buffer_alloc + yplane_size +
    260                     (uv_border_h * uv_stride) + uv_border_w;
    261     ybf->u_buffer = ybf->buffer_alloc + yplane_size + uvplane_size +
    262                     (uv_border_h * uv_stride) + uv_border_w;
    263 
    264 #if CONFIG_ALPHA
    265     ybf->alpha_width = alpha_width;
    266     ybf->alpha_height = alpha_height;
    267     ybf->alpha_stride = alpha_stride;
    268     ybf->alpha_buffer = ybf->buffer_alloc + yplane_size + 2 * uvplane_size +
    269                         (alpha_border_h * alpha_stride) + alpha_border_w;
    270 #endif
    271     ybf->corrupted = 0; /* assume not corrupted by errors */
    272     return 0;
    273   }
    274   return -2;
    275 }
    276 
    277 int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
    278                            int width, int height,
    279                            int ss_x, int ss_y, int border) {
    280   if (ybf) {
    281     vp9_free_frame_buffer(ybf);
    282     return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border,
    283                                     NULL, NULL, NULL);
    284   }
    285   return -2;
    286 }
    287 #endif
    288