diff options
author | Frank Galligan <fgalligan@google.com> | 2014-02-11 08:19:37 -0800 |
---|---|---|
committer | Gerrit Code Review <gerrit@gerrit.golo.chromium.org> | 2014-02-11 08:19:37 -0800 |
commit | d51ca0db00104fb708482095816b75e6e64d9862 (patch) | |
tree | 5291b2721668ed4f3b4c275617a2ff0fd63615ca | |
parent | 803a5c67ddc139cb691704cbaf008f2d6cd1ba1f (diff) | |
parent | e8e152799be60b5bc070c6b115df12a6c1e3b176 (diff) | |
download | libvpx-d51ca0db00104fb708482095816b75e6e64d9862.tar libvpx-d51ca0db00104fb708482095816b75e6e64d9862.tar.gz libvpx-d51ca0db00104fb708482095816b75e6e64d9862.tar.bz2 libvpx-d51ca0db00104fb708482095816b75e6e64d9862.zip |
Merge "Add get release decoder frame buffer functions."
-rw-r--r-- | libs.mk | 1 | ||||
-rw-r--r-- | vp9/common/vp9_alloccommon.c | 12 | ||||
-rw-r--r-- | vp9/common/vp9_frame_buffers.c | 84 | ||||
-rw-r--r-- | vp9/common/vp9_frame_buffers.h | 53 | ||||
-rw-r--r-- | vp9/common/vp9_onyxc_int.h | 10 | ||||
-rw-r--r-- | vp9/decoder/vp9_decodeframe.c | 13 | ||||
-rw-r--r-- | vp9/decoder/vp9_onyxd_if.c | 7 | ||||
-rw-r--r-- | vp9/encoder/vp9_onyx_if.c | 10 | ||||
-rw-r--r-- | vp9/vp9_common.mk | 2 | ||||
-rw-r--r-- | vp9/vp9_dx_iface.c | 17 | ||||
-rw-r--r-- | vpx/vpx_codec.mk | 2 | ||||
-rw-r--r-- | vpx/vpx_frame_buffer.h | 74 | ||||
-rw-r--r-- | vpx_scale/generic/yv12config.c | 49 | ||||
-rw-r--r-- | vpx_scale/yv12config.h | 13 |
14 files changed, 323 insertions, 24 deletions
@@ -175,6 +175,7 @@ CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_enc CODEC_EXPORTS-$(CONFIG_DECODERS) += vpx/exports_dec INSTALL-LIBS-yes += include/vpx/vpx_codec.h +INSTALL-LIBS-yes += include/vpx/vpx_frame_buffer.h INSTALL-LIBS-yes += include/vpx/vpx_image.h INSTALL-LIBS-yes += include/vpx/vpx_integer.h INSTALL-LIBS-$(CONFIG_DECODERS) += include/vpx/vpx_decoder.h diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c index e033fbb99..6f771992b 100644 --- a/vp9/common/vp9_alloccommon.c +++ b/vp9/common/vp9_alloccommon.c @@ -33,9 +33,16 @@ void vp9_update_mode_info_border(VP9_COMMON *cm, MODE_INFO *mi) { void vp9_free_frame_buffers(VP9_COMMON *cm) { int i; - for (i = 0; i < FRAME_BUFFERS; i++) + for (i = 0; i < FRAME_BUFFERS; i++) { vp9_free_frame_buffer(&cm->frame_bufs[i].buf); + if (cm->frame_bufs[i].ref_count > 0 && + cm->frame_bufs[i].raw_frame_buffer.data != NULL) { + cm->release_fb_cb(cm->cb_priv, &cm->frame_bufs[i].raw_frame_buffer); + cm->frame_bufs[i].ref_count = 0; + } + } + vp9_free_frame_buffer(&cm->post_proc_buffer); vpx_free(cm->mip); @@ -85,7 +92,7 @@ int vp9_resize_frame_buffers(VP9_COMMON *cm, int width, int height) { int mi_size; if (vp9_realloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y, - VP9_DEC_BORDER_IN_PIXELS) < 0) + VP9_DEC_BORDER_IN_PIXELS, NULL, NULL, NULL) < 0) goto fail; set_mb_mi(cm, aligned_width, aligned_height); @@ -199,6 +206,7 @@ void vp9_create_common(VP9_COMMON *cm) { void vp9_remove_common(VP9_COMMON *cm) { vp9_free_frame_buffers(cm); + vp9_free_internal_frame_buffers(&cm->int_frame_buffers); } void vp9_initialize_common() { diff --git a/vp9/common/vp9_frame_buffers.c b/vp9/common/vp9_frame_buffers.c new file mode 100644 index 000000000..d903ed695 --- /dev/null +++ b/vp9/common/vp9_frame_buffers.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <assert.h> + +#include "vp9/common/vp9_frame_buffers.h" +#include "vpx_mem/vpx_mem.h" + +int vp9_alloc_internal_frame_buffers(InternalFrameBufferList *list) { + assert(list != NULL); + vp9_free_internal_frame_buffers(list); + + list->num_internal_frame_buffers = + VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS; + list->int_fb = vpx_calloc(list->num_internal_frame_buffers, + sizeof(*list->int_fb)); + return (list->int_fb == NULL); +} + +void vp9_free_internal_frame_buffers(InternalFrameBufferList *list) { + int i; + + assert(list != NULL); + + for (i = 0; i < list->num_internal_frame_buffers; ++i) { + vpx_free(list->int_fb[i].data); + list->int_fb[i].data = NULL; + } + vpx_free(list->int_fb); + list->int_fb = NULL; +} + +int vp9_get_frame_buffer(void *cb_priv, size_t min_size, + vpx_codec_frame_buffer_t *fb) { + int i; + InternalFrameBufferList *const int_fb_list = + (InternalFrameBufferList *)cb_priv; + if (int_fb_list == NULL || fb == NULL) + return -1; + + // Find a free frame buffer. + for (i = 0; i < int_fb_list->num_internal_frame_buffers; ++i) { + if (!int_fb_list->int_fb[i].in_use) + break; + } + + if (i == int_fb_list->num_internal_frame_buffers) + return -1; + + if (int_fb_list->int_fb[i].size < min_size) { + int_fb_list->int_fb[i].data = + (uint8_t *)vpx_realloc(int_fb_list->int_fb[i].data, min_size); + if (!int_fb_list->int_fb[i].data) + return -1; + + int_fb_list->int_fb[i].size = min_size; + } + + fb->data = int_fb_list->int_fb[i].data; + fb->size = int_fb_list->int_fb[i].size; + int_fb_list->int_fb[i].in_use = 1; + + // Set the frame buffer's private data to point at the internal frame buffer. + fb->priv = &int_fb_list->int_fb[i]; + return 0; +} + +int vp9_release_frame_buffer(void *cb_priv, vpx_codec_frame_buffer_t *fb) { + InternalFrameBuffer *int_fb; + (void)cb_priv; + if (fb == NULL) + return -1; + + int_fb = (InternalFrameBuffer *)fb->priv; + int_fb->in_use = 0; + return 0; +} diff --git a/vp9/common/vp9_frame_buffers.h b/vp9/common/vp9_frame_buffers.h new file mode 100644 index 000000000..e2cfe61b6 --- /dev/null +++ b/vp9/common/vp9_frame_buffers.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef VP9_COMMON_VP9_FRAME_BUFFERS_H_ +#define VP9_COMMON_VP9_FRAME_BUFFERS_H_ + +#include "vpx/vpx_frame_buffer.h" +#include "vpx/vpx_integer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct InternalFrameBuffer { + uint8_t *data; + size_t size; + int in_use; +} InternalFrameBuffer; + +typedef struct InternalFrameBufferList { + int num_internal_frame_buffers; + InternalFrameBuffer *int_fb; +} InternalFrameBufferList; + +// Initializes |list|. Returns 0 on success. +int vp9_alloc_internal_frame_buffers(InternalFrameBufferList *list); + +// Free any data allocated to the frame buffers. +void vp9_free_internal_frame_buffers(InternalFrameBufferList *list); + +// Callback used by libvpx to request an external frame buffer. |cb_priv| +// Callback private data, which points to an InternalFrameBufferList. +// |min_size| is the minimum size in bytes needed to decode the next frame. +// |fb| pointer to the frame buffer. +int vp9_get_frame_buffer(void *cb_priv, size_t min_size, + vpx_codec_frame_buffer_t *fb); + +// Callback used by libvpx when there are no references to the frame buffer. +// |cb_priv| is not used. |fb| pointer to the frame buffer. +int vp9_release_frame_buffer(void *cb_priv, vpx_codec_frame_buffer_t *fb); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // VP9_COMMON_VP9_FRAME_BUFFERS_H_ diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index e82556c96..97983c596 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -18,6 +18,7 @@ #include "vp9/common/vp9_entropymv.h" #include "vp9/common/vp9_entropy.h" #include "vp9/common/vp9_entropymode.h" +#include "vp9/common/vp9_frame_buffers.h" #include "vp9/common/vp9_quant_common.h" #include "vp9/common/vp9_tile_common.h" @@ -94,6 +95,7 @@ typedef enum { typedef struct { int ref_count; + vpx_codec_frame_buffer_t raw_frame_buffer; YV12_BUFFER_CONFIG buf; } RefCntBuffer; @@ -223,6 +225,14 @@ typedef struct VP9Common { int frame_parallel_decoding_mode; int log2_tile_cols, log2_tile_rows; + + // Private data associated with the frame buffer callbacks. + void *cb_priv; + vpx_get_frame_buffer_cb_fn_t get_fb_cb; + vpx_release_frame_buffer_cb_fn_t release_fb_cb; + + // Handles memory for the codec. + InternalFrameBufferList int_frame_buffers; } VP9_COMMON; static INLINE YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) { diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c index 93ef7503f..d37afa5bc 100644 --- a/vp9/decoder/vp9_decodeframe.c +++ b/vp9/decoder/vp9_decodeframe.c @@ -691,9 +691,14 @@ static void apply_frame_size(VP9D_COMP *pbi, int width, int height) { vp9_update_frame_size(cm); } - vp9_realloc_frame_buffer(get_frame_new_buffer(cm), cm->width, cm->height, - cm->subsampling_x, cm->subsampling_y, - VP9_DEC_BORDER_IN_PIXELS); + if (vp9_realloc_frame_buffer( + get_frame_new_buffer(cm), cm->width, cm->height, + cm->subsampling_x, cm->subsampling_y, VP9_DEC_BORDER_IN_PIXELS, + &cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer, cm->get_fb_cb, + cm->cb_priv)) { + vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, + "Failed to allocate frame buffer"); + } } static void setup_frame_size(VP9D_COMP *pbi, @@ -1114,7 +1119,7 @@ static size_t read_uncompressed_header(VP9D_COMP *pbi, cm->show_existing_frame = vp9_rb_read_bit(rb); if (cm->show_existing_frame) { // Show an existing frame directly. - int frame_to_show = cm->ref_frame_map[vp9_rb_read_literal(rb, 3)]; + const int frame_to_show = cm->ref_frame_map[vp9_rb_read_literal(rb, 3)]; ref_cnt_fb(cm->frame_bufs, &cm->new_fb_idx, frame_to_show); pbi->refresh_frame_flags = 0; cm->lf.filter_level = 0; diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c index 803d536ba..fd3488355 100644 --- a/vp9/decoder/vp9_onyxd_if.c +++ b/vp9/decoder/vp9_onyxd_if.c @@ -290,9 +290,14 @@ static void swap_frame_buffers(VP9D_COMP *pbi) { VP9_COMMON *const cm = &pbi->common; for (mask = pbi->refresh_frame_flags; mask; mask >>= 1) { - if (mask & 1) + if (mask & 1) { + const int old_idx = cm->ref_frame_map[ref_index]; ref_cnt_fb(cm->frame_bufs, &cm->ref_frame_map[ref_index], cm->new_fb_idx); + if (old_idx >= 0 && cm->frame_bufs[old_idx].ref_count == 0) + cm->release_fb_cb(cm->cb_priv, + &cm->frame_bufs[old_idx].raw_frame_buffer); + } ++ref_index; } diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index a81aa0a71..58e58530d 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -964,7 +964,7 @@ static void alloc_raw_frame_buffers(VP9_COMP *cpi) { if (vp9_realloc_frame_buffer(&cpi->alt_ref_buffer, cpi->oxcf.width, cpi->oxcf.height, cm->subsampling_x, cm->subsampling_y, - VP9_ENC_BORDER_IN_PIXELS)) + VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL)) vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, "Failed to allocate altref buffer"); } @@ -1032,14 +1032,14 @@ static void update_frame_size(VP9_COMP *cpi) { if (vp9_realloc_frame_buffer(&cpi->last_frame_uf, cm->width, cm->height, cm->subsampling_x, cm->subsampling_y, - VP9_ENC_BORDER_IN_PIXELS)) + VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL)) vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, "Failed to reallocate last frame buffer"); if (vp9_realloc_frame_buffer(&cpi->scaled_source, cm->width, cm->height, cm->subsampling_x, cm->subsampling_y, - VP9_ENC_BORDER_IN_PIXELS)) + VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL)) vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, "Failed to reallocate scaled source buffer"); @@ -2674,7 +2674,7 @@ static void scale_references(VP9_COMP *cpi) { vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf, cm->width, cm->height, cm->subsampling_x, cm->subsampling_y, - VP9_ENC_BORDER_IN_PIXELS); + VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL); scale_and_extend_frame(ref, &cm->frame_bufs[new_fb].buf); cpi->scaled_ref_idx[ref_frame - 1] = new_fb; } else { @@ -3684,7 +3684,7 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, vp9_realloc_frame_buffer(get_frame_new_buffer(cm), cm->width, cm->height, cm->subsampling_x, cm->subsampling_y, - VP9_ENC_BORDER_IN_PIXELS); + VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL); for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)]; diff --git a/vp9/vp9_common.mk b/vp9/vp9_common.mk index 23a54dddd..85e83b834 100644 --- a/vp9/vp9_common.mk +++ b/vp9/vp9_common.mk @@ -23,6 +23,8 @@ VP9_COMMON_SRCS-yes += common/vp9_entropymode.c VP9_COMMON_SRCS-yes += common/vp9_entropymv.c VP9_COMMON_SRCS-yes += common/vp9_filter.c VP9_COMMON_SRCS-yes += common/vp9_filter.h +VP9_COMMON_SRCS-yes += common/vp9_frame_buffers.c +VP9_COMMON_SRCS-yes += common/vp9_frame_buffers.h VP9_COMMON_SRCS-yes += common/generic/vp9_systemdependent.c VP9_COMMON_SRCS-yes += common/vp9_idct.c VP9_COMMON_SRCS-yes += common/vp9_alloccommon.h diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c index 0e19b0c48..881a7d152 100644 --- a/vp9/vp9_dx_iface.c +++ b/vp9/vp9_dx_iface.c @@ -15,6 +15,7 @@ #include "vpx/vp8dx.h" #include "vpx/internal/vpx_codec_internal.h" #include "./vpx_version.h" +#include "vp9/common/vp9_frame_buffers.h" #include "vp9/decoder/vp9_onyxd.h" #include "vp9/decoder/vp9_onyxd_int.h" #include "vp9/decoder/vp9_read_bit_buffer.h" @@ -293,10 +294,22 @@ static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx, ctx->postproc_cfg.noise_level = 0; } - if (!optr) + if (!optr) { res = VPX_CODEC_ERROR; - else + } else { + VP9D_COMP *const pbi = (VP9D_COMP*)optr; + VP9_COMMON *const cm = &pbi->common; + + cm->get_fb_cb = vp9_get_frame_buffer; + cm->release_fb_cb = vp9_release_frame_buffer; + + if (vp9_alloc_internal_frame_buffers(&cm->int_frame_buffers)) + vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, + "Failed to initialize internal frame buffers"); + cm->cb_priv = &cm->int_frame_buffers; + ctx->pbi = optr; + } } ctx->decoder_init = 1; diff --git a/vpx/vpx_codec.mk b/vpx/vpx_codec.mk index 549c24908..111c87e53 100644 --- a/vpx/vpx_codec.mk +++ b/vpx/vpx_codec.mk @@ -26,6 +26,7 @@ API_DOC_SRCS-$(CONFIG_VP8_DECODER) += vp8dx.h API_DOC_SRCS-yes += vpx_codec.h API_DOC_SRCS-yes += vpx_decoder.h API_DOC_SRCS-yes += vpx_encoder.h +API_DOC_SRCS-yes += vpx_frame_buffer.h API_DOC_SRCS-yes += vpx_image.h API_SRCS-yes += src/vpx_decoder.c @@ -37,5 +38,6 @@ API_SRCS-yes += src/vpx_codec.c API_SRCS-yes += src/vpx_image.c API_SRCS-yes += vpx_codec.h API_SRCS-yes += vpx_codec.mk +API_SRCS-yes += vpx_frame_buffer.h API_SRCS-yes += vpx_image.h API_SRCS-$(BUILD_LIBVPX) += vpx_integer.h diff --git a/vpx/vpx_frame_buffer.h b/vpx/vpx_frame_buffer.h new file mode 100644 index 000000000..b5489b41b --- /dev/null +++ b/vpx/vpx_frame_buffer.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef VPX_VPX_FRAME_BUFFER_H_ +#define VPX_VPX_FRAME_BUFFER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "./vpx_integer.h" + +/*!\brief The maximum number of work buffers used by libvpx. + */ +#define VPX_MAXIMUM_WORK_BUFFERS 1 + +/*!\brief The maximum number of reference buffers that a VP9 encoder may use. + */ +#define VP9_MAXIMUM_REF_BUFFERS 8 + +/*!\brief External frame buffer + * + * This structure holds allocated frame buffers used by the decoder. + */ +typedef struct vpx_codec_frame_buffer { + uint8_t *data; /**< Pointer to the data buffer */ + size_t size; /**< Size of data in bytes */ + void *priv; /**< Frame's private data */ +} vpx_codec_frame_buffer_t; + +/*!\brief get frame buffer callback prototype + * + * This callback is invoked by the decoder to retrieve data for the frame + * buffer in order for the decode call to complete. The callback must + * allocate at least min_size in bytes and assign it to fb->data. Then the + * callback must set fb->size to the allocated size. The application does not + * need to align the allocated data. The callback is triggered when the + * decoder needs a frame buffer to decode a compressed image into. This + * function may be called more than once for every call to vpx_codec_decode. + * The application may set fb->priv to some data which will be passed + * back in the ximage and the release function call. On success the callback + * must return 0. Any failure the callback must return a value less than 0. + * + * \param[in] priv Callback's private data + * \param[in] new_size Size in bytes needed by the buffer + * \param[in,out] fb Pointer to vpx_codec_frame_buffer_t + */ +typedef int (*vpx_get_frame_buffer_cb_fn_t)( + void *priv, size_t min_size, vpx_codec_frame_buffer_t *fb); + +/*!\brief release frame buffer callback prototype + * + * This callback is invoked by the decoder when the frame buffer is not + * referenced by any other buffers. On success the callback must return 0. + * Any failure the callback must return a value less than 0. + * + * \param[in] priv Callback's private data + * \param[in] fb Pointer to vpx_codec_frame_buffer_t + */ +typedef int (*vpx_release_frame_buffer_cb_fn_t)( + void *priv, vpx_codec_frame_buffer_t *fb); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // VPX_VPX_FRAME_BUFFER_H_ diff --git a/vpx_scale/generic/yv12config.c b/vpx_scale/generic/yv12config.c index 693125a0f..ab0a30a4d 100644 --- a/vpx_scale/generic/yv12config.c +++ b/vpx_scale/generic/yv12config.c @@ -8,6 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include <assert.h> + #include "./vpx_config.h" #include "vpx_scale/yv12config.h" #include "vpx_mem/vpx_mem.h" @@ -19,10 +21,17 @@ /**************************************************************************** * ****************************************************************************/ +#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 frame buffer callbacks 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 +117,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 +134,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 *fb, + vpx_get_frame_buffer_cb_fn_t cb, + void *cb_priv) { if (ybf) { const int aligned_width = (width + 7) & ~7; const int aligned_height = (height + 7) & ~7; @@ -148,7 +162,26 @@ 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) { + if (cb != NULL) { + const int align_addr_extra_size = 31; + const size_t external_frame_size = frame_size + align_addr_extra_size; + + assert(fb != NULL); + + // Allocation to hold larger frame, or first allocation. + if (cb(cb_priv, external_frame_size, fb) < 0) + return -1; + + if (fb->data == NULL || fb->size < external_frame_size) + return -1; + + // This memset is needed for fixing valgrind error from C loop filter + // due to access uninitialized memory in frame border. It could be + // removed if border is totally removed. + vpx_memset(fb->data, 0, fb->size); + + ybf->buffer_alloc = yv12_align_addr(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); @@ -159,14 +192,11 @@ int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, ybf->buffer_alloc_sz = frame_size; // This memset is needed for fixing valgrind error from C loop filter - // due to access uninitialized memory in frame boarder. It could be + // due to access uninitialized memory in frame border. It could be // removed if border is totally removed. vpx_memset(ybf->buffer_alloc, 0, ybf->buffer_alloc_sz); } - if (ybf->buffer_alloc_sz < frame_size) - return -1; - /* Only support allocating buffers that have a border that's a multiple * of 32. The border restriction is required to get 16-byte alignment of * the start of the chroma rows without introducing an arbitrary gap @@ -214,7 +244,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 8f39eb769..525f3a00d 100644 --- a/vpx_scale/yv12config.h +++ b/vpx_scale/yv12config.h @@ -15,6 +15,7 @@ extern "C" { #endif +#include "vpx/vpx_frame_buffer.h" #include "vpx/vpx_integer.h" #define VP8BORDERINPIXELS 32 @@ -65,9 +66,19 @@ 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 cb is not + // NULL, then libvpx is using the frame buffer callbacks to handle memory. + // If cb is not NULL, libvpx will call cb with minimum size in bytes needed + // to decode the current frame. If cb is NULL, libvpx will allocate memory + // internally to decode the current frame. 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 *fb, + vpx_get_frame_buffer_cb_fn_t cb, + void *cb_priv); int vp9_free_frame_buffer(YV12_BUFFER_CONFIG *ybf); #ifdef __cplusplus |