/* * 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. */ //:Ignore ////////////////////////////////////////////////////////////////////////// // // FileName: CVLCDecoder.cpp // // Date Created: 15/01/1999 // // Author: Youssef Ouaghli // // Description: CVLCDecoder class definition. // // Last Modified: $Dmae: 1999/08/26 15:41:08 $ // // RCS Id: $Id: CVLCDecoder.cpp,v 1.47 1999/08/26 15:41:08 youag Exp $ // // $Rma: CVLCDecoder.cpp,v $ // Revision 1.47 1999/08/26 15:41:08 youag // New context: (PrevContext + PrevSymbol) / 2 instead of PrevSymbol // // Revision 1.46 1999/06/01 14:30:48 youag // Small change // // Revision 1.45 1999/05/27 11:05:59 youag // Removing un-needed parameters in CodeQuadrantDC()/DecodeQuadrantDC functions // // Revision 1.44 1999/05/21 15:34:35 youag // Replacing speed_nb_bits() by speed_csize() // // Revision 1.43 1999/05/21 14:45:01 youag // CVLCCoder & CVLCDecoder bad param testing done // // Revision 1.42 1999/05/21 10:28:39 youag // Computing/Getting WT bloc max coef inside CVLCCoder::Code()/CVLCDecoder::Decode() // to avoid possible trap with the interface // // Revision 1.41 1999/05/20 13:59:21 youag // Coding DC quadrant coefs using DPCM // // Revision 1.40 1999/05/20 13:19:43 youag // Correcting coding/decoding of DC quadrant when nbBit is zero // // Revision 1.39 1999/05/20 13:03:29 youag // Coding/Decoding the DC quadrant as a separate case // // Revision 1.38 1999/05/20 12:28:19 youag // Added Assert in CVLCCoder::CodeQuadrant for better testing of the class // // Revision 1.37 1999/05/18 12:20:20 youag // Renaming ac, m_Ac into ad, m_Ad for CACDecoder class // // Revision 1.36 1999/05/11 16:08:51 youag // Removing CVLCCodec::m_Mod optimization beacause of strange effect // during decompression on ALPHA (execution time is doubled) // // Revision 1.35 1999/05/11 15:54:54 youag // CVLCCodec::m_Mod is now an array of pointers. to minimize number of // assembly lines needed to initialize parameter of CACCoder:;CodeSymbol function // // Revision 1.34 1999/05/10 12:04:58 youag // Testing if AC interval rescaling is needed before calling the function // // Revision 1.33 1999/05/10 11:40:01 youag // Cleaning code from unused member functions // // Revision 1.32 1999/05/07 14:08:32 youag // Reduce number of inline functions in order to promote code expansion of // important inline functions // // Revision 1.31 1999/05/07 10:53:43 youag // Checking for CWBuffer size expansion at each 4 bytes // // Revision 1.30 1999/05/06 15:42:32 youag // Reducing use of const & param because of poor assembly code // // Revision 1.29 1999/04/26 13:32:28 youag // Avoiding second test of coding the MPS by using two // CACModel::Update{Mps/Lps} functions // // Revision 1.28 1999/04/20 16:27:39 youag // loop indexes test optimization // // Revision 1.27 1999/04/20 10:47:01 youag // Testing some loop indexes against 0: // Replacing for (i=0 ; i m_NbBitCoef) return false; if (nbBit) { m_Mod = m_Models[nbBit++]; if (!m_Mod[0].IsInitialized()) for (unsigned int i = 0; i <= nbBit; i++) m_Mod[i].Initialize(nbBit + 1); int oldCoef = 1UL << (nbBit - 2); unsigned int context = nbBit; int *p = o_Wblk.GetData()[0]; const unsigned int w = o_Wblk.GetW(); for (int i = i_H; i > 0; i--, p += w) { for (unsigned int j = i_W; j; j--) { int c; context = (context + DecodeCoef(context, c)) >> 1; *p++ = (oldCoef += c); } if (--i) { p += w; for (unsigned int j = i_W; j; j--) { int c; context = (context + DecodeCoef(context, c)) >> 1; *--p = (oldCoef += c); } } } } else { for (int i = i_H - 1; i >= 0; i--) { int *p = o_Wblk.GetData()[i]; for (unsigned int j = i_W; j; j--) *p++ = 0; } } return true; COMP_CATCHTHIS } bool CVLCDecoder::DecodeQuadrant(CWBlock &o_Wblk, const unsigned int i_X, const unsigned int i_Y, const unsigned int i_W, const unsigned int i_H, const unsigned int i_Level, const unsigned int i_Quadrant) { COMP_TRYTHIS unsigned int nbBit = m_Ad.DecodeBits(m_NbBitNbBitCoef); if (nbBit > m_NbBitCoef) return false; const unsigned int coefShift = i_Level >= m_NbLossyBitPlane ? 0 : m_NbLossyBitPlane - i_Level - (i_Quadrant > m_NbLossyQuadrant ? 1 : 0); if (nbBit > coefShift) { nbBit -= coefShift; m_Mod = m_Models[nbBit - 1]; if (!m_Mod[0].IsInitialized()) for (unsigned int i = 0; i <= nbBit; i++) m_Mod[i].Initialize(nbBit + 1); unsigned int context = nbBit; int *p = o_Wblk.GetData()[i_Y] + i_X; const unsigned int w = o_Wblk.GetW(); if (!coefShift) for (int i = i_H; i > 0; i--, p += w) { for (unsigned int j = i_W; j; j--) context = (context + DecodeCoef(context, *p++)) >> 1; if (--i) { p += w; for (unsigned int j = i_W; j; j--) context = (context + DecodeCoef(context, *--p)) >> 1; } } else for (int i = i_H; i > 0; i--, p += w) { for (unsigned int j = i_W; j; j--) { int c; context = (context + DecodeCoef(context, c)) >> 1; *p++ = c << coefShift; } if (--i) { p += w; for (unsigned int j = i_W; j; j--) { int c; context = (context + DecodeCoef(context, c)) >> 1; *--p = c << coefShift; } } } } else { const unsigned int endY = i_Y + i_H; for (unsigned int i = i_Y; i < endY; i++) { int *p = o_Wblk.GetData()[i] + i_X; for (unsigned int j = i_W; j; j--) *p++ = 0; } } return true; COMP_CATCHTHIS } void CVLCDecoder::RefineLossyQuadrant(CWBlock &o_Wblk, const unsigned int i_X, const unsigned int i_Y, const unsigned int i_W, const unsigned int i_H, const unsigned int i_Level, const unsigned int i_Quadrant) { COMP_TRYTHIS_SPEED if (m_NbLossyBitPlane > (i_Level + 1 + (i_Quadrant > m_NbLossyQuadrant ? 1 : 0))) { const int cT = (1L << (m_NbLossyBitPlane - i_Level - (i_Quadrant > m_NbLossyQuadrant ? 2 : 1))) - 1; const unsigned int endY = i_Y + i_H; for (unsigned int i = i_Y; i < endY; i++) { int *p = o_Wblk.GetData()[i] + i_X; for (unsigned int j = i_W; j; j--, p++) { int c; if ((c = *p)) { if (c > 0) *p |= cT; else *p = -(-c | cT); } } } } COMP_CATCHTHIS_SPEED } void CVLCDecoder::RefineLossy(CWBlock &o_Wblk) { COMP_TRYTHIS unsigned int w = o_Wblk.GetW() >> m_NbIteWt; unsigned int h = o_Wblk.GetH() >> m_NbIteWt; unsigned int m = m_NbIteWt; unsigned int q = m_NbIteWt * 3 - 1; for (unsigned int k = 0; k < m_NbIteWt; k++, w <<= 1, h <<= 1, m--) { RefineLossyQuadrant(o_Wblk, w, 0, w, h, m, q--); RefineLossyQuadrant(o_Wblk, 0, h, w, h, m, q--); RefineLossyQuadrant(o_Wblk, w, h, w, h, m - 1, q--); } COMP_CATCHTHIS } bool CVLCDecoder::Decode(CWBlock &o_Wblk, const unsigned int i_NbIteWt, const unsigned int i_NbLossyBp) { COMP_TRYTHIS // Get the wavelet block max coef amplitude in number of bits const unsigned int nbBit = m_Ad.DecodeBits(5); // To make sure CACDecoder::DecodeBits() will not fail if (nbBit > (c_ACNbBits - 2)) return false; if (nbBit) { static const unsigned int bitPlanes[16] = {0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4}; static const unsigned int quadrants[16] = {0, 0, 0, 2, 3, 0, 2, 3, 5, 6, 0, 2, 3, 5, 6, 9}; Assert(i_NbLossyBp < 16, Util::CParamException()); unsigned int w = o_Wblk.GetW() >> i_NbIteWt; unsigned int h = o_Wblk.GetH() >> i_NbIteWt; // Check the block dimension against the number of wavelet transform iteration Assert((w << i_NbIteWt) == o_Wblk.GetW() || (h << i_NbIteWt) == o_Wblk.GetH(), Util::CParamException()); unsigned int m = i_NbIteWt; unsigned int q = i_NbIteWt * 3; m_NbBitCoef = nbBit; m_NbBitNbBitCoef = speed_csize(nbBit); m_NbIteWt = i_NbIteWt; m_NbLossyBitPlane = bitPlanes[i_NbLossyBp]; m_NbLossyQuadrant = quadrants[i_NbLossyBp]; if (!DecodeQuadrantDC(o_Wblk, w, h, q--)) return false; for (unsigned int k = 0; k < i_NbIteWt; k++, w <<= 1, h <<= 1, m--) { if (!DecodeQuadrant(o_Wblk, w, 0, w, h, m, q--)) return false; if (!DecodeQuadrant(o_Wblk, 0, h, w, h, m, q--)) return false; if (!DecodeQuadrant(o_Wblk, w, h, w, h, m - 1, q--)) return false; } if (i_NbLossyBp > 1) RefineLossy(o_Wblk); } else o_Wblk.Zero(); // nbBit == 0 return true; COMP_CATCHTHIS } } // namespace COMP