Index: source/libvpx/vpx_scale/generic/yv12config.c |
=================================================================== |
--- source/libvpx/vpx_scale/generic/yv12config.c (revision 240950) |
+++ source/libvpx/vpx_scale/generic/yv12config.c (working copy) |
@@ -19,10 +19,18 @@ |
/**************************************************************************** |
* |
****************************************************************************/ |
+ |
+#define yv12_align_addr(addr, align) \ |
+ (void*)(((size_t)(addr) + ((align) - 1)) & (size_t)-(align)) |
+ |
int |
vp8_yv12_de_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf) { |
if (ybf) { |
- vpx_free(ybf->buffer_alloc); |
+ // If libvpx is using external frame buffers then buffer_alloc_sz must |
+ // not be set. |
+ if (ybf->buffer_alloc_sz > 0) { |
+ vpx_free(ybf->buffer_alloc); |
+ } |
/* buffer_alloc isn't accessed by most functions. Rather y_buffer, |
u_buffer and v_buffer point to buffer_alloc and are used. Clear out |
@@ -108,7 +116,9 @@ |
int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) { |
if (ybf) { |
- vpx_free(ybf->buffer_alloc); |
+ if (ybf->buffer_alloc_sz > 0) { |
+ vpx_free(ybf->buffer_alloc); |
+ } |
/* buffer_alloc isn't accessed by most functions. Rather y_buffer, |
u_buffer and v_buffer point to buffer_alloc and are used. Clear out |
@@ -123,7 +133,10 @@ |
int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, |
int width, int height, |
- int ss_x, int ss_y, int border) { |
+ int ss_x, int ss_y, int border, |
+ vpx_codec_frame_buffer_t *ext_fb, |
+ vpx_realloc_frame_buffer_cb_fn_t cb, |
+ void *user_priv) { |
if (ybf) { |
const int aligned_width = (width + 7) & ~7; |
const int aligned_height = (height + 7) & ~7; |
@@ -148,12 +161,36 @@ |
#else |
const int frame_size = yplane_size + 2 * uvplane_size; |
#endif |
- if (!ybf->buffer_alloc) { |
- ybf->buffer_alloc = vpx_memalign(32, frame_size); |
- ybf->buffer_alloc_sz = frame_size; |
+ |
+ if (ext_fb != NULL) { |
+ const int align_addr_extra_size = 31; |
+ const int external_frame_size = frame_size + align_addr_extra_size; |
+ if (external_frame_size > ext_fb->size) { |
+ // Allocation to hold larger frame, or first allocation. |
+ if (cb(user_priv, external_frame_size, ext_fb) < 0) { |
+ return -1; |
+ } |
+ |
+ if (ext_fb->data == NULL || ext_fb->size < external_frame_size) { |
+ return -1; |
+ } |
+ |
+ ybf->buffer_alloc = yv12_align_addr(ext_fb->data, 32); |
+ } |
+ } else { |
+ if (frame_size > ybf->buffer_alloc_sz) { |
+ // Allocation to hold larger frame, or first allocation. |
+ if (ybf->buffer_alloc) |
+ vpx_free(ybf->buffer_alloc); |
+ ybf->buffer_alloc = vpx_memalign(32, frame_size); |
+ ybf->buffer_alloc_sz = frame_size; |
+ } |
+ |
+ if (ybf->buffer_alloc_sz < frame_size) |
+ return -1; |
} |
- if (!ybf->buffer_alloc || ybf->buffer_alloc_sz < frame_size) |
+ if (!ybf->buffer_alloc) |
return -1; |
/* Only support allocating buffers that have a border that's a multiple |
@@ -203,7 +240,8 @@ |
int ss_x, int ss_y, int border) { |
if (ybf) { |
vp9_free_frame_buffer(ybf); |
- return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border); |
+ return vp9_realloc_frame_buffer(ybf, width, height, ss_x, ss_y, border, |
+ NULL, NULL, NULL); |
} |
return -2; |
} |