public static vpx_codec_err_t vp8_remove_decoder_instances(frame_buffers fb) { VP8D_COMP pbi = fb.pbi[0]; if (pbi != null) { return(vpx_codec_err_t.VPX_CODEC_ERROR); } /* decoder instance for single thread mode */ remove_decompressor(pbi); return(vpx_codec_err_t.VPX_CODEC_OK); }
public static int vp8dx_get_raw_frame(VP8D_COMP pbi, ref YV12_BUFFER_CONFIG sd, out long time_stamp, out long time_end_stamp, ref vp8_ppflags_t flags) { int ret = -1; time_stamp = 0; time_end_stamp = 0; if (pbi.ready_for_new_data == 1) { return(ret); } /* ie no raw frame to show!!! */ if (pbi.common.show_frame == 0) { return(ret); } pbi.ready_for_new_data = 1; time_stamp = pbi.last_time_stamp; time_end_stamp = 0; //(void)flags; if (pbi.common.frame_to_show != null) { sd = pbi.common.frame_to_show; sd.y_width = pbi.common.Width; sd.y_height = pbi.common.Height; sd.uv_height = pbi.common.Height / 2; ret = 0; } else { ret = -1; } // Port AC: Noop in libvpx. //vpx_clear_system_state(); return(ret); }
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); } }
public static VP8D_COMP create_decompressor(VP8D_CONFIG oxcf) { //VP8D_COMP pbi = vpx_memalign(32, sizeof(VP8D_COMP)); //if (!pbi) return NULL; //memset(pbi, 0, sizeof(VP8D_COMP)); VP8D_COMP pbi = new VP8D_COMP(); // Port AC: jmp_buf seems to be being used as kind of like an exception handler. // There's no direct translation for C# and memory allocation errors will generate // runtime exceptions. Should be safe to remove. //if (setjmp(pbi.common.error.jmp)) //{ // pbi.common.error.setjmp = 0; // remove_decompressor(pbi); // return 0; //} //pbi.common.error.setjmp = 1; alloccommon.vp8_create_common(pbi.common); pbi.common.current_video_frame = 0; pbi.ready_for_new_data = 1; /* vp8cx_init_de_quantizer() is first called here. Add check in * frame_init_dequantizer() to avoid * unnecessary calling of vp8cx_init_de_quantizer() for every frame. */ decodeframe.vp8cx_init_de_quantizer(pbi); vp8_loopfilter.vp8_loop_filter_init(pbi.common); //pbi.common.error.setjmp = 0; // Port AC: Assume void cast is a noop to remove compiler warning. //(void)oxcf; pbi.ec_enabled = 0; /* Error concealment is activated after a key frame has been * decoded without errors when error concealment is enabled. */ pbi.ec_active = 0; pbi.decoded_key_frame = 0; /* Independent partitions is activated when a frame updates the * token probability table to have equal probabilities over the * PREV_COEF context. */ pbi.independent_partitions = 0; mbpitch.vp8_setup_block_dptrs(pbi.mb); if (!_isDecoderInitialised) { //once(initialize_dec); initialize_dec(); } return(pbi); }
public static void remove_decompressor(VP8D_COMP pbi) { //vp8_remove_common(pbi.common); //vpx_mem.vpx_free(pbi); }
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 static int vp8_decode_mb_tokens(VP8D_COMP dx, MACROBLOCKD x) { BOOL_DECODER bc = x.current_bc; FRAME_CONTEXT fc = dx.common.fc; //char* eobs = x->eobs; sbyte[] eobs = x.eobs; int i; int nonzeros; int eobtotal = 0; //short* qcoeff_ptr; //ProbaArray coef_probs; //int coefIndex = entropy.COEF_BANDS * entropy.PREV_COEF_CONTEXTS * entropy.ENTROPY_NODES; //ENTROPY_CONTEXT* a_ctx = ((ENTROPY_CONTEXT*)x->above_context); //ENTROPY_CONTEXT* l_ctx = ((ENTROPY_CONTEXT*)x->left_context); //ENTROPY_CONTEXT* a; //ENTROPY_CONTEXT* l; int blockSlice = entropy.COEF_BANDS * entropy.PREV_COEF_CONTEXTS * entropy.ENTROPY_NODES; fixed(byte *pCoefProbs = fc.coef_probs) { byte *coef_probs = null; fixed(sbyte *pAboveCtx = x.above_context.get().y1, pLeftContext = x.left_context.y1) { ENTROPY_CONTEXT *a_ctx = pAboveCtx; ENTROPY_CONTEXT *l_ctx = pLeftContext; ENTROPY_CONTEXT *a; ENTROPY_CONTEXT *l; int skip_dc = 0; //qcoeff_ptr = x.qcoeff[0]; fixed(short *pQcoeff = x.qcoeff) { short *qcoeff_ptr = pQcoeff; if (x.mode_info_context.get().mbmi.is_4x4 == 0) { a = a_ctx + 8; l = l_ctx + 8; //coef_probs = fc.coef_probs[1]; coef_probs = pCoefProbs + blockSlice; nonzeros = GetCoeffs(bc, coef_probs, (*a + *l), 0, qcoeff_ptr + 24 * 16); *a = *l = (sbyte)(nonzeros > 0 ? 1 : 0); eobs[24] = (sbyte)nonzeros; eobtotal += nonzeros - 16; //coef_probs = fc.coef_probs[0]; coef_probs = pCoefProbs; skip_dc = 1; } else { //coef_probs = fc.coef_probs[3]; coef_probs = pCoefProbs + 3 * blockSlice; skip_dc = 0; } for (i = 0; i < 16; ++i) { a = a_ctx + (i & 3); l = l_ctx + ((i & 0xc) >> 2); nonzeros = GetCoeffs(bc, coef_probs, (*a + *l), skip_dc, qcoeff_ptr); *a = *l = (sbyte)(nonzeros > 0 ? 1 : 0); nonzeros += skip_dc; eobs[i] = (sbyte)nonzeros; eobtotal += nonzeros; qcoeff_ptr += 16; } //coef_probs = fc.coef_probs[2]; coef_probs = pCoefProbs + 2 * blockSlice; a_ctx += 4; l_ctx += 4; for (i = 16; i < 24; ++i) { a = a_ctx + ((i > 19 ? 1 : 0) << 1) + (i & 1); l = l_ctx + ((i > 19 ? 1 : 0) << 1) + ((i & 3) > 1 ? 1 : 0); nonzeros = GetCoeffs(bc, coef_probs, (*a + *l), 0, qcoeff_ptr); *a = *l = (sbyte)(nonzeros > 0 ? 1 : 0); eobs[i] = (sbyte)nonzeros; eobtotal += nonzeros; qcoeff_ptr += 16; } } } } return(eobtotal); }