|
|
|
@ -161,23 +161,26 @@ static int ParseSegmentHeader(VP8BitReader* br, |
|
|
|
|
VP8SegmentHeader* hdr, VP8Proba* proba) { |
|
|
|
|
assert(br != NULL); |
|
|
|
|
assert(hdr != NULL); |
|
|
|
|
hdr->use_segment_ = VP8Get(br); |
|
|
|
|
hdr->use_segment_ = VP8Get(br, "global-header"); |
|
|
|
|
if (hdr->use_segment_) { |
|
|
|
|
hdr->update_map_ = VP8Get(br); |
|
|
|
|
if (VP8Get(br)) { // update data
|
|
|
|
|
hdr->update_map_ = VP8Get(br, "global-header"); |
|
|
|
|
if (VP8Get(br, "global-header")) { // update data
|
|
|
|
|
int s; |
|
|
|
|
hdr->absolute_delta_ = VP8Get(br); |
|
|
|
|
hdr->absolute_delta_ = VP8Get(br, "global-header"); |
|
|
|
|
for (s = 0; s < NUM_MB_SEGMENTS; ++s) { |
|
|
|
|
hdr->quantizer_[s] = VP8Get(br) ? VP8GetSignedValue(br, 7) : 0; |
|
|
|
|
hdr->quantizer_[s] = VP8Get(br, "global-header") ? |
|
|
|
|
VP8GetSignedValue(br, 7, "global-header") : 0; |
|
|
|
|
} |
|
|
|
|
for (s = 0; s < NUM_MB_SEGMENTS; ++s) { |
|
|
|
|
hdr->filter_strength_[s] = VP8Get(br) ? VP8GetSignedValue(br, 6) : 0; |
|
|
|
|
hdr->filter_strength_[s] = VP8Get(br, "global-header") ? |
|
|
|
|
VP8GetSignedValue(br, 6, "global-header") : 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (hdr->update_map_) { |
|
|
|
|
int s; |
|
|
|
|
for (s = 0; s < MB_FEATURE_TREE_PROBS; ++s) { |
|
|
|
|
proba->segments_[s] = VP8Get(br) ? VP8GetValue(br, 8) : 255u; |
|
|
|
|
proba->segments_[s] = VP8Get(br, "global-header") ? |
|
|
|
|
VP8GetValue(br, 8, "global-header") : 255u; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
@ -205,7 +208,7 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec, |
|
|
|
|
size_t last_part; |
|
|
|
|
size_t p; |
|
|
|
|
|
|
|
|
|
dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2)) - 1; |
|
|
|
|
dec->num_parts_minus_one_ = (1 << VP8GetValue(br, 2, "global-header")) - 1; |
|
|
|
|
last_part = dec->num_parts_minus_one_; |
|
|
|
|
if (size < 3 * last_part) { |
|
|
|
|
// we can't even read the sizes with sz[]! That's a failure.
|
|
|
|
@ -229,21 +232,21 @@ static VP8StatusCode ParsePartitions(VP8Decoder* const dec, |
|
|
|
|
// Paragraph 9.4
|
|
|
|
|
static int ParseFilterHeader(VP8BitReader* br, VP8Decoder* const dec) { |
|
|
|
|
VP8FilterHeader* const hdr = &dec->filter_hdr_; |
|
|
|
|
hdr->simple_ = VP8Get(br); |
|
|
|
|
hdr->level_ = VP8GetValue(br, 6); |
|
|
|
|
hdr->sharpness_ = VP8GetValue(br, 3); |
|
|
|
|
hdr->use_lf_delta_ = VP8Get(br); |
|
|
|
|
hdr->simple_ = VP8Get(br, "global-header"); |
|
|
|
|
hdr->level_ = VP8GetValue(br, 6, "global-header"); |
|
|
|
|
hdr->sharpness_ = VP8GetValue(br, 3, "global-header"); |
|
|
|
|
hdr->use_lf_delta_ = VP8Get(br, "global-header"); |
|
|
|
|
if (hdr->use_lf_delta_) { |
|
|
|
|
if (VP8Get(br)) { // update lf-delta?
|
|
|
|
|
if (VP8Get(br, "global-header")) { // update lf-delta?
|
|
|
|
|
int i; |
|
|
|
|
for (i = 0; i < NUM_REF_LF_DELTAS; ++i) { |
|
|
|
|
if (VP8Get(br)) { |
|
|
|
|
hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6); |
|
|
|
|
if (VP8Get(br, "global-header")) { |
|
|
|
|
hdr->ref_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for (i = 0; i < NUM_MODE_LF_DELTAS; ++i) { |
|
|
|
|
if (VP8Get(br)) { |
|
|
|
|
hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6); |
|
|
|
|
if (VP8Get(br, "global-header")) { |
|
|
|
|
hdr->mode_lf_delta_[i] = VP8GetSignedValue(br, 6, "global-header"); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -352,8 +355,8 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { |
|
|
|
|
buf_size -= frm_hdr->partition_length_; |
|
|
|
|
|
|
|
|
|
if (frm_hdr->key_frame_) { |
|
|
|
|
pic_hdr->colorspace_ = VP8Get(br); |
|
|
|
|
pic_hdr->clamp_type_ = VP8Get(br); |
|
|
|
|
pic_hdr->colorspace_ = VP8Get(br, "global-header"); |
|
|
|
|
pic_hdr->clamp_type_ = VP8Get(br, "global-header"); |
|
|
|
|
} |
|
|
|
|
if (!ParseSegmentHeader(br, &dec->segment_hdr_, &dec->proba_)) { |
|
|
|
|
return VP8SetError(dec, VP8_STATUS_BITSTREAM_ERROR, |
|
|
|
@ -378,7 +381,7 @@ int VP8GetHeaders(VP8Decoder* const dec, VP8Io* const io) { |
|
|
|
|
"Not a key frame."); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
VP8Get(br); // ignore the value of update_proba_
|
|
|
|
|
VP8Get(br, "global-header"); // ignore the value of update_proba_
|
|
|
|
|
|
|
|
|
|
VP8ParseProba(br, dec); |
|
|
|
|
|
|
|
|
@ -403,28 +406,28 @@ static const uint8_t kZigzag[16] = { |
|
|
|
|
// See section 13-2: http://tools.ietf.org/html/rfc6386#section-13.2
|
|
|
|
|
static int GetLargeValue(VP8BitReader* const br, const uint8_t* const p) { |
|
|
|
|
int v; |
|
|
|
|
if (!VP8GetBit(br, p[3])) { |
|
|
|
|
if (!VP8GetBit(br, p[4])) { |
|
|
|
|
if (!VP8GetBit(br, p[3], "coeffs")) { |
|
|
|
|
if (!VP8GetBit(br, p[4], "coeffs")) { |
|
|
|
|
v = 2; |
|
|
|
|
} else { |
|
|
|
|
v = 3 + VP8GetBit(br, p[5]); |
|
|
|
|
v = 3 + VP8GetBit(br, p[5], "coeffs"); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
if (!VP8GetBit(br, p[6])) { |
|
|
|
|
if (!VP8GetBit(br, p[7])) { |
|
|
|
|
v = 5 + VP8GetBit(br, 159); |
|
|
|
|
if (!VP8GetBit(br, p[6], "coeffs")) { |
|
|
|
|
if (!VP8GetBit(br, p[7], "coeffs")) { |
|
|
|
|
v = 5 + VP8GetBit(br, 159, "coeffs"); |
|
|
|
|
} else { |
|
|
|
|
v = 7 + 2 * VP8GetBit(br, 165); |
|
|
|
|
v += VP8GetBit(br, 145); |
|
|
|
|
v = 7 + 2 * VP8GetBit(br, 165, "coeffs"); |
|
|
|
|
v += VP8GetBit(br, 145, "coeffs"); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
const uint8_t* tab; |
|
|
|
|
const int bit1 = VP8GetBit(br, p[8]); |
|
|
|
|
const int bit0 = VP8GetBit(br, p[9 + bit1]); |
|
|
|
|
const int bit1 = VP8GetBit(br, p[8], "coeffs"); |
|
|
|
|
const int bit0 = VP8GetBit(br, p[9 + bit1], "coeffs"); |
|
|
|
|
const int cat = 2 * bit1 + bit0; |
|
|
|
|
v = 0; |
|
|
|
|
for (tab = kCat3456[cat]; *tab; ++tab) { |
|
|
|
|
v += v + VP8GetBit(br, *tab); |
|
|
|
|
v += v + VP8GetBit(br, *tab, "coeffs"); |
|
|
|
|
} |
|
|
|
|
v += 3 + (8 << cat); |
|
|
|
|
} |
|
|
|
@ -438,24 +441,24 @@ static int GetCoeffsFast(VP8BitReader* const br, |
|
|
|
|
int ctx, const quant_t dq, int n, int16_t* out) { |
|
|
|
|
const uint8_t* p = prob[n]->probas_[ctx]; |
|
|
|
|
for (; n < 16; ++n) { |
|
|
|
|
if (!VP8GetBit(br, p[0])) { |
|
|
|
|
if (!VP8GetBit(br, p[0], "coeffs")) { |
|
|
|
|
return n; // previous coeff was last non-zero coeff
|
|
|
|
|
} |
|
|
|
|
while (!VP8GetBit(br, p[1])) { // sequence of zero coeffs
|
|
|
|
|
while (!VP8GetBit(br, p[1], "coeffs")) { // sequence of zero coeffs
|
|
|
|
|
p = prob[++n]->probas_[0]; |
|
|
|
|
if (n == 16) return 16; |
|
|
|
|
} |
|
|
|
|
{ // non zero coeff
|
|
|
|
|
const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0]; |
|
|
|
|
int v; |
|
|
|
|
if (!VP8GetBit(br, p[2])) { |
|
|
|
|
if (!VP8GetBit(br, p[2], "coeffs")) { |
|
|
|
|
v = 1; |
|
|
|
|
p = p_ctx[1]; |
|
|
|
|
} else { |
|
|
|
|
v = GetLargeValue(br, p); |
|
|
|
|
p = p_ctx[2]; |
|
|
|
|
} |
|
|
|
|
out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0]; |
|
|
|
|
out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return 16; |
|
|
|
@ -468,24 +471,24 @@ static int GetCoeffsAlt(VP8BitReader* const br, |
|
|
|
|
int ctx, const quant_t dq, int n, int16_t* out) { |
|
|
|
|
const uint8_t* p = prob[n]->probas_[ctx]; |
|
|
|
|
for (; n < 16; ++n) { |
|
|
|
|
if (!VP8GetBitAlt(br, p[0])) { |
|
|
|
|
if (!VP8GetBitAlt(br, p[0], "coeffs")) { |
|
|
|
|
return n; // previous coeff was last non-zero coeff
|
|
|
|
|
} |
|
|
|
|
while (!VP8GetBitAlt(br, p[1])) { // sequence of zero coeffs
|
|
|
|
|
while (!VP8GetBitAlt(br, p[1], "coeffs")) { // sequence of zero coeffs
|
|
|
|
|
p = prob[++n]->probas_[0]; |
|
|
|
|
if (n == 16) return 16; |
|
|
|
|
} |
|
|
|
|
{ // non zero coeff
|
|
|
|
|
const VP8ProbaArray* const p_ctx = &prob[n + 1]->probas_[0]; |
|
|
|
|
int v; |
|
|
|
|
if (!VP8GetBitAlt(br, p[2])) { |
|
|
|
|
if (!VP8GetBitAlt(br, p[2], "coeffs")) { |
|
|
|
|
v = 1; |
|
|
|
|
p = p_ctx[1]; |
|
|
|
|
} else { |
|
|
|
|
v = GetLargeValue(br, p); |
|
|
|
|
p = p_ctx[2]; |
|
|
|
|
} |
|
|
|
|
out[kZigzag[n]] = VP8GetSigned(br, v) * dq[n > 0]; |
|
|
|
|
out[kZigzag[n]] = VP8GetSigned(br, v, "coeffs") * dq[n > 0]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return 16; |
|
|
|
|