diff options
Diffstat (limited to 'vp8/vp8_dx_iface.c')
-rw-r--r-- | vp8/vp8_dx_iface.c | 301 |
1 files changed, 170 insertions, 131 deletions
diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c index c13d69783..871b8d385 100644 --- a/vp8/vp8_dx_iface.c +++ b/vp8/vp8_dx_iface.c @@ -11,7 +11,7 @@ #include <stdlib.h> #include <string.h> -#include "vpx_rtcd.h" +#include "vp8_rtcd.h" #include "vpx/vpx_decoder.h" #include "vpx/vp8dx.h" #include "vpx/internal/vpx_codec_internal.h" @@ -41,15 +41,6 @@ typedef enum static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_t); -typedef struct -{ - unsigned int id; - unsigned long sz; - unsigned int align; - unsigned int flags; - unsigned long(*calc_sz)(const vpx_codec_dec_cfg_t *, vpx_codec_flags_t); -} mem_req_t; - static const mem_req_t vp8_mem_req_segs[] = { {VP8_SEG_ALG_PRIV, 0, 8, VPX_CODEC_MEM_ZERO, vp8_priv_sz}, @@ -64,7 +55,6 @@ struct vpx_codec_alg_priv vp8_stream_info_t si; int defer_alloc; int decoder_init; - struct VP8D_COMP *pbi; int postproc_cfg_set; vp8_postproc_cfg_t postproc_cfg; #if CONFIG_POSTPROC_VISUALIZER @@ -74,9 +64,13 @@ struct vpx_codec_alg_priv int dbg_color_b_modes_flag; int dbg_display_mv_flag; #endif + vp8_decrypt_cb *decrypt_cb; + void *decrypt_state; vpx_image_t img; int img_setup; + struct frame_buffers yv12_frame_buffers; void *user_priv; + FRAGMENT_DATA fragments; }; static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_t flags) @@ -90,65 +84,6 @@ static unsigned long vp8_priv_sz(const vpx_codec_dec_cfg_t *si, vpx_codec_flags_ return sizeof(vpx_codec_alg_priv_t); } - -static void vp8_mmap_dtor(vpx_codec_mmap_t *mmap) -{ - free(mmap->priv); -} - -static vpx_codec_err_t vp8_mmap_alloc(vpx_codec_mmap_t *mmap) -{ - vpx_codec_err_t res; - unsigned int align; - - align = mmap->align ? mmap->align - 1 : 0; - - if (mmap->flags & VPX_CODEC_MEM_ZERO) - mmap->priv = calloc(1, mmap->sz + align); - else - mmap->priv = malloc(mmap->sz + align); - - res = (mmap->priv) ? VPX_CODEC_OK : VPX_CODEC_MEM_ERROR; - mmap->base = (void *)((((uintptr_t)mmap->priv) + align) & ~(uintptr_t)align); - mmap->dtor = vp8_mmap_dtor; - return res; -} - -static vpx_codec_err_t vp8_validate_mmaps(const vp8_stream_info_t *si, - const vpx_codec_mmap_t *mmaps, - vpx_codec_flags_t init_flags) -{ - int i; - vpx_codec_err_t res = VPX_CODEC_OK; - - for (i = 0; i < NELEMENTS(vp8_mem_req_segs) - 1; i++) - { - /* Ensure the segment has been allocated */ - if (!mmaps[i].base) - { - res = VPX_CODEC_MEM_ERROR; - break; - } - - /* Verify variable size segment is big enough for the current si. */ - if (vp8_mem_req_segs[i].calc_sz) - { - vpx_codec_dec_cfg_t cfg; - - cfg.w = si->w; - cfg.h = si->h; - - if (mmaps[i].sz < vp8_mem_req_segs[i].calc_sz(&cfg, init_flags)) - { - res = VPX_CODEC_MEM_ERROR; - break; - } - } - } - - return res; -} - static void vp8_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap) { int i; @@ -163,6 +98,8 @@ static void vp8_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap) ctx->priv->alg_priv->mmaps[0] = *mmap; ctx->priv->alg_priv->si.sz = sizeof(ctx->priv->alg_priv->si); + ctx->priv->alg_priv->decrypt_cb = NULL; + ctx->priv->alg_priv->decrypt_state = NULL; ctx->priv->init_flags = ctx->init_flags; if (ctx->config.dec) @@ -173,16 +110,6 @@ static void vp8_init_ctx(vpx_codec_ctx_t *ctx, const vpx_codec_mmap_t *mmap) } } -static void *mmap_lkup(vpx_codec_alg_priv_t *ctx, unsigned int id) -{ - int i; - - for (i = 0; i < NELEMENTS(ctx->mmaps); i++) - if (ctx->mmaps[i].id == id) - return ctx->mmaps[i].base; - - return NULL; -} static void vp8_finalize_mmaps(vpx_codec_alg_priv_t *ctx) { /* nothing to clean up */ @@ -194,7 +121,7 @@ static vpx_codec_err_t vp8_init(vpx_codec_ctx_t *ctx, vpx_codec_err_t res = VPX_CODEC_OK; (void) data; - vpx_rtcd(); + vp8_rtcd(); /* This function only allocates space for the vpx_codec_alg_priv_t * structure. More memory may be required at the time the stream @@ -209,15 +136,38 @@ static vpx_codec_err_t vp8_init(vpx_codec_ctx_t *ctx, mmap.align = vp8_mem_req_segs[0].align; mmap.flags = vp8_mem_req_segs[0].flags; - res = vp8_mmap_alloc(&mmap); + res = vpx_mmap_alloc(&mmap); + if (res != VPX_CODEC_OK) return res; - if (!res) - { - vp8_init_ctx(ctx, &mmap); + vp8_init_ctx(ctx, &mmap); - ctx->priv->alg_priv->defer_alloc = 1; - /*post processing level initialized to do nothing */ - } + /* initialize number of fragments to zero */ + ctx->priv->alg_priv->fragments.count = 0; + /* is input fragments enabled? */ + ctx->priv->alg_priv->fragments.enabled = + (ctx->priv->alg_priv->base.init_flags & + VPX_CODEC_USE_INPUT_FRAGMENTS); + + ctx->priv->alg_priv->defer_alloc = 1; + /*post processing level initialized to do nothing */ + } + + ctx->priv->alg_priv->yv12_frame_buffers.use_frame_threads = + (ctx->priv->alg_priv->base.init_flags & + VPX_CODEC_USE_FRAME_THREADING); + + /* for now, disable frame threading */ + ctx->priv->alg_priv->yv12_frame_buffers.use_frame_threads = 0; + + if(ctx->priv->alg_priv->yv12_frame_buffers.use_frame_threads && + (( ctx->priv->alg_priv->base.init_flags & + VPX_CODEC_USE_ERROR_CONCEALMENT) + || ( ctx->priv->alg_priv->base.init_flags & + VPX_CODEC_USE_INPUT_FRAGMENTS) ) ) + { + /* row-based threading, error concealment, and input fragments will + * not be supported when using frame-based threading */ + res = VPX_CODEC_INVALID_PARAM; } return res; @@ -227,7 +177,7 @@ static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx) { int i; - vp8dx_remove_decompressor(ctx->pbi); + vp8_remove_decoder_instances(&ctx->yv12_frame_buffers); for (i = NELEMENTS(ctx->mmaps) - 1; i >= 0; i--) { @@ -238,14 +188,18 @@ static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t *ctx) return VPX_CODEC_OK; } -static vpx_codec_err_t vp8_peek_si(const uint8_t *data, - unsigned int data_sz, - vpx_codec_stream_info_t *si) +static vpx_codec_err_t vp8_peek_si_internal(const uint8_t *data, + unsigned int data_sz, + vpx_codec_stream_info_t *si, + vp8_decrypt_cb *decrypt_cb, + void *decrypt_state) { vpx_codec_err_t res = VPX_CODEC_OK; if(data + data_sz <= data) + { res = VPX_CODEC_INVALID_PARAM; + } else { /* Parse uncompresssed part of key frame header. @@ -254,30 +208,44 @@ static vpx_codec_err_t vp8_peek_si(const uint8_t *data, * 4 bytes:- including image width and height in the lowest 14 bits * of each 2-byte value. */ + uint8_t clear_buffer[10]; + const uint8_t *clear = data; + if (decrypt_cb) + { + int n = data_sz > 10 ? 10 : data_sz; + decrypt_cb(decrypt_state, data, clear_buffer, n); + clear = clear_buffer; + } si->is_kf = 0; - if (data_sz >= 10 && !(data[0] & 0x01)) /* I-Frame */ + if (data_sz >= 10 && !(clear[0] & 0x01)) /* I-Frame */ { - const uint8_t *c = data + 3; si->is_kf = 1; /* vet via sync code */ - if (c[0] != 0x9d || c[1] != 0x01 || c[2] != 0x2a) + if (clear[3] != 0x9d || clear[4] != 0x01 || clear[5] != 0x2a) res = VPX_CODEC_UNSUP_BITSTREAM; - si->w = (c[3] | (c[4] << 8)) & 0x3fff; - si->h = (c[5] | (c[6] << 8)) & 0x3fff; + si->w = (clear[6] | (clear[7] << 8)) & 0x3fff; + si->h = (clear[8] | (clear[9] << 8)) & 0x3fff; /*printf("w=%d, h=%d\n", si->w, si->h);*/ if (!(si->h | si->w)) res = VPX_CODEC_UNSUP_BITSTREAM; } else + { res = VPX_CODEC_UNSUP_BITSTREAM; + } } return res; +} +static vpx_codec_err_t vp8_peek_si(const uint8_t *data, + unsigned int data_sz, + vpx_codec_stream_info_t *si) { + return vp8_peek_si_internal(data, data_sz, si, NULL, NULL); } static vpx_codec_err_t vp8_get_si(vpx_codec_alg_priv_t *ctx, @@ -320,8 +288,7 @@ static void yuvconfig2image(vpx_image_t *img, * the Y, U, and V planes, nor other alignment adjustments that * might be representable by a YV12_BUFFER_CONFIG, so we just * initialize all the fields.*/ - img->fmt = yv12->clrtype == REG_YUV ? - VPX_IMG_FMT_I420 : VPX_IMG_FMT_VPXI420; + img->fmt = VPX_IMG_FMT_I420; img->w = yv12->y_stride; img->h = (yv12->y_height + 2 * VP8BORDERINPIXELS + 15) & ~15; img->d_w = yv12->y_width; @@ -343,6 +310,47 @@ static void yuvconfig2image(vpx_image_t *img, img->self_allocd = 0; } +static int +update_fragments(vpx_codec_alg_priv_t *ctx, + const uint8_t *data, + unsigned int data_sz, + vpx_codec_err_t *res) +{ + *res = VPX_CODEC_OK; + + if (ctx->fragments.count == 0) + { + /* New frame, reset fragment pointers and sizes */ + vpx_memset((void*)ctx->fragments.ptrs, 0, sizeof(ctx->fragments.ptrs)); + vpx_memset(ctx->fragments.sizes, 0, sizeof(ctx->fragments.sizes)); + } + if (ctx->fragments.enabled && !(data == NULL && data_sz == 0)) + { + /* Store a pointer to this fragment and return. We haven't + * received the complete frame yet, so we will wait with decoding. + */ + ctx->fragments.ptrs[ctx->fragments.count] = data; + ctx->fragments.sizes[ctx->fragments.count] = data_sz; + ctx->fragments.count++; + if (ctx->fragments.count > (1 << EIGHT_PARTITION) + 1) + { + ctx->fragments.count = 0; + *res = VPX_CODEC_INVALID_PARAM; + return -1; + } + return 0; + } + + if (!ctx->fragments.enabled) + { + ctx->fragments.ptrs[0] = data; + ctx->fragments.sizes[0] = data_sz; + ctx->fragments.count = 1; + } + + return 1; +} + static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, const uint8_t *data, unsigned int data_sz, @@ -353,6 +361,11 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, unsigned int resolution_change = 0; unsigned int w, h; + + /* Update the input fragment data */ + if(update_fragments(ctx, data, data_sz, &res) <= 0) + return res; + /* Determine the stream parameters. Note that we rely on peek_si to * validate that we have a buffer that does not wrap around the top * of the heap. @@ -360,7 +373,8 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, w = ctx->si.w; h = ctx->si.h; - res = ctx->base.iface->dec.peek_si(data, data_sz, &ctx->si); + res = vp8_peek_si_internal(ctx->fragments.ptrs[0], ctx->fragments.sizes[0], + &ctx->si, ctx->decrypt_cb, ctx->decrypt_state); if((res == VPX_CODEC_UNSUP_BITSTREAM) && !ctx->si.is_kf) { @@ -395,7 +409,7 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, ctx->mmaps[i].sz = vp8_mem_req_segs[i].calc_sz(&cfg, ctx->base.init_flags); - res = vp8_mmap_alloc(&ctx->mmaps[i]); + res = vpx_mmap_alloc(&ctx->mmaps[i]); } if (!res) @@ -407,12 +421,13 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, /* Initialize the decoder instance on the first frame*/ if (!res && !ctx->decoder_init) { - res = vp8_validate_mmaps(&ctx->si, ctx->mmaps, ctx->base.init_flags); + res = vpx_validate_mmaps(&ctx->si, ctx->mmaps, + vp8_mem_req_segs, NELEMENTS(vp8_mem_req_segs), + ctx->base.init_flags); if (!res) { VP8D_CONFIG oxcf; - struct VP8D_COMP* optr; oxcf.Width = ctx->si.w; oxcf.Height = ctx->si.h; @@ -421,10 +436,6 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, oxcf.max_threads = ctx->cfg.threads; oxcf.error_concealment = (ctx->base.init_flags & VPX_CODEC_USE_ERROR_CONCEALMENT); - oxcf.input_fragments = - (ctx->base.init_flags & VPX_CODEC_USE_INPUT_FRAGMENTS); - - optr = vp8dx_create_decompressor(&oxcf); /* If postprocessing was enabled by the application and a * configuration has not been provided, default it. @@ -438,20 +449,19 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, ctx->postproc_cfg.noise_level = 0; } - if (!optr) - res = VPX_CODEC_ERROR; - else - ctx->pbi = optr; + res = vp8_create_decoder_instances(&ctx->yv12_frame_buffers, &oxcf); + ctx->yv12_frame_buffers.pbi[0]->decrypt_cb = ctx->decrypt_cb; + ctx->yv12_frame_buffers.pbi[0]->decrypt_state = ctx->decrypt_state; } ctx->decoder_init = 1; } - if (!res && ctx->pbi) + if (!res) { + VP8D_COMP *pbi = ctx->yv12_frame_buffers.pbi[0]; if(resolution_change) { - VP8D_COMP *pbi = ctx->pbi; VP8_COMMON *const pc = & pbi->common; MACROBLOCKD *const xd = & pbi->mb; #if CONFIG_MULTITHREAD @@ -541,15 +551,20 @@ static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx, pbi->common.error.setjmp = 0; /* required to get past the first get_free_fb() call */ - ctx->pbi->common.fb_idx_ref_cnt[0] = 0; + pbi->common.fb_idx_ref_cnt[0] = 0; } + /* update the pbi fragment data */ + pbi->fragments = ctx->fragments; + ctx->user_priv = user_priv; - if (vp8dx_receive_compressed_data(ctx->pbi, data_sz, data, deadline)) + if (vp8dx_receive_compressed_data(pbi, data_sz, data, deadline)) { - VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi; res = update_error_state(ctx, &pbi->common.error); } + + /* get ready for the next series of fragments */ + ctx->fragments.count = 0; } return res; @@ -563,7 +578,7 @@ static vpx_image_t *vp8_get_frame(vpx_codec_alg_priv_t *ctx, /* iter acts as a flip flop, so an image is only returned on the first * call to get_frame. */ - if (!(*iter)) + if (!(*iter) && ctx->yv12_frame_buffers.pbi[0]) { YV12_BUFFER_CONFIG sd; int64_t time_stamp = 0, time_end_stamp = 0; @@ -590,7 +605,8 @@ static vpx_image_t *vp8_get_frame(vpx_codec_alg_priv_t *ctx, #endif } - if (0 == vp8dx_get_raw_frame(ctx->pbi, &sd, &time_stamp, &time_end_stamp, &flags)) + if (0 == vp8dx_get_raw_frame(ctx->yv12_frame_buffers.pbi[0], &sd, + &time_stamp, &time_end_stamp, &flags)) { yuvconfig2image(&ctx->img, &sd, ctx->user_priv); @@ -693,6 +709,8 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img, yv12->u_buffer = img->planes[VPX_PLANE_U]; yv12->v_buffer = img->planes[VPX_PLANE_V]; + yv12->y_crop_width = img->d_w; + yv12->y_crop_height = img->d_h; yv12->y_width = img->d_w; yv12->y_height = img->d_h; yv12->uv_width = yv12->y_width / 2; @@ -702,8 +720,6 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img, yv12->uv_stride = img->stride[VPX_PLANE_U]; yv12->border = (img->stride[VPX_PLANE_Y] - img->d_w) / 2; - yv12->clrtype = (img->fmt == VPX_IMG_FMT_VPXI420 || img->fmt == VPX_IMG_FMT_VPXYV12); - return res; } @@ -715,14 +731,15 @@ static vpx_codec_err_t vp8_set_reference(vpx_codec_alg_priv_t *ctx, vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); - if (data) + if (data && !ctx->yv12_frame_buffers.use_frame_threads) { vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; YV12_BUFFER_CONFIG sd; image2yuvconfig(&frame->img, &sd); - return vp8dx_set_reference(ctx->pbi, frame->frame_type, &sd); + return vp8dx_set_reference(ctx->yv12_frame_buffers.pbi[0], + frame->frame_type, &sd); } else return VPX_CODEC_INVALID_PARAM; @@ -736,14 +753,15 @@ static vpx_codec_err_t vp8_get_reference(vpx_codec_alg_priv_t *ctx, vpx_ref_frame_t *data = va_arg(args, vpx_ref_frame_t *); - if (data) + if (data && !ctx->yv12_frame_buffers.use_frame_threads) { vpx_ref_frame_t *frame = (vpx_ref_frame_t *)data; YV12_BUFFER_CONFIG sd; image2yuvconfig(&frame->img, &sd); - return vp8dx_get_reference(ctx->pbi, frame->frame_type, &sd); + return vp8dx_get_reference(ctx->yv12_frame_buffers.pbi[0], + frame->frame_type, &sd); } else return VPX_CODEC_INVALID_PARAM; @@ -799,10 +817,11 @@ static vpx_codec_err_t vp8_get_last_ref_updates(vpx_codec_alg_priv_t *ctx, va_list args) { int *update_info = va_arg(args, int *); - VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi; - if (update_info) + if (update_info && !ctx->yv12_frame_buffers.use_frame_threads) { + VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0]; + *update_info = pbi->common.refresh_alt_ref_frame * (int) VP8_ALTR_FRAME + pbi->common.refresh_golden_frame * (int) VP8_GOLD_FRAME + pbi->common.refresh_last_frame * (int) VP8_LAST_FRAME; @@ -819,11 +838,11 @@ static vpx_codec_err_t vp8_get_last_ref_frame(vpx_codec_alg_priv_t *ctx, va_list args) { int *ref_info = va_arg(args, int *); - VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi; - VP8_COMMON *oci = &pbi->common; - if (ref_info) + if (ref_info && !ctx->yv12_frame_buffers.use_frame_threads) { + VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0]; + VP8_COMMON *oci = &pbi->common; *ref_info = (vp8dx_references_buffer( oci, ALTREF_FRAME )?VP8_ALTR_FRAME:0) | (vp8dx_references_buffer( oci, GOLDEN_FRAME )?VP8_GOLD_FRAME:0) | @@ -841,10 +860,10 @@ static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx, { int *corrupted = va_arg(args, int *); + VP8D_COMP *pbi = (VP8D_COMP *)ctx->yv12_frame_buffers.pbi[0]; - if (corrupted) + if (corrupted && pbi) { - VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi; *corrupted = pbi->common.frame_to_show->corrupted; return VPX_CODEC_OK; @@ -854,6 +873,25 @@ static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx, } +static vpx_codec_err_t vp8_set_decryptor(vpx_codec_alg_priv_t *ctx, + int ctrl_id, + va_list args) +{ + vp8_decrypt_init *init = va_arg(args, vp8_decrypt_init *); + + if (init) + { + ctx->decrypt_cb = init->decrypt_cb; + ctx->decrypt_state = init->decrypt_state; + } + else + { + ctx->decrypt_cb = NULL; + ctx->decrypt_state = NULL; + } + return VPX_CODEC_OK; +} + vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] = { {VP8_SET_REFERENCE, vp8_set_reference}, @@ -866,6 +904,7 @@ vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] = {VP8D_GET_LAST_REF_UPDATES, vp8_get_last_ref_updates}, {VP8D_GET_FRAME_CORRUPTED, vp8_get_frame_corrupted}, {VP8D_GET_LAST_REF_USED, vp8_get_last_ref_frame}, + {VP8D_SET_DECRYPTOR, vp8_set_decryptor}, { -1, NULL}, }; |