/* * Copyright 2011-2019, European Organisation for the Exploitation of Meteorological Satellites (EUMETSAT) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef CACDecoder_included #define CACDecoder_included /******************************************************************************* TYPE: Concrete Class. PURPOSE: This class handles the entropy decoding of symbols by means of arithmetic decoding. FUNCTION: Given a multi-symbols probality model this class allows to decode a sequence of symbols by recovering it from a real number reflecting the probability of the sequence. It also allows decoding a binary sequence using an equi-probable symbols model. The decoding of multi-symbols and equi-probable symbols can be freely mixed using one common input stream. INTERFACES: See 'INTERFACES' in the module declaration below RESOURCES: Heap Memory (>2K). REFERENCE: "Arithmetic Coding for Data Compression"; Witten, Neal & Cleary; Commun. ACM, vol. 30, pp 520-540, June 1987. PROCESSING: The initial decoding range is set to [0, 2^c_ACNbBits[ A value window (c_ACNbBits bits) is initialized so that it contains the c_ACNbBits most significant bits of the real number binary representation. Given the current value window and a symbols probability model, the arithmetic decoder can find the symbol that has been encoded. Each time a symbol is decoded this range is reduced according to the symbol probability. If the range falls below a given size, the current value window is moved right by one or more bits and the range is rescaled. Each time a bit is read from the input buffer, we look for the presence of a marker; a flag is activated if a marker is present and the read is canceled. DATA: See 'DATA :' in the class header below. LOGIC: *******************************************************************************/ #include #include "RMAErrorHandling.h" #include "CBuffer.h" #include "WTConst.h" #include "CACModel.h" namespace COMP { class CACDecoder { private: // DATA : const unsigned __int32 c_TopValue; // range maximum size - 1 const unsigned __int32 c_FirstQtr; // a quarter of the range maximum size unsigned __int32 m_Value; // current value window unsigned __int32 m_Range; // current range bool m_MarkerReached; // flag indicating if a marker has been eaten CRBuffer &m_Buf; // the input buffer // PRIVATE FUNCTIONS : // Description: Read a binary string form the input stream. // Returns: The binary string. unsigned __int32 InputBits( const unsigned int i_NbBits // the number of bits in the binary string ) { COMP_TRYTHIS_SPEED #ifdef _DEBUG Assert(i_NbBits > 0 && i_NbBits <= 32, Util::CParamException()); #endif if (m_Buf.in_marker(i_NbBits)) { m_MarkerReached = true; #ifdef _DEBUG std::cerr << "Reading a marker !" << std::endl; #endif return 0; } const unsigned __int32 bits = m_Buf.read32() >> (32U - i_NbBits); m_Buf.seek(i_NbBits); return bits; COMP_CATCHTHIS_SPEED } // Description: Eventually rescale the decoding range and move the value window. // Returns: Nothing. void UpdateInterval(); public: // INTERFACES : // Description: Constructor. // Returns: Nothing. CACDecoder( CRBuffer &i_Buf // the input buffer ) : c_TopValue((1UL << c_ACNbBits) - 1), c_FirstQtr(1UL << (c_ACNbBits - 2)), m_Buf(i_Buf) { } // Description: Tell if a marker was found during previous read of the input buffer. // Returns: true if a marker was found, false otherwise. bool IsMarkerReached() const { return m_MarkerReached; } // Description: Start and initialise the arithmetic decoding. // Returns: Nothing. void Start() { COMP_TRYTHIS m_MarkerReached = false; m_Range = c_TopValue + 1UL; m_Value = InputBits(c_ACNbBits); COMP_CATCHTHIS } // Description: Decode a symbol using a multi-symbols probability model. // Returns: The symbol decoded. unsigned int DecodeSymbol( CACModel &i_Mod // the multi-symbols probability model ); // Description: Decode a binary sequence using an equi-probable symbols model. // Returns: The binary sequence. unsigned __int32 DecodeBits( const unsigned int i_NbBits // the number of bits of the sequence ) { COMP_TRYTHIS_SPEED #ifdef _DEBUG Assert(i_NbBits > 0 && i_NbBits <= (c_ACNbBits - 2), Util::CParamException()); #endif m_Range >>= i_NbBits; const unsigned __int32 bits = m_Value / m_Range; m_Value -= bits * m_Range; if (m_Range <= c_FirstQtr) UpdateInterval(); return bits; COMP_CATCHTHIS_SPEED } // Description: Decode a bit using an equi-probable symbols model. // Returns: The bit decoded. unsigned __int32 DecodeBit() { COMP_TRYTHIS_SPEED m_Range >>= 1; const unsigned __int32 bit = m_Value >= m_Range ? 1UL : 0UL; if (bit) m_Value -= m_Range; if (m_Range <= c_FirstQtr) UpdateInterval(); return bit; COMP_CATCHTHIS_SPEED } // Description: Stop the arithmetic decoding. // Returns: Nothing. void Stop() { } }; } // end namespace #endif