diff options
author | Frank Galligan <fgalligan@google.com> | 2013-12-11 09:06:35 -0800 |
---|---|---|
committer | Frank Galligan <fgalligan@google.com> | 2013-12-15 18:45:46 -0800 |
commit | 10f891696bc4c972c13cc9fde2c53470501a03e2 (patch) | |
tree | 21d8f81ea2df7408f5e1e16e547c2113d0c99012 /vpx_scale | |
parent | 52b2d50db4d194b7484e8ca0bec4c8c71bf94eaa (diff) | |
download | libvpx-10f891696bc4c972c13cc9fde2c53470501a03e2.tar.gz libvpx-10f891696bc4c972c13cc9fde2c53470501a03e2.tar.bz2 libvpx-10f891696bc4c972c13cc9fde2c53470501a03e2.zip |
Add support to pass in external frame buffers.
VP9 decoder can now use frame buffers passed in by the application.
Change-Id: I599527ec85c577f3f5552831d79a693884fafb73
Diffstat (limited to 'vpx_scale')
-rw-r--r-- | vpx_scale/generic/yv12config.c | 57 | ||||
-rw-r--r-- | vpx_scale/yv12config.h | 14 |
2 files changed, 59 insertions, 12 deletions
diff --git a/vpx_scale/generic/yv12config.c b/vpx_scale/generic/yv12config.c index 7c3f7ece9..a020e19b7 100644 --- a/vpx_scale/generic/yv12config.c +++ b/vpx_scale/generic/yv12config.c @@ -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 vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, 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_free_frame_buffer(YV12_BUFFER_CONFIG *ybf) { 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,15 +161,36 @@ int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, #else const int frame_size = yplane_size + 2 * uvplane_size; #endif - 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 (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 @@ -206,7 +240,8 @@ int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, 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; } diff --git a/vpx_scale/yv12config.h b/vpx_scale/yv12config.h index 0e950fb14..f23e1163c 100644 --- a/vpx_scale/yv12config.h +++ b/vpx_scale/yv12config.h @@ -15,6 +15,7 @@ extern "C" { #endif +#include "vpx/vpx_external_frame_buffer.h" #include "vpx/vpx_integer.h" #define VP8BORDERINPIXELS 32 @@ -64,9 +65,20 @@ extern "C" { int vp9_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int ss_x, int ss_y, int border); + + // Updates the yv12 buffer config with the frame buffer. If ext_fb is not + // NULL then libvpx is using external frame buffers. The function will + // check if the frame buffer is big enough to fit the decoded frame and + // try to reallocate the frame buffer. If ext_fb is not NULL and the frame + // buffer is not big enough libvpx will call cb with minimum size in bytes. + // + // Returns 0 on success. Returns < 0 on failure. int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int ss_x, int ss_y, - int border); + int border, + vpx_codec_frame_buffer_t *ext_fb, + vpx_realloc_frame_buffer_cb_fn_t cb, + void *user_priv); int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf); #ifdef __cplusplus |