static vpx_image_t vp8_get_frame(vpx_codec_alg_priv_t ctx, vpx_codec_iter_t iter) { vpx_image_t img = null; /* iter acts as a flip flop, so an image is only returned on the first * call to get_frame. */ if (iter == IntPtr.Zero && ctx.yv12_frame_buffers.pbi[0] != null) { YV12_BUFFER_CONFIG sd = new YV12_BUFFER_CONFIG(); long time_stamp = 0, time_end_stamp = 0; vp8_ppflags_t flags = new vp8_ppflags_t(); // Port AC: ppflags struct will be initialised to zero by default. //vp8_zero(flags); //if ([email protected]_flags & VPX_CODEC_USE_POSTPROC) { // flags.post_proc_flag = ctx->postproc_cfg.post_proc_flag; // flags.deblocking_level = ctx->postproc_cfg.deblocking_level; // flags.noise_level = ctx->postproc_cfg.noise_level; //} if (0 == onyxd.vp8dx_get_raw_frame(ctx.yv12_frame_buffers.pbi[0], ref sd, out time_stamp, out time_end_stamp, ref flags)) { yuvconfig2image(ctx.img, sd, ctx.user_priv); img = ctx.img; //*iter = img; } } return(img); }
internal static vpx_codec_err_t vp8_destroy(vpx_codec_alg_priv_t ctx) { onyxd.vp8_remove_decoder_instances(ctx.yv12_frame_buffers); //vpx_free(ctx); return(vpx_codec_err_t.VPX_CODEC_OK); }
public static vpx_codec_err_t update_error_state(vpx_codec_alg_priv_t ctx, vpx_internal_error_info error) { vpx_codec_err_t res = error.error_code; if (res != vpx_codec_err_t.VPX_CODEC_OK) { [email protected]_detail = error.has_detail > 0 ? error.detail : null; } return(res); }
/// <summary> /// Update the input fragment data. /// </summary> /// <param name="ctx"></param> /// <param name="data"></param> /// <param name="data_sz"></param> /// <param name="res"></param> /// <returns> /// <=0: Error. /// 1: OK. /// </returns> public unsafe static int update_fragments(vpx_codec_alg_priv_t ctx, byte *data, uint data_sz, out vpx_codec_err_t res) { res = vpx_codec_err_t.VPX_CODEC_OK; if (ctx.fragments.count == 0) { /* New frame, reset fragment pointers and sizes */ //memset((void*)ctx.fragments.ptrs, 0, sizeof(ctx.fragments.ptrs)); //memset(ctx.fragments.sizes, 0, sizeof(ctx.fragments.sizes)); Array.Clear(ctx.fragments.ptrs, 0, ctx.fragments.ptrs.Length); Array.Clear(ctx.fragments.sizes, 0, ctx.fragments.sizes.Length); } if (ctx.fragments.enabled > 0 && !(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 << (int)TOKEN_PARTITION.EIGHT_PARTITION) + 1) { ctx.fragments.count = 0; res = vpx_codec_err_t.VPX_CODEC_INVALID_PARAM; return(-1); } return(0); } if (ctx.fragments.enabled == 0 && (data == null && data_sz == 0)) { return(0); } if (ctx.fragments.enabled == 0) { ctx.fragments.ptrs[0] = data; ctx.fragments.sizes[0] = data_sz; ctx.fragments.count = 1; } return(1); }
private static int vp8_init_ctx(vpx_codec_ctx_t ctx) { //vpx_codec_alg_priv_t priv = (vpx_codec_alg_priv_t)vpx_calloc(1, sizeof(*priv)); //if (!priv) return 1; vpx_codec_alg_priv_t priv = new vpx_codec_alg_priv_t(); //ctx.priv = new vpx_codec_priv_t(); ctx.priv = new vpx_codec_alg_priv_t(); //ctx.priv.init_flags = ctx.init_flags; //priv.si.sz = sizeof(priv->si); //priv.decrypt_cb = null; //priv.decrypt_state = IntPtr.Zero; //if (ctx.dec_cfg != null) { /* Update the reference to the config structure to an internal copy. */ //priv.cfg = *ctx->config.dec; ctx.dec_cfg = priv.cfg; //&priv->cfg; //} return(0); }
public unsafe static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t ctx, byte *data, uint data_sz, IntPtr user_priv, long deadline) { try { vpx_codec_err_t res = vpx_codec_err_t.VPX_CODEC_OK; uint resolution_change = 0; uint w, h; if (ctx.fragments.enabled == 0 && data == null && data_sz == 0) { return(0); } /* Update the input fragment data */ if (update_fragments(ctx, data, data_sz, out 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. */ w = ctx.si.w; h = ctx.si.h; //res = vp8_peek_si_internal(ctx.fragments.ptrs[0], ctx.fragments.sizes[0], // ctx.si, ctx.decrypt_cb, ctx.decrypt_state); res = vp8_peek_si_internal(ctx.fragments.ptrs[0], ctx.fragments.sizes[0], ref ctx.si, null, IntPtr.Zero); if (res == vpx_codec_err_t.VPX_CODEC_UNSUP_BITSTREAM && ctx.si.is_kf == 0) { /* the peek function returns an error for non keyframes, however for * this case, it is not an error */ res = vpx_codec_err_t.VPX_CODEC_OK; } if (ctx.decoder_init == 0 && ctx.si.is_kf == 0) { res = vpx_codec_err_t.VPX_CODEC_UNSUP_BITSTREAM; } if ((ctx.si.h != h) || (ctx.si.w != w)) { resolution_change = 1; } /* Initialize the decoder instance on the first frame*/ if (res == vpx_codec_err_t.VPX_CODEC_OK && ctx.decoder_init == 0) { VP8D_CONFIG oxcf = new VP8D_CONFIG(); oxcf.Width = (int)ctx.si.w; oxcf.Height = (int)ctx.si.h; oxcf.Version = 9; oxcf.postprocess = 0; oxcf.max_threads = (int)ctx.cfg.threads; oxcf.error_concealment = (int)([email protected]_flags & vpx_decoder.VPX_CODEC_USE_ERROR_CONCEALMENT); res = onyxd.vp8_create_decoder_instances(ctx.yv12_frame_buffers, oxcf); if (res == vpx_codec_err_t.VPX_CODEC_OK) { ctx.decoder_init = 1; } } if (res == vpx_codec_err_t.VPX_CODEC_OK) { VP8D_COMP pbi = ctx.yv12_frame_buffers.pbi[0]; VP8_COMMON pc = pbi.common; if (resolution_change > 0) { MACROBLOCKD xd = pbi.mb; pc.Width = (int)ctx.si.w; pc.Height = (int)ctx.si.h; { int prev_mb_rows = pc.mb_rows; // Port AC: TODO identify alternative error mechanism. //if (setjmp(pbi.common.error.jmp)) //{ // pbi.common.error.setjmp = 0; // /* on failure clear the cached resolution to ensure a full // * reallocation is attempted on resync. */ // ctx.si.w = 0; // ctx.si.h = 0; // vpx_clear_system_state(); // /* same return value as used in vp8dx_receive_compressed_data */ // return -1; //} //pbi.common.error.setjmp = 1; if (pc.Width <= 0) { pc.Width = (int)w; vpx_codec.vpx_internal_error(ref pc.error, vpx_codec_err_t.VPX_CODEC_CORRUPT_FRAME, "Invalid frame width"); } if (pc.Height <= 0) { pc.Height = (int)h; vpx_codec.vpx_internal_error(ref pc.error, vpx_codec_err_t.VPX_CODEC_CORRUPT_FRAME, "Invalid frame height"); } if (alloccommon.vp8_alloc_frame_buffers(pc, pc.Width, pc.Height) != 0) { vpx_codec.vpx_internal_error(ref pc.error, vpx_codec_err_t.VPX_CODEC_MEM_ERROR, "Failed to allocate frame buffers"); } xd.pre = pc.yv12_fb[pc.lst_fb_idx]; xd.dst = pc.yv12_fb[pc.new_fb_idx]; mbpitch.vp8_build_block_doffsets(pbi.mb); // Port AC: Assume this cast was a noop to remove compiler warning. //(void)prev_mb_rows; } // Port AC: TODO identify alternative error mechanism. //pbi.common.error.setjmp = 0; /* required to get past the first get_free_fb() call */ pbi.common.fb_idx_ref_cnt[0] = 0; } // Port AC: TODO identify alternative error mechanism. //if (setjmp(pbi.common.error.jmp)) //{ // vpx_clear_system_state(); // /* We do not know if the missing frame(s) was supposed to update // * any of the reference buffers, but we act conservative and // * mark only the last buffer as corrupted. // */ // pc.yv12_fb[pc.lst_fb_idx].corrupted = 1; // if (pc.fb_idx_ref_cnt[pc.new_fb_idx] > 0) // { // pc.fb_idx_ref_cnt[pc.new_fb_idx]--; // } // pc.error.setjmp = 0; // res = update_error_state(ctx, pbi.common.error); // return res; //} //pbi.common.error.setjmp = 1; /* update the pbi fragment data */ pbi.fragments = ctx.fragments; ctx.user_priv = user_priv; if (onyxd.vp8dx_receive_compressed_data(pbi, deadline) != 0) { res = update_error_state(ctx, pbi.common.error); } /* get ready for the next series of fragments */ ctx.fragments.count = 0; } return(res); } catch (VpxException vpxExcp) { return(vpxExcp.ErrorCode); } }