public static void vp8_init_mbmode_probs(VP8_COMMON x) { //memcpy(x.fc.ymode_prob, vp8_entropymodeldata.vp8_ymode_prob, sizeof(vp8_ymode_prob)); //memcpy(x.fc.uv_mode_prob, vp8_entropymodeldata.vp8_uv_mode_prob, sizeof(vp8_uv_mode_prob)); //memcpy(x.fc.sub_mv_ref_prob, sub_mv_ref_prob, sizeof(sub_mv_ref_prob)); Array.Copy(vp8_entropymodedata.vp8_ymode_prob, x.fc.ymode_prob, vp8_entropymodedata.vp8_ymode_prob.Length); Array.Copy(vp8_entropymodedata.vp8_uv_mode_prob, x.fc.uv_mode_prob, vp8_entropymodedata.vp8_uv_mode_prob.Length); Array.Copy(sub_mv_ref_prob, x.fc.sub_mv_ref_prob, x.fc.sub_mv_ref_prob.Length); }
private static int get_free_fb(VP8_COMMON cm) { int i; for (i = 0; i < VP8_COMMON.NUM_YV12_BUFFERS; ++i) { if (cm.fb_idx_ref_cnt[i] == 0) { break; } } //assert(i < NUM_YV12_BUFFERS); cm.fb_idx_ref_cnt[i] = 1; return(i); }
public static void vp8_de_alloc_frame_buffers(VP8_COMMON oci) { int i; for (i = 0; i < VP8_COMMON.NUM_YV12_BUFFERS; ++i) { yv12config.vp8_yv12_de_alloc_frame_buffer(ref oci.yv12_fb[i]); } yv12config.vp8_yv12_de_alloc_frame_buffer(ref oci.temp_scale_frame); //vpx_mem.vpx_free(oci.above_context); //vpx_mem.vpx_free(oci.mip); oci.above_context = null; oci.mip = null; }
public static void vp8_setup_version(VP8_COMMON cm) { switch (cm.version) { case 0: cm.no_lpf = 0; cm.filter_type = LOOPFILTERTYPE.NORMAL_LOOPFILTER; cm.use_bilinear_mc_filter = 0; cm.full_pixel = 0; break; case 1: cm.no_lpf = 0; cm.filter_type = LOOPFILTERTYPE.SIMPLE_LOOPFILTER; cm.use_bilinear_mc_filter = 1; cm.full_pixel = 0; break; case 2: cm.no_lpf = 1; cm.filter_type = LOOPFILTERTYPE.NORMAL_LOOPFILTER; cm.use_bilinear_mc_filter = 1; cm.full_pixel = 0; break; case 3: cm.no_lpf = 1; cm.filter_type = LOOPFILTERTYPE.SIMPLE_LOOPFILTER; cm.use_bilinear_mc_filter = 1; cm.full_pixel = 1; break; default: /*4,5,6,7 are reserved for future use*/ cm.no_lpf = 0; cm.filter_type = LOOPFILTERTYPE.NORMAL_LOOPFILTER; cm.use_bilinear_mc_filter = 0; cm.full_pixel = 0; break; } }
public static void vp8_create_common(VP8_COMMON oci) { systemdependent.vp8_machine_specific_config(oci); entropymode.vp8_init_mbmode_probs(oci); entropymode.vp8_default_bmode_probs(oci.fc.bmode_prob); oci.mb_no_coeff_skip = 1; oci.no_lpf = 0; oci.filter_type = LOOPFILTERTYPE.NORMAL_LOOPFILTER; oci.use_bilinear_mc_filter = 0; oci.full_pixel = 0; oci.multi_token_partition = TOKEN_PARTITION.ONE_PARTITION; oci.clamp_type = CLAMP_TYPE.RECON_CLAMP_REQUIRED; /* Initialize reference frame sign bias structure to defaults */ //memset(oci.ref_frame_sign_bias, 0, sizeof(oci->ref_frame_sign_bias)); /* Default disable buffer to buffer copying */ oci.copy_buffer_to_gf = 0; oci.copy_buffer_to_arf = 0; }
public static int check_fragments_for_errors(VP8D_COMP pbi) { if (pbi.ec_active == 0 && pbi.fragments.count <= 1 && pbi.fragments.sizes[0] == 0) { VP8_COMMON cm = pbi.common; /* If error concealment is disabled we won't signal missing frames * to the decoder. */ if (cm.fb_idx_ref_cnt[cm.lst_fb_idx] > 1) { /* The last reference shares buffer with another reference * buffer. Move it to its own buffer before setting it as * corrupt, otherwise we will make multiple buffers corrupt. */ int prev_idx = cm.lst_fb_idx; cm.fb_idx_ref_cnt[prev_idx]--; cm.lst_fb_idx = get_free_fb(cm); yv12extend.vp8_yv12_copy_frame(cm.yv12_fb[prev_idx], cm.yv12_fb[cm.lst_fb_idx]); } /* This is used to signal that we are missing frames. * 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. */ cm.yv12_fb[cm.lst_fb_idx].corrupted = 1; /* Signal that we have no frame to show. */ cm.show_frame = 0; /* Nothing more to do. */ return(0); } return(1); }
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); } }
/* If any buffer copy / swapping is signalled it should be done here. */ public static int swap_frame_buffers(VP8_COMMON cm) { int err = 0; /* The alternate reference frame or golden frame can be updated * using the new, last, or golden/alt ref frame. If it * is updated using the newly decoded frame it is a refresh. * An update using the last or golden/alt ref frame is a copy. */ if (cm.copy_buffer_to_arf > 0) { int new_fb = 0; if (cm.copy_buffer_to_arf == 1) { new_fb = cm.lst_fb_idx; } else if (cm.copy_buffer_to_arf == 2) { new_fb = cm.gld_fb_idx; } else { err = -1; } ref_cnt_fb(cm.fb_idx_ref_cnt, ref cm.alt_fb_idx, new_fb); } if (cm.copy_buffer_to_gf > 0) { int new_fb = 0; if (cm.copy_buffer_to_gf == 1) { new_fb = cm.lst_fb_idx; } else if (cm.copy_buffer_to_gf == 2) { new_fb = cm.alt_fb_idx; } else { err = -1; } ref_cnt_fb(cm.fb_idx_ref_cnt, ref cm.gld_fb_idx, new_fb); } if (cm.refresh_golden_frame > 0) { ref_cnt_fb(cm.fb_idx_ref_cnt, ref cm.gld_fb_idx, cm.new_fb_idx); } if (cm.refresh_alt_ref_frame > 0) { ref_cnt_fb(cm.fb_idx_ref_cnt, ref cm.alt_fb_idx, cm.new_fb_idx); } if (cm.refresh_last_frame > 0) { ref_cnt_fb(cm.fb_idx_ref_cnt, ref cm.lst_fb_idx, cm.new_fb_idx); cm.frame_to_show = cm.yv12_fb[cm.lst_fb_idx]; } else { cm.frame_to_show = cm.yv12_fb[cm.new_fb_idx]; } cm.fb_idx_ref_cnt[cm.new_fb_idx]--; return(err); }
public static int vp8dx_receive_compressed_data(VP8D_COMP pbi, Int64 time_stamp) { VP8_COMMON cm = pbi.common; int retcode = -1; pbi.common.error.error_code = vpx_codec_err_t.VPX_CODEC_OK; retcode = check_fragments_for_errors(pbi); if (retcode <= 0) { return(retcode); } cm.new_fb_idx = get_free_fb(cm); /* setup reference frames for vp8_decode_frame */ pbi.dec_fb_ref[(int)MV_REFERENCE_FRAME.INTRA_FRAME] = cm.yv12_fb[cm.new_fb_idx]; pbi.dec_fb_ref[(int)MV_REFERENCE_FRAME.LAST_FRAME] = cm.yv12_fb[cm.lst_fb_idx]; pbi.dec_fb_ref[(int)MV_REFERENCE_FRAME.GOLDEN_FRAME] = cm.yv12_fb[cm.gld_fb_idx]; pbi.dec_fb_ref[(int)MV_REFERENCE_FRAME.ALTREF_FRAME] = cm.yv12_fb[cm.alt_fb_idx]; retcode = decodeframe.vp8_decode_frame(pbi); if (retcode < 0) { if (cm.fb_idx_ref_cnt[cm.new_fb_idx] > 0) { cm.fb_idx_ref_cnt[cm.new_fb_idx]--; } pbi.common.error.error_code = vpx_codec_err_t.VPX_CODEC_ERROR; // Propagate the error info. if (pbi.mb.error_info.error_code != vpx_codec_err_t.VPX_CODEC_ERROR) { pbi.common.error.error_code = pbi.mb.error_info.error_code; //memcpy(pbi.common.error.detail, pbi.mb.error_info.detail, // sizeof(pbi.mb.error_info.detail)); pbi.common.error.detail = pbi.mb.error_info.detail; } goto decode_exit; } if (swap_frame_buffers(cm) != 0) { pbi.common.error.error_code = vpx_codec_err_t.VPX_CODEC_ERROR; goto decode_exit; } //vpx_clear_system_state(); if (cm.show_frame > 0) { cm.current_video_frame++; cm.show_frame_mi = cm.mi; } pbi.ready_for_new_data = 0; pbi.last_time_stamp = time_stamp; decode_exit: //vpx_clear_system_state(); return(retcode); }
public unsafe static int vp8_alloc_frame_buffers(VP8_COMMON oci, int width, int height) { int i; vp8_de_alloc_frame_buffers(oci); /* our internal buffers are always multiples of 16 */ if ((width & 0xf) != 0) { width += 16 - (width & 0xf); } if ((height & 0xf) != 0) { height += 16 - (height & 0xf); } for (i = 0; i < VP8_COMMON.NUM_YV12_BUFFERS; ++i) { oci.fb_idx_ref_cnt[i] = 0; oci.yv12_fb[i].flags = 0; if (yv12config.vp8_yv12_alloc_frame_buffer(ref oci.yv12_fb[i], width, height, yv12config.VP8BORDERINPIXELS) < 0) { goto allocation_fail; } } oci.new_fb_idx = 0; oci.lst_fb_idx = 1; oci.gld_fb_idx = 2; oci.alt_fb_idx = 3; oci.fb_idx_ref_cnt[0] = 1; oci.fb_idx_ref_cnt[1] = 1; oci.fb_idx_ref_cnt[2] = 1; oci.fb_idx_ref_cnt[3] = 1; if (yv12config.vp8_yv12_alloc_frame_buffer(ref oci.temp_scale_frame, width, 16, yv12config.VP8BORDERINPIXELS) < 0) { goto allocation_fail; } oci.mb_rows = height >> 4; oci.mb_cols = width >> 4; oci.MBs = oci.mb_rows * oci.mb_cols; oci.mode_info_stride = oci.mb_cols + 1; //oci.mip = vpx_calloc((oci.mb_cols + 1) * (oci.mb_rows + 1), sizeof(MODE_INFO)); oci.mip = new MODE_INFO[(oci.mb_cols + 1) * (oci.mb_rows + 1)]; // Port AC: NASTY, highly inefficient. Need to find a better way but running into problems // with C# only supporting fixed arrays of primitive types. Would need to re-design the // MODE_INFO.b_mode_info etc. C data structure which would then deviate significantly from // C code and make future maintenance difficult. for (int ii = 0; ii < oci.mip.Length; ii++) { oci.mip[ii] = new MODE_INFO(); } //if (!oci->mip) goto allocation_fail; //oci.mi = oci.mip + oci.mode_info_stride + 1; //oci.mi = oci.mip[oci.mode_info_stride + 1]; oci.mi = new ArrPtr <MODE_INFO>(oci.mip, oci.mode_info_stride + 1); /* Allocation of previous mode info will be done in vp8_decode_frame() * as it is a decoder only data */ //oci->above_context = //vpx_calloc(sizeof(ENTROPY_CONTEXT_PLANES) * oci->mb_cols, 1); oci.above_context = new ENTROPY_CONTEXT_PLANES[oci.mb_cols]; //if (!oci.above_context) goto allocation_fail; return(0); allocation_fail: vp8_de_alloc_frame_buffers(oci); return(1); }
public static void vp8_remove_common(VP8_COMMON oci) { vp8_de_alloc_frame_buffers(oci); }
public static void vp8_default_coef_probs(VP8_COMMON pc) { //memcpy(pc->fc.coef_probs, default_coef_probs, sizeof(default_coef_probs)); Array.Copy(default_coef_probs_c.default_coef_probs, pc.fc.coef_probs, default_coef_probs_c.default_coef_probs.Length); }