#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"
/* Structures for handling memory allocations */
typedef enum {
- VP9_SEG_ALG_PRIV = 256,
+ VP9_SEG_ALG_PRIV = 256,
VP9_SEG_MAX
} mem_seg_id_t;
#define NELEMENTS(x) ((int)(sizeof(x)/sizeof(x[0])))
int img_setup;
int img_avail;
int invert_tile_order;
+
+ // External frame buffer info to save for VP9 common.
+ void *ext_priv; // Private data associated with the external frame buffers.
+ vpx_get_frame_buffer_cb_fn_t get_ext_fb_cb;
+ vpx_release_frame_buffer_cb_fn_t release_ext_fb_cb;
};
static unsigned long priv_sz(const vpx_codec_dec_cfg_t *si,
static vpx_codec_err_t vp9_init(vpx_codec_ctx_t *ctx,
vpx_codec_priv_enc_mr_cfg_t *data) {
- vpx_codec_err_t res = VPX_CODEC_OK;
+ vpx_codec_err_t res = VPX_CODEC_OK;
- /* This function only allocates space for the vpx_codec_alg_priv_t
- * structure. More memory may be required at the time the stream
- * information becomes known.
- */
+ // This function only allocates space for the vpx_codec_alg_priv_t
+ // structure. More memory may be required at the time the stream
+ // information becomes known.
if (!ctx->priv) {
vpx_codec_mmap_t mmap;
mmap.flags = vp9_mem_req_segs[0].flags;
res = vpx_mmap_alloc(&mmap);
-
if (!res) {
vp9_init_ctx(ctx, &mmap);
ctx->priv->alg_priv->defer_alloc = 1;
- /*post processing level initialized to do nothing */
}
}
return VPX_CODEC_OK;
}
-static vpx_codec_err_t vp9_peek_si(const uint8_t *data,
- unsigned int data_sz,
+static vpx_codec_err_t vp9_peek_si(const uint8_t *data, unsigned int data_sz,
vpx_codec_stream_info_t *si) {
if (data_sz <= 8) return VPX_CODEC_UNSUP_BITSTREAM;
if (data + data_sz <= data) return VPX_CODEC_INVALID_PARAM;
{
struct vp9_read_bit_buffer rb = { data, data + data_sz, 0, NULL, NULL };
const int frame_marker = vp9_rb_read_literal(&rb, 2);
- const int version = vp9_rb_read_bit(&rb) | (vp9_rb_read_bit(&rb) << 1);
- if (frame_marker != 0x2) return VPX_CODEC_UNSUP_BITSTREAM;
+ const int version = vp9_rb_read_bit(&rb);
+ (void) vp9_rb_read_bit(&rb); // unused version bit
+
+ if (frame_marker != VP9_FRAME_MARKER)
+ return VPX_CODEC_UNSUP_BITSTREAM;
#if CONFIG_NON420
if (version > 1) return VPX_CODEC_UNSUP_BITSTREAM;
#else
static vpx_codec_err_t vp9_get_si(vpx_codec_alg_priv_t *ctx,
vpx_codec_stream_info_t *si) {
- unsigned int sz;
-
- if (si->sz >= sizeof(vp9_stream_info_t))
- sz = sizeof(vp9_stream_info_t);
- else
- sz = sizeof(vpx_codec_stream_info_t);
-
+ const size_t sz = (si->sz >= sizeof(vp9_stream_info_t))
+ ? sizeof(vp9_stream_info_t)
+ : sizeof(vpx_codec_stream_info_t);
memcpy(si, &ctx->si, sz);
- si->sz = sz;
+ si->sz = (unsigned int)sz;
return VPX_CODEC_OK;
}
-static vpx_codec_err_t
-update_error_state(vpx_codec_alg_priv_t *ctx,
- const struct vpx_internal_error_info *error) {
- vpx_codec_err_t res;
+static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t *ctx,
+ const struct vpx_internal_error_info *error) {
+ if (error->error_code)
+ ctx->base.err_detail = error->has_detail ? error->detail : NULL;
- if ((res = error->error_code))
- ctx->base.err_detail = error->has_detail
- ? error->detail
- : NULL;
-
- return res;
+ return error->error_code;
}
-static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx,
- const uint8_t **data,
- unsigned int data_sz,
- void *user_priv,
- long deadline) {
+static vpx_codec_err_t decode_one(vpx_codec_alg_priv_t *ctx,
+ const uint8_t **data, unsigned int data_sz,
+ void *user_priv, int64_t deadline) {
vpx_codec_err_t res = VPX_CODEC_OK;
ctx->img_avail = 0;
oxcf.inv_tile_order = ctx->invert_tile_order;
optr = vp9_create_decompressor(&oxcf);
- /* If postprocessing was enabled by the application and a
- * configuration has not been provided, default it.
- */
- if (!ctx->postproc_cfg_set
- && (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)) {
- ctx->postproc_cfg.post_proc_flag =
- VP8_DEBLOCK | VP8_DEMACROBLOCK;
+ // If postprocessing was enabled by the application and a
+ // configuration has not been provided, default it.
+ if (!ctx->postproc_cfg_set &&
+ (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC)) {
+ ctx->postproc_cfg.post_proc_flag = VP8_DEBLOCK | VP8_DEMACROBLOCK;
ctx->postproc_cfg.deblocking_level = 4;
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;
+
+ // Set index to not initialized.
+ cm->new_fb_idx = -1;
+
+ if (ctx->get_ext_fb_cb != NULL && ctx->release_ext_fb_cb != NULL) {
+ cm->get_fb_cb = ctx->get_ext_fb_cb;
+ cm->release_fb_cb = ctx->release_ext_fb_cb;
+ cm->cb_priv = ctx->ext_priv;
+ } else {
+ 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;
if (ctx->base.init_flags & VPX_CODEC_USE_POSTPROC) {
flags.post_proc_flag =
#if CONFIG_POSTPROC_VISUALIZER
- ((ctx->dbg_color_ref_frame_flag != 0) ?
- VP9D_DEBUG_CLR_FRM_REF_BLKS : 0)
- | ((ctx->dbg_color_mb_modes_flag != 0) ?
- VP9D_DEBUG_CLR_BLK_MODES : 0)
- | ((ctx->dbg_color_b_modes_flag != 0) ?
- VP9D_DEBUG_CLR_BLK_MODES : 0)
- | ((ctx->dbg_display_mv_flag != 0) ?
- VP9D_DEBUG_DRAW_MV : 0)
- |
+ (ctx->dbg_color_ref_frame_flag ? VP9D_DEBUG_CLR_FRM_REF_BLKS : 0) |
+ (ctx->dbg_color_mb_modes_flag ? VP9D_DEBUG_CLR_BLK_MODES : 0) |
+ (ctx->dbg_color_b_modes_flag ? VP9D_DEBUG_CLR_BLK_MODES : 0) |
+ (ctx->dbg_display_mv_flag ? VP9D_DEBUG_DRAW_MV : 0) |
#endif
ctx->postproc_cfg.post_proc_flag;
- flags.deblocking_level = ctx->postproc_cfg.deblocking_level;
- flags.noise_level = ctx->postproc_cfg.noise_level;
+ flags.deblocking_level = ctx->postproc_cfg.deblocking_level;
+ flags.noise_level = ctx->postproc_cfg.noise_level;
#if CONFIG_POSTPROC_VISUALIZER
flags.display_ref_frame_flag = ctx->dbg_color_ref_frame_flag;
flags.display_mb_modes_flag = ctx->dbg_color_mb_modes_flag;
- flags.display_b_modes_flag = ctx->dbg_color_b_modes_flag;
- flags.display_mv_flag = ctx->dbg_display_mv_flag;
+ flags.display_b_modes_flag = ctx->dbg_color_b_modes_flag;
+ flags.display_mv_flag = ctx->dbg_display_mv_flag;
#endif
}
if (vp9_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) {
- VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
+ VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi;
res = update_error_state(ctx, &pbi->common.error);
}
if (!res && 0 == vp9_get_raw_frame(ctx->pbi, &sd, &time_stamp,
&time_end_stamp, &flags)) {
+ VP9D_COMP *const pbi = (VP9D_COMP*)ctx->pbi;
+ VP9_COMMON *const cm = &pbi->common;
yuvconfig2image(&ctx->img, &sd, user_priv);
+
+ ctx->img.fb_priv = cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer.priv;
ctx->img_avail = 1;
}
}
return res;
}
-static void parse_superframe_index(const uint8_t *data,
- size_t data_sz,
- uint32_t sizes[8],
- int *count) {
+static void parse_superframe_index(const uint8_t *data, size_t data_sz,
+ uint32_t sizes[8], int *count) {
uint8_t marker;
assert(data_sz);
return img;
}
-static vpx_codec_err_t vp9_xma_get_mmap(const vpx_codec_ctx_t *ctx,
- vpx_codec_mmap_t *mmap,
- vpx_codec_iter_t *iter) {
- vpx_codec_err_t res;
- const mem_req_t *seg_iter = *iter;
+static vpx_codec_err_t vp9_set_fb_fn(
+ vpx_codec_alg_priv_t *ctx,
+ vpx_get_frame_buffer_cb_fn_t cb_get,
+ vpx_release_frame_buffer_cb_fn_t cb_release, void *cb_priv) {
+ if (cb_get == NULL || cb_release == NULL) {
+ return VPX_CODEC_INVALID_PARAM;
+ } else if (ctx->pbi == NULL) {
+ // If the decoder has already been initialized, do not accept changes to
+ // the frame buffer functions.
+ ctx->get_ext_fb_cb = cb_get;
+ ctx->release_ext_fb_cb = cb_release;
+ ctx->ext_priv = cb_priv;
+ return VPX_CODEC_OK;
+ }
+
+ return VPX_CODEC_ERROR;
+}
+
+static vpx_codec_err_t vp9_xma_get_mmap(const vpx_codec_ctx_t *ctx,
+ vpx_codec_mmap_t *mmap,
+ vpx_codec_iter_t *iter) {
+ vpx_codec_err_t res;
+ const mem_req_t *seg_iter = *iter;
/* Get address of next segment request */
do {
return res;
}
-static vpx_codec_err_t vp9_xma_set_mmap(vpx_codec_ctx_t *ctx,
+static vpx_codec_err_t vp9_xma_set_mmap(vpx_codec_ctx_t *ctx,
const vpx_codec_mmap_t *mmap) {
vpx_codec_err_t res = VPX_CODEC_MEM_ERROR;
int i, done;
return res;
}
-static vpx_codec_err_t set_reference(vpx_codec_alg_priv_t *ctx,
- int ctr_id,
+static vpx_codec_err_t set_reference(vpx_codec_alg_priv_t *ctx, int ctr_id,
va_list args) {
vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
YV12_BUFFER_CONFIG sd;
image2yuvconfig(&frame->img, &sd);
-
return vp9_set_reference_dec(ctx->pbi,
(VP9_REFFRAME)frame->frame_type, &sd);
} else {
}
}
-static vpx_codec_err_t copy_reference(vpx_codec_alg_priv_t *ctx,
- int ctr_id,
+static vpx_codec_err_t copy_reference(vpx_codec_alg_priv_t *ctx, int ctr_id,
va_list args) {
vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *);
}
}
-static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx,
- int ctr_id,
+static vpx_codec_err_t get_reference(vpx_codec_alg_priv_t *ctx, int ctr_id,
va_list args) {
vp9_ref_frame_t *data = va_arg(args, vp9_ref_frame_t *);
}
}
-static vpx_codec_err_t set_postproc(vpx_codec_alg_priv_t *ctx,
- int ctr_id,
+static vpx_codec_err_t set_postproc(vpx_codec_alg_priv_t *ctx, int ctr_id,
va_list args) {
#if CONFIG_VP9_POSTPROC
vp8_postproc_cfg_t *data = va_arg(args, vp8_postproc_cfg_t *);
#endif
}
-static vpx_codec_err_t set_dbg_options(vpx_codec_alg_priv_t *ctx,
- int ctrl_id,
+static vpx_codec_err_t set_dbg_options(vpx_codec_alg_priv_t *ctx, int ctrl_id,
va_list args) {
#if CONFIG_POSTPROC_VISUALIZER && CONFIG_POSTPROC
int data = va_arg(args, int);
}
static vpx_codec_err_t get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
- int ctrl_id,
- va_list args) {
+ int ctrl_id, va_list args) {
int *update_info = va_arg(args, int *);
- VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
+ VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi;
if (update_info) {
*update_info = pbi->refresh_frame_flags;
static vpx_codec_err_t get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
- int ctrl_id,
- va_list args) {
+ int ctrl_id, va_list args) {
int *corrupted = va_arg(args, int *);
if (corrupted) {
- VP9D_COMP *pbi = (VP9D_COMP *)ctx->pbi;
+ VP9D_COMP *pbi = (VP9D_COMP*)ctx->pbi;
if (pbi)
*corrupted = pbi->common.frame_to_show->corrupted;
else
}
}
+static vpx_codec_err_t get_display_size(vpx_codec_alg_priv_t *ctx,
+ int ctrl_id, va_list args) {
+ int *const display_size = va_arg(args, int *);
+
+ if (display_size) {
+ const VP9D_COMP *const pbi = (VP9D_COMP*)ctx->pbi;
+ if (pbi) {
+ display_size[0] = pbi->common.display_width;
+ display_size[1] = pbi->common.display_height;
+ } else {
+ return VPX_CODEC_ERROR;
+ }
+ return VPX_CODEC_OK;
+ } else {
+ return VPX_CODEC_INVALID_PARAM;
+ }
+}
+
static vpx_codec_err_t set_invert_tile_order(vpx_codec_alg_priv_t *ctx,
int ctr_id,
va_list args) {
{VP8D_GET_LAST_REF_UPDATES, get_last_ref_updates},
{VP8D_GET_FRAME_CORRUPTED, get_frame_corrupted},
{VP9_GET_REFERENCE, get_reference},
+ {VP9D_GET_DISPLAY_SIZE, get_display_size},
{VP9_INVERT_TILE_DECODE_ORDER, set_invert_tile_order},
{ -1, NULL},
};
CODEC_INTERFACE(vpx_codec_vp9_dx) = {
"WebM Project VP9 Decoder" VERSION_STRING,
VPX_CODEC_INTERNAL_ABI_VERSION,
- VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC,
+ VPX_CODEC_CAP_DECODER | VP9_CAP_POSTPROC |
+ VPX_CODEC_CAP_EXTERNAL_FRAME_BUFFER,
/* vpx_codec_caps_t caps; */
vp9_init, /* vpx_codec_init_fn_t init; */
vp9_destroy, /* vpx_codec_destroy_fn_t destroy; */
vp9_get_si, /* vpx_codec_get_si_fn_t get_si; */
vp9_decode, /* vpx_codec_decode_fn_t decode; */
vp9_get_frame, /* vpx_codec_frame_get_fn_t frame_get; */
+ vp9_set_fb_fn, /* vpx_codec_set_fb_fn_t set_fb_fn; */
},
{ // NOLINT
/* encoder functions */