UNPKG

jsvpx

Version:

Javascript implementation of libvpx

412 lines (342 loc) 13.4 kB
'use strict'; var blockd = require('../common/blockd.js'); var vp8_block2left = blockd.vp8_block2left; var vp8_block2above = blockd.vp8_block2above; var bitreader = require('../../vpx_dsp/bitreader.js'); var vpx_read = bitreader.vpx_read; var vpx_read_bit = bitreader.vpx_read_bit; var c_utils = require('../../util/c_utils.js'); var memset = c_utils.memset; var B_PRED = 4; var SPLITMV = 9; var TOKEN_BLOCK_Y1 = 0; var TOKEN_BLOCK_UV = 1; var TOKEN_BLOCK_Y2 = 2; var TOKEN_BLOCK_TYPES = 3; var EOB_CONTEXT_NODE = 0; var ZERO_CONTEXT_NODE = 1; var ONE_CONTEXT_NODE = 2; var LOW_VAL_CONTEXT_NODE = 3; var TWO_CONTEXT_NODE = 4; var THREE_CONTEXT_NODE = 5; var HIGH_LOW_CONTEXT_NODE = 6; var CAT_ONE_CONTEXT_NODE = 7; var CAT_THREEFOUR_CONTEXT_NODE = 8; var CAT_THREE_CONTEXT_NODE = 9; var CAT_FIVE_CONTEXT_NODE = 10; var DCT_VAL_CATEGORY1 = 5; var DCT_VAL_CATEGORY2 = 6; var DCT_VAL_CATEGORY3 = 7; var DCT_VAL_CATEGORY4 = 8; var DCT_VAL_CATEGORY5 = 9; var DCT_VAL_CATEGORY6 = 10; var ENTROPY_NODES = 11; /** * Comparable to vp8_reset_mb_tokens_context * @param {type} left * @param {type} above * @param {type} mode * @returns {null} */ var context_clear = new Uint32Array(8); function vp8_reset_mb_tokens_context(left, above, mode) { /* Reset the macroblock context on the left and right. We have to * preserve the context of the second order block if this mode * would not have updated it. */ left.set(context_clear); above.set(context_clear); //memset(left, 0, 0, 8); //memset(above, 0, 0, 8); if (mode !== B_PRED && mode !== SPLITMV) { left[8] = 0; above[8] = 0; } } function X(n) { return ((n) * 33); //PREV_COEF_CONTEXTS * ENTROPY_NODES } var bands_x = new Int32Array([ X(0), X(1), X(2), X(3), X(6), X(4), X(5), X(6), X(6), X(6), X(6), X(6), X(6), X(6), X(6), X(7) ]); var extrabits = [ {min_val: 0, length: -1, probs: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])}, //ZERO_TOKEN {min_val: 1, length: 0, probs: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])}, //ONE_TOKEN {min_val: 2, length: 0, probs: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])}, //TWO_TOKEN {min_val: 3, length: 0, probs: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])}, //THREE_TOKEN {min_val: 4, length: 0, probs: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])}, //FOUR_TOKEN {min_val: 5, length: 0, probs: new Uint8Array([159, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])}, //DCT_VAL_CATEGORY1 {min_val: 7, length: 1, probs: new Uint8Array([145, 165, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])}, //DCT_VAL_CATEGORY2 {min_val: 11, length: 2, probs: new Uint8Array([140, 148, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0])}, //DCT_VAL_CATEGORY3 {min_val: 19, length: 3, probs: new Uint8Array([135, 140, 155, 176, 0, 0, 0, 0, 0, 0, 0, 0])}, //DCT_VAL_CATEGORY4 {min_val: 35, length: 4, probs: new Uint8Array([130, 134, 141, 157, 180, 0, 0, 0, 0, 0, 0, 0])}, //DCT_VAL_CATEGORY5 {min_val: 67, length: 10, probs: new Uint8Array([129, 130, 133, 140, 153, 177, 196, 230, 243, 254, 254, 0])}, //DCT_VAL_CATEGORY6 {min_val: 0, length: -1, probs: new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])} // EOB TOKEN ]; var zigzag = new Uint32Array([ 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 ]); var BLOCK_LOOP = 0, DO_WHILE = 1, CHECK_0_ = 2, CAT_FIVE_CONTEXT_NODE_0_ = 3, CAT_THREEFOUR_CONTEXT_NODE_0_ = 4, CAT_THREE_CONTEXT_NODE_0_ = 5, HIGH_LOW_CONTEXT_NODE_0_ = 6, CAT_ONE_CONTEXT_NODE_0_ = 7, LOW_VAL_CONTEXT_NODE_0_ = 8, THREE_CONTEXT_NODE_0_ = 9, TWO_CONTEXT_NODE_0_ = 10, ONE_CONTEXT_NODE_0_ = 11, BLOCK_FINISHED = 12, END = 13; var i = 0, stopp = 0, type = 0; var c = 0, t = 0, v = 0; var val = 0, bits_count = 0; var eob_mask = 0; var b_tokens = 0; var b_tokens_off = 0;//* /* tokens for this block */ var type_probs = 0; var type_probs_off = 0;//* /* probabilities for this block type */ var prob = 0; var prob_off = 0;//* var dqf = 0; var global_bool; var goto_; function DECODE_AND_APPLYSIGN(value_to_sign) { if (vpx_read_bit(global_bool) === 1) { v = -value_to_sign * dqf[(!!c) + 0]; } else { v = value_to_sign * dqf[(!!c) + 0]; } } function DECODE_AND_BRANCH_IF_ZERO(probability, branch) { if (!vpx_read(global_bool, probability)) { goto_ = branch; return 1; } } function DECODE_EXTRABIT_AND_ADJUST_VAL(t, bits_count) { val += vpx_read(global_bool, extrabits[t].probs[bits_count]) << bits_count; } function DECODE_AND_LOOP_IF_ZERO(probability, branch) { if (!vpx_read(global_bool, probability)) { prob_off = type_probs_off; if (c < 15) { ++c; prob_off += bands_x[c] | 0; goto_ = branch; return 1; } else { goto_ = BLOCK_FINISHED; return 1; /*for malformed input */ } } } function DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) { DECODE_AND_APPLYSIGN(val); prob_off = type_probs_off + 22;//(ENTROPY_NODES * 2) if (c < 15) { b_tokens[b_tokens_off + zigzag[c]] = v; ++c; goto_ = DO_WHILE; return 1; } b_tokens[b_tokens_off + zigzag[15]] = v; goto_ = BLOCK_FINISHED; return 1; } function decode_mb_tokens(bool, left, above, tokens, tokens_off, mode, probs, factor) { global_bool = bool; //* eob_mask = 0; if (mode !== B_PRED && mode !== SPLITMV) { i = 24; stopp = 24; type = 1; b_tokens = tokens; b_tokens_off = tokens_off + 384; dqf = factor[TOKEN_BLOCK_Y2]; } else { i = 0; stopp = 16; type = 3; b_tokens = tokens; b_tokens_off = tokens_off; dqf = factor[TOKEN_BLOCK_Y1]; } /* Save a pointer to the coefficient probs for the current type. * Need to repeat this whenever type changes. */ type_probs = probs; /*[type][0][0];*/ type_probs_off = type * 264; //COEF_BANDS * PREV_COEF_CONTEXTS * ENTROPY_NODES; //8 * 3 * 11 goto_ = BLOCK_LOOP; do { if (goto_ === BLOCK_LOOP) { t = left[vp8_block2left[i]] + above[vp8_block2above[i]]; c = (!type) + 0; /* all blocks start at 0 except type 0, which starts * at 1. */ prob = type_probs; prob_off = type_probs_off; prob_off += t * ENTROPY_NODES; goto_ = DO_WHILE; } if (goto_ === DO_WHILE) { prob_off += bands_x[c]; if (DECODE_AND_BRANCH_IF_ZERO(prob[prob_off + EOB_CONTEXT_NODE], BLOCK_FINISHED)) continue; goto_ = CHECK_0_; } if (goto_ === CHECK_0_) { if (DECODE_AND_LOOP_IF_ZERO(prob[prob_off + ZERO_CONTEXT_NODE], CHECK_0_) === 1) continue; if (DECODE_AND_BRANCH_IF_ZERO(prob[prob_off + ONE_CONTEXT_NODE], ONE_CONTEXT_NODE_0_) === 1) continue; if (DECODE_AND_BRANCH_IF_ZERO(prob[prob_off + LOW_VAL_CONTEXT_NODE], LOW_VAL_CONTEXT_NODE_0_) === 1) continue; if (DECODE_AND_BRANCH_IF_ZERO(prob[prob_off + HIGH_LOW_CONTEXT_NODE], HIGH_LOW_CONTEXT_NODE_0_) === 1) continue; if (DECODE_AND_BRANCH_IF_ZERO(prob[prob_off + CAT_THREEFOUR_CONTEXT_NODE], CAT_THREEFOUR_CONTEXT_NODE_0_) === 1) continue; if (DECODE_AND_BRANCH_IF_ZERO(prob[prob_off + CAT_FIVE_CONTEXT_NODE], CAT_FIVE_CONTEXT_NODE_0_) === 1) continue; val = extrabits[DCT_VAL_CATEGORY6].min_val; bits_count = extrabits[DCT_VAL_CATEGORY6].length; do { DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY6, bits_count); bits_count--; } while (bits_count >= 0); if (DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) === 1) continue; } if (goto_ === CAT_FIVE_CONTEXT_NODE_0_) { val = extrabits[DCT_VAL_CATEGORY5].min_val; DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 4); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 3); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 2); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 1); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY5, 0); if (DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) === 1) continue; } if (goto_ === CAT_THREEFOUR_CONTEXT_NODE_0_) { if (DECODE_AND_BRANCH_IF_ZERO(prob[prob_off + CAT_THREE_CONTEXT_NODE], CAT_THREE_CONTEXT_NODE_0_) === 1) continue; val = extrabits[DCT_VAL_CATEGORY4].min_val; DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 3); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 2); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 1); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY4, 0); if (DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) === 1) continue; } if (goto_ === CAT_THREE_CONTEXT_NODE_0_) { val = extrabits[DCT_VAL_CATEGORY3].min_val; DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 2); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 1); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY3, 0); if (DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) === 1) continue; } if (goto_ === HIGH_LOW_CONTEXT_NODE_0_) { if (DECODE_AND_BRANCH_IF_ZERO(prob[prob_off + CAT_ONE_CONTEXT_NODE], CAT_ONE_CONTEXT_NODE_0_) === 1) continue; val = extrabits[DCT_VAL_CATEGORY2].min_val; DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 1); DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY2, 0); if (DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) === 1) continue; } if (goto_ === CAT_ONE_CONTEXT_NODE_0_) { val = extrabits[DCT_VAL_CATEGORY1].min_val; DECODE_EXTRABIT_AND_ADJUST_VAL(DCT_VAL_CATEGORY1, 0); if (DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(val) === 1) continue; } if (goto_ === LOW_VAL_CONTEXT_NODE_0_) { if (DECODE_AND_BRANCH_IF_ZERO(prob[prob_off + TWO_CONTEXT_NODE], TWO_CONTEXT_NODE_0_)) continue; if (DECODE_AND_BRANCH_IF_ZERO(prob[prob_off + THREE_CONTEXT_NODE], THREE_CONTEXT_NODE_0_)) continue; if (DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(4)) continue; } if (goto_ === THREE_CONTEXT_NODE_0_) { if (DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(3)) continue; } if (goto_ === TWO_CONTEXT_NODE_0_) { if (DECODE_SIGN_WRITE_COEFF_AND_CHECK_EXIT(2)) continue; } if (goto_ === ONE_CONTEXT_NODE_0_) { DECODE_AND_APPLYSIGN(1); prob_off = type_probs_off + ENTROPY_NODES; if (c < 15) { b_tokens[b_tokens_off + zigzag[c]] = v; ++c; goto_ = DO_WHILE; continue; } b_tokens[b_tokens_off + zigzag[15]] = v; goto_ = BLOCK_FINISHED; } if (goto_ === BLOCK_FINISHED) { eob_mask = (eob_mask | ((c > 1) + 0 << i)) >>> 0; t = (c != !type) + 0; // any nonzero data? eob_mask = (eob_mask | (t << 31)) >>> 0;//intBitLeft(t , 31); left[vp8_block2left[i]] = above[vp8_block2above[i]] = t; b_tokens_off += 16; i++; if (i < stopp) { goto_ = BLOCK_LOOP; continue; } if (i === 25) { type = 0; i = 0; stopp = 16; type_probs_off = type << 8;//type_probs = probs[type][0][0]; //COEF_BANDS * PREV_COEF_CONTEXTS * ENTROPY_NODES b_tokens_off = tokens_off; dqf = factor[TOKEN_BLOCK_Y1]; goto_ = BLOCK_LOOP; continue; } if (i === 16) { type = 2; type_probs_off = type * 264;//type_probs = probs[type][0][0]; stopp = 24; dqf = factor[TOKEN_BLOCK_UV]; goto_ = BLOCK_LOOP; continue; } } goto_ = END; } while (goto_ !== END); return eob_mask; } module.exports = {}; module.exports.decode_mb_tokens = decode_mb_tokens; module.exports.vp8_reset_mb_tokens_context = vp8_reset_mb_tokens_context;