📄 dst_arith_decoder.c
字号:
/*****************************************************************************/
/* Copyright 1998, Hewlett-Packard Company */
/* All rights reserved */
/* File: "dst_arith_decoder.c" */
/* Description: Implementation of non-macro arithmetic decoder functions */
/* Author: David Taubman */
/* Affiliation: Hewlett-Packard and */
/* The University of New South Wales, Australia */
/* Version: VM7.0 */
/* Last Revised: 24 March, 2000 */
/*****************************************************************************/
/*****************************************************************************/
/* Modified to incorporate MQ-coder by Mitsubishi Electric Corp. */
/* Copyright 1999, Mitsubishi Electric Corp. */
/* All rights reserved for modified parts */
/*****************************************************************************/
/*****************************************************************************/
/* Modified to speed up MQ-decoder */
/* Copyright 1999 Science Applications International Corporation (SAIC). */
/* All Rights Reserved for modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Modifications tagged with comment lines or delimiters involving the */
/* string, "David T mod" or "mod by David T", have been made by David */
/* Taubman; they are copyrighted by Hewlett-Packard Company with all rights */
/* reserved for the modified parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Substantially modified by David Taubman to support flexible termination */
/* of code stream segments and error resilience capabilities. Copyright */
/* 1999 by Hewlett-Packard Company with all rights reserved for the modified */
/* parts. */
/*****************************************************************************/
/*****************************************************************************/
/* Modified by David Taubman to avoid the need for byte stuffing when resync */
/* markers are in use. This simplifies the code and substantially improves */
/* the usefulness of the system for applications requiring error resilience. */
/* Changes are as follows: a) changed SOT marker to lie within intra-packet */
/* marker range 0xFF90 through 0xFFFF; b) introduced an MQ-like bit-stuffing */
/* policy in packet heads; c) introduced an MQ-like bit-stuffing policy in */
/* the raw bit-stream segments generated by the entropy coder in lazy mode; */
/* d) modified error resilient termination policy for raw bit-stream */
/* to fill unused bits with the simpler code 0101... instead of 1010...; */
/* e) eliminated the use of byte-stuffing with resync markers. In the new */
/* code, none of the packet segments (packet head, MQ segments and raw */
/* segments) may contain any two byte sequence in the range 0xFF90 through */
/* 0xFFFF; moreover, no segment can terminate with a 0xFF, so that the */
/* entire packet is guaranteed to be free of two byte sequences in the above */
/* range. All delimiting markers from the codestream (i.e. SOT, RESYNC and */
/* EOC) are guaranteed to lie within that range. */
/* Copyright 1999 by Hewlett-Packard Company with all */
/* rights reserved for the modified parts. */
/*****************************************************************************/
#include <local_services.h>
#include <assert.h>
#include <stdio.h>
#include "dst_arith_decoder.h"
/* ========================================================================= */
/* --------------------------- Private Macros ------------------------------ */
/* ========================================================================= */
/*****************************************************************************/
/* MACRO get_byte */
/*****************************************************************************/
#define get_byte(_state) \
{ \
if (_state->current_lsb == 0) \
{ \
_state->word = dst_arith_coder__input_word(_state); \
_state->current_lsb = 32; \
} \
_state->current_lsb -= 8; \
assert(_state->current_lsb >= 0); \
_state->mqd.buffer = \
(_state->word >> _state->current_lsb) & 0x00FF; \
}
/* ========================================================================= */
/* ------------------------- Internal Functions ---------------------------- */
/* ========================================================================= */
/*****************************************************************************/
/* STATIC dec_preload */
/*****************************************************************************/
static void
dec_preload(dst_arith_state_ptr state, mqd_var_ptr mqd)
/* creg initialize : 15bit load */
{
int preload = S_DR_PRELOAD;
mqd->creg = dst_arith_coder__bytein(mqd->creg,&(mqd->ct),state);
/* Set buffer <- memory */
mqd->creg = dst_arith_coder__bytein(mqd->creg,&(mqd->ct),state);
/* 1st byte -> creg.B */
mqd->creg <<= mqd->ct;
preload -= mqd->ct;
mqd->creg = dst_arith_coder__bytein(mqd->creg,&(mqd->ct),state);
/* 2nd byte -> creg.B */
mqd->creg <<= preload;
mqd->ct -= preload;
if(mqd->ct == 0)
mqd->creg = dst_arith_coder__bytein(mqd->creg,&(mqd->ct),state);
}
/*****************************************************************************/
/* STATIC init_dec */
/*****************************************************************************/
static void
init_dec(mqd_var_ptr mqd)
{
mqd->areg = DEC_HALF;
mqd->creg = LONG_ZERO;
mqd->buffer = LONG_ZERO;
mqd->ct = 0;
mqd->nextct = NEXTBITS_NML;
mqd->converted_doublets = 0;
mqd->active = 0;
}
/*****************************************************************************/
/* STATIC check_mq_erterm_bits */
/*****************************************************************************/
static int
check_mq_erterm_bits(dst_arith_state_ptr state, std_int last_byte)
{
int approximate_er_bits;
int ct, next_ct, converted_doublets, bits_left, spare_bits;
unsigned long creg;
std_int offset, min_last_byte, max_last_byte;
/* Load required MQ state variables. */
ct = state->mqd.ct;
next_ct = state->mqd.nextct;
creg = state->mqd.creg;
converted_doublets = state->mqd.converted_doublets;
/* Perform checks at the byte level and determine number of bits
contained in the terminating byte beyond the MSB of the C register. */
if (converted_doublets == 1)
{ /* Terminating byte != FF and MSB of C register must be in one of
7 most significant bits of the terminating byte. */
if ((ct == 8) || (next_ct != 8))
return(-1);
bits_left = ct;
}
else if (converted_doublets == 2)
{
if (ct == 8)
{ /* Terminating byte != FF and MSB of C register must be in LSB
of the terminating byte. */
if (next_ct != 7)
return(-1);
bits_left = 0;
}
else
{ /* Terminating byte must be FF. */
last_byte = 0x00FF;
if (ct == 8)
return(-1);
if (next_ct == 7)
bits_left = ct;
else
{
bits_left = 0;
if (ct != 7)
return(-1);
}
}
}
else
return(-1);
/* Now compute the lower and upper bounds on the terminating byte and
hence the number of spare bits in the code space. */
creg >>= (31-bits_left);
offset = (std_int) creg; /* This is the quantity added to the minimum value
for the terminating byte by the encoder. */
if (offset != 0)
return(-1);
min_last_byte = last_byte - offset;
max_last_byte = min_last_byte + (1<<bits_left) - 1;
if (max_last_byte > 255)
max_last_byte = 255;
spare_bits = 8;
while (((1<<spare_bits)-1) > (max_last_byte-min_last_byte))
spare_bits--;
/* Estimate the number of bits of error detection code space and return
this value. Note that the number of bits of effective error detection
code space is equal to -log_2 of the probability that an error would
have violated the length-based checks above, plus the number of spare
bits. To estimate the first quantity more carefully we would need
to know the number of symbols actually decoded. Instead, as a place
holder, we currently assume that approximately half the number of
bits used to signal the segment length are effective as error detection
bits. */
approximate_er_bits = 0;
while ((1<<approximate_er_bits) < state->current_segment_bytes)
approximate_er_bits++;
approximate_er_bits >>= 1;
approximate_er_bits += spare_bits;
return(approximate_er_bits);
}
/*****************************************************************************/
/* STATIC check_raw_erterm_bits */
/*****************************************************************************/
static int
check_raw_erterm_bits(dst_arith_state_ptr state)
{
int spare_bits, approximate_er_bits;
std_int code;
/* Check for correct padding bits in a partially used terminating byte */
spare_bits = 0;
while (state->current_lsb & 7)
{
state->current_lsb--;
code = (state->word >> state->current_lsb) & 1;
spare_bits++;
if (code == (spare_bits & 1))
return(-1);
}
/* Now check that we have at least consumed all necessary bytes. Note
that trailing FF's may have been discarded by the encoder so we might
have read past the end of the available bytes; however, there should
be no excuse for reading too few bytes, with one exception: if the
last bit consumed was the final bit in an FF, the encoder was allowed
to insert a non-FF byte as the last byte in the raw bit-stream --
simplifies some encoder implementations. */
if (!state->final_segment_word_consumed)
{
int unused_bytes;
unused_bytes = state->bytes_left_in_segment -
(state->bytes_in_word - (state->current_lsb >> 3));
if (unused_bytes > 0)
{
if (((state->word >> state->current_lsb) & 0x00FF) == 0x00FF)
unused_bytes--;
if (unused_bytes > 0)
return(-1);
}
}
/* Estimate the number of bits of error detection code space and return
this value. Note that the number of bits of effective error detection
code space is equal to -log_2 of the probability that an error would
have violated the length-based checks above, plus the number of spare
bits. For the first quantity, we currently estimate that approximately
half the number of bits used to signal the segment length are effective
as error detection bits. */
approximate_er_bits = 0;
while ((1<<approximate_er_bits) < state->current_segment_bytes)
approximate_er_bits++;
approximate_er_bits >>= 1;
approximate_er_bits += spare_bits;
return(approximate_er_bits);
}
/* ========================================================================= */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -