--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/imagingmodules/jp2kcodec/Src/JP2KEntropyDecoder.cpp Thu Dec 17 09:22:31 2009 +0200
@@ -0,0 +1,1857 @@
+/*
+* Copyright (c) 2003, 2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Entropy decoder functionality..
+*
+*/
+
+
+// INCLUDE FILES
+#include "JP2KCodeBlock.h"
+#include "JP2KTileInfo.h"
+#include "JP2KImageInfo.h"
+#include "JP2KEntropyDecoder.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+
+// CONSTANTS
+
+// Mq decoder state information, all of the 47 states contain
+// the probability estimate of LPS in hexadecimal, the next
+// mps state index, the next lps state index and the flag
+// indicating a mps switch.
+const TUint32 KMqQeStates[KNumberOriginalMQEntries] = {0x5601,0x3401,0x1801,0x0ac1,0x0521,0x0221,0x5601,
+ 0x5401,0x4801,0x3801,0x3001,0x2401,0x1c01,0x1601,
+ 0x5601,0x5401,0x5101,0x4801,0x3801,0x3401,0x3001,
+ 0x2801,0x2401,0x2201,0x1c01,0x1801,0x1601,0x1401,
+ 0x1201,0x1101,0x0ac1,0x09c1,0x08a1,0x0521,0x0441,
+ 0x02a1,0x0221,0x0141,0x0111,0x0085,0x0049,0x0025,
+ 0x0015,0x0009,0x0005,0x0001,0x5601};
+
+const TInt32 KMqMpsStates[KNumberOriginalMQEntries] = {1,2,3,4,5,38,7,8,9,10,11,12,13,29,15,16,17,18,19,
+ 20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,
+ 36,37,38,39,40,41,42,43,44,45,45,46};
+
+const TInt32 KMqLpsStates[KNumberOriginalMQEntries] = {1,6,9,12,29,33,6,14,14,14,17,18,20,21,14,14,15,16,
+ 17,18,19,19,20,21,22,23,24,25,26,27,28,29,30,31,
+ 32,33,34,35,36,37,38,39,40,41,42,43,46};
+
+const TInt32 KMqSwitchFlagStates[KNumberOriginalMQEntries] = {1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0};
+
+// MQCoder initial states
+const TInt32 KMqInitStates[KNumberContexts] = {46,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// J2KEntropyStream::ReadByteFromStream
+// Read a byte from the input stream
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+TUint8 J2KEntropyStream::ReadByteFromStream()
+ {
+ if ( iPosition < iNumBytes )
+ {
+ return ( TUint8 )iBuffer[iPosition++];
+ }
+ else
+ {
+ // 0xFF to represent EOF
+ return ( 0xFF );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// J2KEntropyStream::ReadBitFromStream
+// Read a bit from the input stream
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+TUint8 J2KEntropyStream::ReadBitFromStream()
+ {
+ if ( iTinyBufferPos == 0 )
+ {
+ // Input the byte buffer
+ iTinyBuffer = ReadByteFromStream();
+
+ if ( iDelayedFF )
+ {
+ iTinyBufferPos = 7;
+ }
+ else
+ {
+ iTinyBufferPos = 8;
+ }
+
+ if ( iTinyBuffer != 0xFF ) // No bit-stuffing needed
+ {
+ iDelayedFF = 0;
+ }
+ else // We need to do bit stuffing on next byte
+ {
+ iDelayedFF = 1;
+ }
+ }
+
+ return (TUint8)( ( iTinyBuffer >> ( --iTinyBufferPos ) ) & 0x01 );
+ }
+
+// -----------------------------------------------------------------------------
+// J2KEntropyStream::CheckPrediction
+// Check a prediction termination for raw coding
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+TEntropyErrorState J2KEntropyStream::CheckPrediction()
+ {
+ // Error resilient sequence in last byte
+ TInt32 errorResSeq = 0;
+
+ // If tiny buffer is empty and equal to 0xFF,
+ // get the next byte for error resilience marker
+ if ( iTinyBufferPos == 0 && iTinyBuffer == 0xFF )
+ {
+ iTinyBuffer = ReadByteFromStream();
+ iTinyBufferPos = 7;
+ }
+
+ // Search for the error resilience marker
+ if ( iTinyBufferPos > 0 )
+ {
+ // Get the error resilience sequence
+ errorResSeq = iTinyBuffer & ( ( 1 << iTinyBufferPos ) - 1 );
+
+ // Compare the read error resilience marker to the constant 01010101 byte
+ if ( errorResSeq != ( KErrorResilienceTermination >> ( 8 - iTinyBufferPos ) ) )
+ {
+ return EEntropyCodingError;
+ }
+ }
+
+ // If we are not at the end of this stream,
+ // next byte should be smaller than 0x80.
+ if ( iPosition < iNumBytes )
+ {
+ if ( iTinyBuffer == 0xFF && iTinyBufferPos == 1 )
+ {
+ if ( ReadByteFromStream() >= 0x80 )
+ {
+ return EEntropyCodingError;
+ }
+ }
+ else
+ {
+ if ( ReadByteFromStream() != 0xFF )
+ {
+ return EEntropyCodingError;
+ }
+ }
+ }
+
+ // No error detected
+ return ENoError;
+ }
+
+// -----------------------------------------------------------------------------
+// J2KEntropyStream::ResetInputStream
+// Reset the input stream
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void J2KEntropyStream::ResetInputStream()
+ {
+ // Initialize the stream parameters. Note that stream->position is not reset here,
+ // it is reset only when the stream is created for the first time.
+ iTinyBuffer = 0;
+ iTinyBufferPos = 0;
+ iDelayedFF = 0;
+ }
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// Destructor
+J2KMQCoder::~J2KMQCoder()
+ {
+ iOriginalStates.ResetAndDestroy();
+ iContextList.ResetAndDestroy();
+ }
+
+// -----------------------------------------------------------------------------
+// J2KMQCoder::MqByteIn
+// Read a byte from the input stream
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void J2KMQCoder::MqByteIn()
+ {
+ if ( !iMarker )
+ {
+ if ( iB == 0xff )
+ {
+ iB = iInputStream.ReadByteFromStream();
+
+ if ( iB > 0x8f )
+ {
+ iMarker = 1;
+ iCT = 8;
+ }
+ else
+ {
+ iC += 0xFE00 - ( iB << 9 );
+ iCT = 7;
+ }
+ }
+ else
+ {
+ iB = iInputStream.ReadByteFromStream();
+ iC += 0xFF00 - ( iB << 8 );
+ iCT = 8;
+ }
+ }
+ else
+ {
+ iCT = 8;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// J2KMQCoder::MqDecodeSymbol
+// Decode the symbol
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+TUint8 J2KMQCoder::MqDecodeSymbol( TInt32 aContextIndex )
+ {
+ // Set the current context to point to the right place in the context list
+ iCurrentContext = iContextList[aContextIndex];
+ iCurrentState = iCurrentContext->iState;
+
+ iA -= iCurrentState->iQe;
+
+ // Decision returned ( i.e. decoded symbol )
+ TInt32 decision = 0;
+ if ( ( iC >> 16 ) < iA ) // Chigh >= A
+ {
+ MpsExchange( decision );
+ }
+ else // lps exchange
+ {
+ LpsExchange( decision );
+ }
+
+ // Return decision
+ return (TUint8)decision;
+ }
+
+// -----------------------------------------------------------------------------
+// J2KMQCoder::MqInitDecoder
+// Initialize the MQCoder
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void J2KMQCoder::MqInitDecoder()
+ {
+ iMarker = 0;
+ iB = iInputStream.ReadByteFromStream();
+
+ // Software conventions decoder initialization
+ iC = ( iB ^ 0xFF ) << 16;
+ MqByteIn();
+
+ iC <<= 7;
+ iCT -= 7;
+ iA = 0x8000;
+ }
+
+// -----------------------------------------------------------------------------
+// J2KMQCoder::MqCheckPrediction
+// Check the prediction termination
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+TEntropyErrorState J2KMQCoder::MqCheckPrediction()
+ {
+ // If no marker was found, B should be == 0xFF and counter zero,
+ // otherwise there is an error
+ if ( !iMarker && ( iCT != 0 || iB != 0xFF ) )
+ {
+ return EEntropyCodingError;
+ }
+
+ // If counter CT is 1, no need to check any further
+ if ( iCT == 1 )
+ {
+ return ENoError;
+ }
+
+ // If counter CT is zero, then next byte must be larger than 0x8F, if the terminating
+ // marker has not been reached yet
+ if ( iCT == 0 )
+ {
+ if ( !iMarker )
+ {
+ // Get next byte and check that it is larger than 0x8F
+ iB = iInputStream.ReadByteFromStream();
+ if ( iB <= 0x8F )
+ {
+ return EEntropyCodingError;
+ }
+ }
+ // Set the counter back to 8
+ iCT = 8;
+ }
+
+ // Number of bits that where added in the termination process
+ // Compute the number of bits, k for error resilience information
+ TUint32 k = (TUint32)( iCT - 1 );
+
+ // Check for a coded LPS.
+ TUint32 q = 0x8000 >> k;
+
+ // Check that we can decode an LPS interval of probability 'q'
+ iA -= q;
+ if ( ( iC >> 16 ) < iA ) // software convention
+ {
+ // MPS interval was decoded, thus error occured
+ return EEntropyCodingError;
+ }
+
+ // Check for coded LPS interval.
+ iA = q;
+
+ do // Renormalization
+ {
+ if ( iCT == 0 )
+ {
+ MqByteIn();
+ }
+
+ iA <<= 1;
+ iC <<= 1;
+ iCT--;
+
+ } while ( iA < 0x8000 );
+
+ // No error was found
+ return ENoError;
+ }
+
+// -----------------------------------------------------------------------------
+// J2KMQCoder::ResetMqContexts
+// Reset the MQCoder context list to the original state
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void J2KMQCoder::ResetMqContexts()
+ {
+ // Reset all context states to initial states and set the mps
+ // of every context to 0.
+ for ( TInt32 i = KNumberContexts - 1; i >= 0; i-- )
+ {
+ iContextList[i]->iState = iOriginalStates[KMqInitStates[i]];
+ iContextList[i]->iMPS = 0;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// J2KMQCoder::ResetMQDecoder
+// Initialze MQCoder and reset the context
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void J2KMQCoder::ResetMQDecoder( TInt32 aSegmentLength )
+ {
+ // Reset all contexts ( states and mps )
+ ResetMqContexts();
+ iInputStream.ResetInputStream();
+ iInputStream.iPosition = 0;
+ iInputStream.iNumBytes = aSegmentLength;
+ MqInitDecoder();
+ }
+
+// -----------------------------------------------------------------------------
+// J2KMQCoder::InitializeOrigMqTable
+// Initialize MQCoder original states table
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void J2KMQCoder::InitializeOrigMqTable()
+ {
+ for ( TUint8 i = 0; i < KNumberOriginalMQEntries; i++ )
+ {
+ iOriginalStates[i]->iQe = KMqQeStates[i];
+ iOriginalStates[i]->iNextMPS = iOriginalStates[KMqMpsStates[i]];
+ iOriginalStates[i]->iNextLPS = iOriginalStates[KMqLpsStates[i]];
+ iOriginalStates[i]->iSwitchFlag = KMqSwitchFlagStates[i];
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// J2KMQCoder::ReNormalize
+// Renormalize
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void J2KMQCoder::ReNormalize()
+ {
+ do
+ {
+ if ( iCT == 0 )
+ {
+ MqByteIn();
+ }
+
+ iA <<= 1;
+ iC <<= 1;
+ --iCT;
+ } while ( !( iA & 0x8000 ) );
+ }
+
+// -----------------------------------------------------------------------------
+// J2KMQCoder::MpsExchange
+// MPS exchange
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void J2KMQCoder::MpsExchange( TInt32& aD )
+ {
+ aD = iCurrentContext->iMPS;
+ if ( !( iA & 0x8000 ) )
+ {
+ if ( iA < iCurrentState->iQe )
+ {
+ aD ^= 1;
+ if ( iCurrentState->iSwitchFlag )
+ {
+ iCurrentContext->iMPS ^= 1;
+ }
+
+ iCurrentContext->iState = iCurrentState->iNextLPS;
+ }
+ else
+ {
+ iCurrentContext->iState = iCurrentState->iNextMPS;
+ }
+
+ ReNormalize();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// J2KMQCoder::LpsExchange
+// LPS exchange
+// ( other items were commented in a header ).
+// -----------------------------------------------------------------------------
+//
+void J2KMQCoder::LpsExchange( TInt32& aD )
+ {
+ iC -= iA << 16;
+ aD = iCurrentContext->iMPS;
+ if ( iA < iCurrentState->iQe )
+ {
+ iCurrentContext->iState = iCurrentState->iNextMPS;
+ }
+ else
+ {
+ aD ^= 1;
+ if ( iCurrentState->iSwitchFlag )
+ {
+ iCurrentContext->iMPS ^= 1;
+ }
+
+ iCurrentContext->iState = iCurrentState->iNextLPS;
+ }
+ iA = iCurrentState->iQe;
+ ReNormalize( );
+ }
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CJ2kEntropyDecoder* CJ2kEntropyDecoder::NewL( CJ2kImageInfo& aImageInfo )
+ {
+ CJ2kEntropyDecoder *self = new ( ELeave ) CJ2kEntropyDecoder;
+
+ CleanupStack::PushL( self );
+ self->ConstructL( aImageInfo );
+ CleanupStack::Pop();
+
+ return self;
+ }
+
+// Destructor
+CJ2kEntropyDecoder::~CJ2kEntropyDecoder()
+ {
+ delete iMRLutBuf;
+ iMRLutBuf = 0;
+
+ delete iSCLutBuf;
+ iSCLutBuf = 0;
+
+ delete iZcLutLL;
+ iZcLutLL = 0;
+
+ delete iZcLutHL;
+ iZcLutHL = 0;
+
+ delete iZcLutHH;
+ iZcLutHH = 0;
+
+ TJ2kUtils::Free2DArray( iData );
+ User::Free( iStates );
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::SetNewSizeL
+// Set the size of internal buffer and other control data
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::SetNewSizeL( const TSize& aSize )
+ {
+ if ( aSize.iWidth <= iCurrentSize.iWidth &&
+ aSize.iHeight <= iCurrentSize.iHeight )
+ {
+ return;
+ }
+ else
+ {
+ iCurrentSize = aSize;
+
+ TJ2kUtils::Free2DArray( iData );
+ iData = 0;
+ iData = TJ2kUtils::Alloc2DArrayL( iCurrentSize.iHeight, iCurrentSize.iWidth );
+
+ iMaxBlockWidth = (TUint8)( iCurrentSize.iWidth );
+
+ // We can compute some parameters for entropy decoding here not to compute them for every pass!!!
+ iBlockDataWidth = iMaxBlockWidth;
+ iStateWidth = iMaxBlockWidth + 2;
+ iStateSize = ( iCurrentSize.iHeight + 2 ) * ( iCurrentSize.iWidth + 2 );
+ iDataSamplesPerStripe = iBlockDataWidth * KStripeHeight;
+ iStateSamplesPerStripe = iStateWidth * KStripeHeight;
+
+ TInt16* ptrTemp = STATIC_CAST( TInt16*, User::ReAlloc( iStates, iStateSize * sizeof( TInt16 ) ) );
+ if ( !ptrTemp )
+ {
+ User::Leave( KErrNoMemory );
+ }
+ iStates = ptrTemp;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::SetCurrentZCLUT
+// Set the current pointer to point to the right LUT depending on the current subband
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::SetCurrentZCLUT( TUint8 aBandIndex )
+ {
+ if ( aBandIndex == 1 )
+ {
+ // For HL band
+ iCurrentZcLutPtr = (TUint8*)iZcLutHL->Des().Ptr();
+ }
+ else if ( aBandIndex == 3 )
+ {
+ // For HH band
+ iCurrentZcLutPtr = (TUint8*)iZcLutHH->Des().Ptr();
+ }
+ else
+ {
+ // For LL and LH band
+ iCurrentZcLutPtr = (TUint8*)iZcLutLL->Des().Ptr();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::DecodeCodeblock
+// Decode the coded codeblock
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::DecodeCodeblock( CJ2kCodeBlock& aCodeblock, TUint8 aCblkStyle,
+ TUint8 aMagBits )
+ {
+ TInt32 startBitplane = 0; // The bitplane where coding starts
+ TInt32 endBitplane = 0; // The last coded bitplane
+ TInt32 terminationLength = 0;
+ TUint8 tempPassIndex = 0;
+ TUint8 passIndex = 0;
+
+ iMQDecoder.iInputStream.iBuffer = CONST_CAST( TUint8*, aCodeblock.Data() );
+ TSize codeBlockSize = aCodeblock.CodeBlockCanvas().Size();
+
+ iVerticalCausalContextUsed = ( ( aCblkStyle & EVerticalStripe ) != 0 );
+ iResetContexts = ( ( aCblkStyle & EResetContext ) != 0 );
+ iPredictableTerminationUsed = ( ( aCblkStyle & EPredictableTermination ) != 0 );
+ TUint8 terminateEachPass = ( ( aCblkStyle & ETermination ) != 0 );
+ TUint8 segmentationSymbolsUsed = ( ( aCblkStyle & ESegmentationSymbols ) != 0 );
+ TUint8 arithmeticBypass = ( ( aCblkStyle & EArithmeticBypass ) != 0 );
+ aCodeblock.ResetPassIndex();
+
+
+ // Initialize the stream and the mq coder for this code block:
+ // also set mq coder's stream to point to aCodeblock's stream
+ if ( !arithmeticBypass && !terminateEachPass ) // No termination
+ {
+ iMQDecoder.ResetMQDecoder( aCodeblock.DataLength() );
+ }
+ else
+ {
+ // Compute the length of the first terminated segment. If we are
+ // terminating on each pass, terminated lengths are equal to
+ // codeblock lengths. On the other hand if we are using arithmetic
+ // bypass ( without terminating each pass ), the first termination length
+ // is the codeblock lengths summed up to the point where we have last AC
+ // pass before first raw coding pass.
+
+ if ( terminateEachPass )
+ {
+ terminationLength = aCodeblock.CblkLength( (TUint16)passIndex++ );
+ }
+ else // AC bypass without termination on each pass
+ {
+ // Loop adding codeblock lengths until enough passes have been consumed
+ while ( ( tempPassIndex < KFirstBypassTermIndex ) && ( passIndex <= aCodeblock.LastPass() ) )
+ {
+ tempPassIndex = (TUint8)( tempPassIndex + aCodeblock.PassesPerSegment( passIndex ) );
+ terminationLength = (TUint32)( terminationLength + aCodeblock.CblkLength( passIndex++ ) );
+ }
+ }
+
+ // Now initialize the iMQDecoder with the right terminated length
+ iMQDecoder.ResetMQDecoder( terminationLength );
+ }
+
+ // Initialize data array
+ for ( TInt i = codeBlockSize.iHeight - 1; i >= 0; i-- )
+ {
+ Mem::FillZ( iData[i], codeBlockSize.iWidth * sizeof( TPrecInt ) );
+ }
+
+ // Initialize iStates array
+ Mem::FillZ( iStates, iStateSize * sizeof( TInt16 ) );
+
+ // Compute different bitplanes; empty bitplanes tells how many bitplanes are
+ // empty in this codeblock compared to the whole subband, iStartBitplane gives
+ // the index of the first bitplane to be coded for this block and iEndBitplane
+ // is the index of the last bitplane coded for this codeblock.
+
+ // Compute coded block's magnitude bits
+ aMagBits = (TUint8)( aMagBits - aCodeblock.EmptyBitplanes() );
+ startBitplane = ( KImplementationPrecision - 2 ) - aCodeblock.EmptyBitplanes();
+ endBitplane = startBitplane - aMagBits;
+
+ // Compute the number of stripes for this codeblock
+ iNumStripes = (TUint16)( ( codeBlockSize.iHeight + KStripeHeight - 1 ) / KStripeHeight );
+ iBlockWidth = codeBlockSize.iWidth;
+
+ // Compute the last stripe's height once,
+ // so that we don't have to compute it for all passes!
+ iLastStripeHeight = codeBlockSize.iHeight - ( iNumStripes - 1 ) * KStripeHeight;
+
+ iCurrentBitplane = (TUint8)( startBitplane );
+
+ // First do only the normalization pass
+ iTerminateThisPass = ( terminateEachPass || ( iCurrentBitplane == endBitplane ) );
+
+ CleanupPass( segmentationSymbolsUsed );
+
+ aCodeblock.IncrementPassIndex();
+
+ iCurrentBitplane--;
+
+ // Then repeat the three passes: significance, refinement and normalization
+ // for the remaining bitplanes.
+ while ( aCodeblock.PassIndex() <= aCodeblock.LastPass() )
+ {
+ // Significance pass, terminate only if terminating after each pass
+ iTerminateThisPass = terminateEachPass;
+
+ if ( ( arithmeticBypass == 0 ) || ( aCodeblock.PassIndex() < KFirstLazyPassIndex ) )
+ {
+ if ( terminateEachPass ) // if last pass was terminated, initialize MQ-coder
+ {
+ // Update the number of available TUint8s for this terminated sequence
+ iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex++ );
+ iMQDecoder.MqInitDecoder();
+ }
+
+ SignificancePass();
+ }
+ else
+ {
+ // if we are here, then the previous pass was terminated
+ if ( terminateEachPass )
+ {
+ // Update the number of available bytes for this terminated sequence
+ iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex++ );
+ }
+ else // AC bypass without termination on each pass
+ {
+ // Here we have two cases:
+ // 1. If this codeblock length is for this pass only, then for the terminated length
+ // we have to add the next pass codeblock length also.
+ // 2. This codeblock length is for both this pass ( significance ) and the next pass
+ // ( refinement ). Terminated length is equal to the CblkLength[iPassIndex].
+ if ( aCodeblock.PassesPerSegment( passIndex ) == 2 )
+ {
+ iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex++ );
+ }
+ else
+ {
+ iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex ) +
+ aCodeblock.CblkLength( (TUint16)( passIndex + 1 ) );
+ passIndex += 2;
+ }
+ }
+ iMQDecoder.iInputStream.ResetInputStream();
+ LazySignificancePass();
+ }
+
+ aCodeblock.IncrementPassIndex();
+ if ( aCodeblock.PassIndex() > aCodeblock.LastPass() )
+ {
+ // We have fully decoded this codeblock
+ return;
+ }
+
+ // Magnitude refinement pass, terminate if raw coding or termination after each pass
+ iTerminateThisPass = ( terminateEachPass || ( arithmeticBypass && ( aCodeblock.PassIndex() >
+ KFirstLazyPassIndex ) ) );
+
+ if ( arithmeticBypass == 0 || ( aCodeblock.PassIndex() < KFirstLazyPassIndex ) )
+ {
+ if ( terminateEachPass ) // if previous pass was terminated, initialize MQ-coder
+ {
+ // Update the number of available bytes for this terminated sequence
+ iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex++ );
+ iMQDecoder.MqInitDecoder();
+ }
+
+ RefinementPass();
+ }
+ else
+ {
+ if ( terminateEachPass ) // if previous pass was terminated
+ {
+ // Update the number of available bytes for this terminated sequence
+ iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex++ );
+ iMQDecoder.iInputStream.ResetInputStream();
+ }
+
+ LazyRefinementPass();
+ }
+
+ aCodeblock.IncrementPassIndex();
+ if ( aCodeblock.PassIndex() > aCodeblock.LastPass() )
+ {
+ // We have fully decoded this codeblock
+ return;
+ }
+
+ // Cleanup pass, terminate if coding raw, termination after each pass, last bitplane
+ // before starting raw coding or last bitplane in this codeblock.
+ iTerminateThisPass = ( terminateEachPass || ( iCurrentBitplane == endBitplane ) ||
+ ( arithmeticBypass && ( aCodeblock.PassIndex() >= KFirstLazyPassIndex ) ) );
+
+ // If last ( AC ) pass was terminated, initialize MQ-coder
+ if ( terminateEachPass || ( arithmeticBypass && ( aCodeblock.PassIndex() > KFirstLazyPassIndex ) ) )
+ {
+ // Update the number of available bytes for this terminated sequence
+ iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex++ );
+ iMQDecoder.MqInitDecoder();
+ }
+
+ CleanupPass( segmentationSymbolsUsed );
+
+ aCodeblock.IncrementPassIndex();
+ if ( aCodeblock.PassIndex() > aCodeblock.LastPass() )
+ {
+ // We have fully decoded this codeblock
+ return;
+ }
+
+ // move onto next bitplane
+ if ( iCurrentBitplane == 0 ) // This might happen with 16-bit and ROI
+ {
+ // We have fully decoded this codeblock
+ return;
+ }
+
+ iCurrentBitplane--;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::ConstructL( CJ2kImageInfo& aImageInfo )
+ {
+ iCurrentSize = aImageInfo.MaxBlockSize();
+
+ for ( TUint16 i = 0; i < KNumberContexts; i++ )
+ {
+ J2KEntropyContexts *context = new ( ELeave ) J2KEntropyContexts;
+ CleanupStack::PushL( context );
+ User::LeaveIfError( iMQDecoder.iContextList.Append( context ) );
+ CleanupStack::Pop(1);
+ }
+
+ for ( TUint16 ii = 0; ii < KNumberOriginalMQEntries; ii++ )
+ {
+ J2KEntropyStates *state = new ( ELeave ) J2KEntropyStates;
+ CleanupStack::PushL( state );
+ User::LeaveIfError( iMQDecoder.iOriginalStates.Append( state ) );
+ CleanupStack::Pop(1);
+ }
+
+ // Allocate memory for the SC Look up table
+ iSCLutBuf = HBufC8::NewL( KLutSize );
+ iSCLut = CONST_CAST( TUint8*, iSCLutBuf->Des().Ptr() );
+
+ // Allocate memory for the MR Look up table
+ iMRLutBuf = HBufC8::NewL( KLutSize );
+ iMRLut = CONST_CAST( TUint8*, iMRLutBuf->Des().Ptr() );
+
+ // Allocate memory for the Zero coding Look up table
+ iZcLutLL = HBufC8::NewL( ( 1 << KZcLutBits ) );
+ iZcLutHL = HBufC8::NewL( ( 1 << KZcLutBits ) );
+ iZcLutHH = HBufC8::NewL( ( 1 << KZcLutBits ) );
+
+ iData = TJ2kUtils::Alloc2DArrayL( iCurrentSize.iHeight, iCurrentSize.iWidth );
+
+ iMaxBlockWidth = (TUint16)( iCurrentSize.iWidth );
+
+ // We can compute some parameters for entropy decoding here not to compute them for every pass!!!
+ iBlockDataWidth = iMaxBlockWidth;
+ iStateWidth = iMaxBlockWidth + 2;
+ iStateSize = ( iCurrentSize.iHeight + 2 ) * ( iCurrentSize.iWidth + 2 );
+ iDataSamplesPerStripe = iBlockDataWidth * KStripeHeight;
+ iStateSamplesPerStripe = iStateWidth * KStripeHeight;
+
+ iStates = STATIC_CAST( TInt16*, User::AllocL( iStateSize * sizeof( TInt16 ) ) );
+
+ // Initialization of the MQ tables needed since
+ // the original table could not be used as it was constant!
+ iMQDecoder.InitializeOrigMqTable();
+
+ iMaxBitDepth = 0;
+ for ( TUint16 iii = 0; iii < aImageInfo.NumOfComponents(); ++iii )
+ {
+ iMaxBitDepth = Max( iMaxBitDepth, aImageInfo.DepthOfComponent( iii ) );
+ }
+
+ // Initialize ZC lookup table
+ InitializeZCLut();
+
+ // Initialize SC/MR lookup table
+ InitializeScMrLut();
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::InitializeZCLut
+// Initialize ZC lookup table
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::InitializeZCLut()
+ {
+ // Create pointers for all the ZC LUT's
+ TUint8* iZcLutLLPtr = CONST_CAST( TUint8*, iZcLutLL->Des().Ptr() );
+ TUint8* iZcLutHLPtr = CONST_CAST( TUint8*, iZcLutHL->Des().Ptr() );
+ TUint8* iZcLutHHPtr = CONST_CAST( TUint8*, iZcLutHH->Des().Ptr() );
+
+ TInt32 ctxt = 0;
+ TUint16 sh = 0; // horizontal sum
+ TUint16 sv = 0; // vertical sum
+ TUint16 sd = 0; // diagonal sum
+
+ for ( TUint16 i = 0; i <= KZcMask; i++ )
+ {
+ sh = (TUint16)( ( ( i >> KPositionRight ) & 1 ) + ( ( i >> KPositionLeft ) & 1 ) );
+ sv = (TUint16)( ( ( i >> KPositionDown ) & 1 ) + ( ( i >> KPositionUp ) & 1 ) );
+ sd = (TUint16)( ( ( i >> KPositionUpperLeft ) & 1 ) + ( ( i >> KPositionUpperRight ) & 1 ) +
+ ( ( i >> KPositionLowerLeft ) & 1 ) + ( ( i >> KPositionLowerRight ) & 1 ) );
+
+ if ( sh == 2 )
+ {
+ ctxt = 10;
+ }
+ else if ( sh == 1 )
+ {
+ if ( sv )
+ {
+ ctxt = 9;
+ }
+ else if ( sd )
+ {
+ ctxt = 8;
+ }
+ else
+ {
+ ctxt = 7;
+ }
+ }
+ else
+ {
+ if ( sv )
+ {
+ ctxt = 4 + sv;
+ }
+ else
+ {
+ ctxt = 2 + ( ( sd > 2 ) ? 2 : sd );
+ }
+ }
+
+ iZcLutLLPtr[i] = (TUint8) ctxt;
+
+
+ if ( sv == 2 )
+ {
+ ctxt = 10;
+ }
+ else if ( sv == 1 )
+ {
+ if ( sh )
+ {
+ ctxt = 9;
+ }
+ else if ( sd )
+ {
+ ctxt = 8;
+ }
+ else
+ {
+ ctxt = 7;
+ }
+ }
+ else
+ {
+ if ( sh )
+ {
+ ctxt = 4 + sh;
+ }
+ else
+ {
+ ctxt = 2 + ( ( sd > 2 ) ? 2 : sd );
+ }
+ }
+
+ iZcLutHLPtr[i] = (TUint8) ctxt;
+
+ if ( sd >= 3 )
+ {
+ ctxt = 10;
+ }
+ else if ( sd == 2 )
+ {
+ if ( ( sv + sh ) >= 1 )
+ {
+ ctxt = 9;
+ }
+ else
+ {
+ ctxt = 8;
+ }
+ }
+ else if ( sd == 1 )
+ {
+ ctxt = 5 + ( ( ( sv + sh ) > 2 ) ? 2 : ( sv + sh ) );
+ }
+ else
+ {
+ ctxt = 2 + ( ( ( sv + sh ) > 2 ) ? 2 : ( sv + sh ) );
+ }
+
+ iZcLutHHPtr[i] = (TUint8) ctxt;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::InitializeScMrLut
+// Initialize SC/MR lookup table
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::InitializeScMrLut()
+ {
+ TInt32 ctxt = 0;
+ TInt32 vpos = 0; // vert +
+ TInt32 vneg = 0; // vert -
+ TInt32 hpos = 0; // hor +
+ TInt32 hneg = 0; // hor -
+ TInt32 hc = 0; // horizontal contribution
+ TInt32 vc = 0; // vertical contribution
+ TInt16 predict = 0; // the xor bit for differentiating states. ( positioned at the 6th bit )
+
+ for ( TUint8 i = 0; i < 16; i++ )
+ {
+ vpos = i & 1;
+ vneg = ( i >> 1 ) & 1;
+ hpos = ( i >> 2 ) & 1;
+ hneg = ( i >> 3 ) & 1;
+ hc = hpos - hneg;
+ vc = vpos - vneg;
+ predict = 0;
+ if ( hc < 0 )
+ {
+ predict = 1;
+ hc = -hc;
+ vc = -vc;
+ }
+ if ( hc == 0 )
+ {
+ if ( vc < 0 )
+ {
+ predict = 1;
+ vc = -vc;
+ }
+ ctxt = 11 + vc;
+ }
+ else
+ {
+ ctxt = 14 + vc;
+ }
+
+ iSCLut[i] = (TUint8) ( ctxt | ( predict << KPredictionBit ) );
+ }
+ iMRLut[0] = 16;
+ iMRLut[1] = 17;
+ iMRLut[2] = 18;
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::GetCausal
+// Get the casual
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::GetCausal( TPrecInt*& aDataCol, TInt16*& aStateCol )
+ {
+ TInt32 vpos = 0;
+ TInt32 vneg = 0;
+ TUint16 state = 0;
+ TInt16 causalityMask = 0;
+
+ aDataCol--;
+ for ( TInt32 col = iStateWidth; col > 0; col-- )
+ {
+ state = *aStateCol;
+ vpos = 0;
+ vneg = 0;
+ if ( ( ( state >> KPositionDown ) & 1 ) == 1 )
+ {
+ if ( ( ( state >> KPositionUp ) & 1 ) == 1 )
+ {
+ if ( col < iStateWidth )
+ {
+ if ( *aDataCol >= 0 )
+ {
+ vneg = 1;
+ }
+ else
+ {
+ vpos = 1;
+ }
+ }
+ }
+ else
+ {
+ vpos = 1;
+ vneg = 1;
+ }
+ }
+ causalityMask = (TInt16)( ~( ( KStateDown| KStateLowerLeft | KStateLowerRight ) |
+ ( vneg << KPositionVerNeg ) | ( vpos << KPositionVerPos ) ) );
+
+ ( *aStateCol ) &= causalityMask;
+ aDataCol++;
+ aStateCol++;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::DecodeSignificance
+// Decode the significance bit
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::DecodeSignificance( TPrecInt*& aDataValue, TInt16*& aStateValue, TPrecInt aMask )
+ {
+ TUint32 state = *aStateValue;
+ TInt32 context = state & KZcMask;
+ if ( ( state & KStateSignificant ) == 0 && context > 0 )
+ {
+ if ( iMQDecoder.MqDecodeSymbol( iCurrentZcLutPtr[context] ) != 0 )
+ {
+ TUint32 ctxt = iSCLut[( state >> KScShift ) & KScLutMask];
+ TInt32 symbol = iMQDecoder.MqDecodeSymbol( ( ctxt & KScLutMask ) ) ^ ( ( ctxt >> KPredictionBit ) & 1 );
+ *aDataValue = ( symbol << KSignShift ) | aMask;
+ *aStateValue |= KStateSignificant | KStateVisited;
+ UpdateSignificance( aStateValue, symbol );
+ }
+ else
+ {
+ ( *aStateValue ) |= KStateVisited;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::DecodeRawSignificance
+// Decode the lazy significance bit
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::DecodeRawSignificance( TPrecInt*& aDataValue, TInt16*& aStateValue, TPrecInt aMask )
+ {
+ TInt32 state = *aStateValue;
+ if ( ( state & KStateSignificant ) == 0 && ( state & KZcMask ) > 0 )
+ {
+ if ( iMQDecoder.iInputStream.ReadBitFromStream() )
+ {
+ TInt32 symbol = iMQDecoder.iInputStream.ReadBitFromStream();
+ *aDataValue = ( symbol << KSignShift ) | aMask;
+ *aStateValue |= KStateSignificant | KStateVisited;
+ UpdateSignificance( aStateValue, symbol );
+ }
+ else
+ {
+ ( *aStateValue ) |= KStateVisited;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::DecodeRefinement
+// Decode the refinement bit
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::DecodeRefinement( TPrecInt*& aDataValue, TInt16*& aStateValue,
+ TPrecInt aMask, TInt32 aResetMask )
+ {
+ TInt32 state = *aStateValue;
+ if ( ( state & ( KStateSignificant | KStateVisited ) ) == KStateSignificant )
+ {
+ TInt16 mrContext = (TInt16)( state & KStatePreviousMR );
+ TInt32 ctxt = 0;
+ if ( mrContext )
+ {
+ ctxt = 2;
+ }
+ else
+ {
+ if ( ( state & KZcMask ) == 0 )
+ {
+ ctxt = 0;
+ }
+ else
+ {
+ ctxt = 1;
+ }
+ }
+ TInt32 symbol = iMQDecoder.MqDecodeSymbol( iMRLut[ctxt] );
+ ( *aDataValue ) &= aResetMask;
+ ( *aDataValue ) |= ( symbol << iCurrentBitplane ) | aMask;
+ ( *aStateValue ) |= KStatePreviousMR;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::DecodeRawRefinement
+// Decode the lazy refinement bit
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::DecodeRawRefinement( TPrecInt*& aDataValue, TInt16*& aStateValue,
+ TPrecInt aMask, TInt32 aResetMask )
+ {
+ if ( ( ( *aStateValue ) & ( KStateSignificant | KStateVisited ) ) == KStateSignificant )
+ {
+ TInt32 symbol = iMQDecoder.iInputStream.ReadBitFromStream();
+ ( *aDataValue ) &= aResetMask;
+ ( *aDataValue ) |= ( symbol << iCurrentBitplane ) | aMask;
+ ( *aStateValue ) |= KStatePreviousMR;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::DecodeNormalization
+// Perform the normalization
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::DecodeNormalization( TPrecInt*& aDataValue, TInt16*& aStateValue,
+ TPrecInt aMask, TInt32& aZCValue )
+ {
+ TUint32 state = *aStateValue;
+ if ( state < (TUint32)KStateVisited )
+ {
+ TInt32 symbol = 0;
+ TUint32 ctxt = 0;
+ if ( aZCValue == 1 )
+ {
+ ( *aStateValue ) &= ~KStateVisited;
+ if ( iMQDecoder.MqDecodeSymbol( iCurrentZcLutPtr[state & KZcMask] ) != 0 )
+ {
+ ctxt = iSCLut[( state >> KScShift ) & KScLutMask];
+ symbol = iMQDecoder.MqDecodeSymbol( ( ctxt & KScLutMask ) ) ^( ( ctxt >> KPredictionBit ) & 1 );
+ ( *aDataValue ) = ( symbol << KSignShift ) | aMask;
+ ( *aStateValue ) |= KStateSignificant;
+ UpdateSignificance( aStateValue, symbol );
+ aZCValue = 1;
+ }
+ }
+ else
+ {
+ ctxt = iSCLut[( state >> KScShift ) & KScLutMask];
+ symbol = iMQDecoder.MqDecodeSymbol( ( ctxt & KScLutMask ) ) ^ ( ( ctxt >> KPredictionBit ) & 1 );
+ ( *aDataValue ) = ( symbol << KSignShift ) | aMask;
+ ( *aStateValue ) |= KStateSignificant; \
+ UpdateSignificance( aStateValue, symbol );
+ aZCValue = 1;
+ }
+ }
+ else
+ {
+ ( *aStateValue ) &= ( ~KStateVisited );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::UpdateSignificance
+// Update the significance
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::UpdateSignificance( TInt16*& aStateValue, TInt32 aSymbol )
+ {
+ TInt16* u = ( aStateValue ) - ( iStateWidth );
+ TInt16* d = ( aStateValue ) + ( iStateWidth );
+ u[-1] |= KStateLowerRight;
+ u[1] |= KStateLowerLeft;
+ d[-1] |= KStateUpperRight;
+ d[1] |= KStateUpperLeft;
+
+ if ( aSymbol != 0 )
+ {
+ aStateValue[-1] |= KStateRight | KStateHorNegative;
+ aStateValue[1] |= KStateLeft | KStateHorNegative;
+ *d |= KStateUp | KStateVerNegative;
+ *u |= KStateDown | KStateVerNegative;
+ }
+ else
+ {
+ aStateValue[-1] |= KStateRight | KStateHorPositive;
+ aStateValue[1] |= KStateLeft | KStateHorPositive;
+ *d |= KStateUp | KStateVerPositive;
+ *u |= KStateDown | KStateVerPositive;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::SignificancePass
+// Perform the significance pass
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::SignificancePass()
+ {
+ // Mask for the current bitplane is actually also an approximation of the
+ // lower bitplanes, i.e. mask might be 00001100 for the fourth bitplane instead
+ // of 00001000, thus the data will be increased by the current bitplane and
+ // half of the sum of the lower bitplanes.
+ TPrecInt mask = ( 1 << iCurrentBitplane ) | ( 1 << ( iCurrentBitplane - 1 ) );
+
+ TPrecInt* dataRow = &( iData[0][0] );
+ TInt16* stateRow = CONST_CAST( TInt16*, GetFirstStateRow( ) );
+
+ TPrecInt* dataCol = 0;
+ TPrecInt* dataValue = 0;
+ TInt16* stateCol = 0;
+ TInt16* stateValue = 0;
+
+ // Column index in the stripe
+ TInt32 col = 0;
+ TInt32 row = 0;
+
+ // Code stripe by stripe
+ for ( TInt32 s = iNumStripes - 1; s > 0; s-- )
+ {
+ // If using stripe causal context formation, reset necessary bits
+ // in state of first line in next stripe ( not on last
+ // stripe ).
+ if ( iVerticalCausalContextUsed )
+ {
+ dataCol = dataRow + 2 * iBlockDataWidth;
+ stateCol = stateRow + iStateSamplesPerStripe - iStateWidth - 1;
+ GetCausal( dataCol, stateCol );
+ }
+
+ dataCol = dataRow;
+ stateCol = stateRow;
+
+ // Scan column by column in each stripe
+ for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
+ {
+ stateValue = stateCol;
+ dataValue = dataCol;
+
+ for ( row = KStripeHeight; row > 0; row-- )
+ {
+ DecodeSignificance( dataValue, stateValue, mask );
+ dataValue += iBlockDataWidth;
+ stateValue += iStateWidth;
+ }
+ }
+
+ dataRow += iDataSamplesPerStripe;
+ stateRow += iStateSamplesPerStripe;
+ }
+
+ // Deal with the last stripe separately
+ dataCol = dataRow;
+ stateCol = stateRow;
+
+ // Scan column by column in each stripe
+ for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
+ {
+ stateValue = stateCol;
+ dataValue = dataCol;
+
+ for ( row = iLastStripeHeight; row > 0; row-- )
+ {
+ DecodeSignificance( dataValue, stateValue, mask );
+ if ( row > 1 )
+ {
+ dataValue += iBlockDataWidth;
+ }
+ stateValue += iStateWidth;
+ }
+ }
+
+ // If there is predictable termination, check for errors
+ if ( iTerminateThisPass && iPredictableTerminationUsed )
+ {
+ iErrorState = iMQDecoder.MqCheckPrediction();
+ }
+
+ // Reset the MQ context states if we need to
+ if ( iResetContexts )
+ {
+ iMQDecoder.ResetMqContexts();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::LazySignificancePass
+// Perform the lazy significance pass
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::LazySignificancePass()
+ {
+ // Mask for the current bitplane
+ TPrecInt mask = ( 1 << iCurrentBitplane ) | ( 1 << ( iCurrentBitplane - 1 ) );
+
+ TPrecInt* dataRow = &( iData[0][0] );
+ TInt16* stateRow = CONST_CAST( TInt16*, GetFirstStateRow() );
+ TPrecInt* dataCol = 0;
+ TPrecInt* dataValue = 0;
+ TInt16* stateCol = 0;
+ TInt16* stateValue = 0;
+
+ // Column index in the stripe
+ TInt32 col = 0;
+ TInt32 row = 0;
+
+ for ( TInt32 s = iNumStripes - 1; s > 0; s-- )
+ {
+ // If using stripe causal context formation, reset necessary bits
+ // in state of first line in next stripe ( not on last
+ // stripe ).
+ if ( iVerticalCausalContextUsed )
+ {
+ dataCol = dataRow + 2 * iBlockDataWidth;
+ stateCol = stateRow + iStateSamplesPerStripe - iStateWidth - 1;
+ GetCausal( dataCol, stateCol );
+ }
+
+ // Scan column by column in each stripe
+ dataCol = dataRow;
+ stateCol = stateRow;
+
+ // Scan column by column in each stripe
+ for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
+ {
+ stateValue = stateCol;
+ dataValue = dataCol;
+
+ for ( row = KStripeHeight; row > 0; row-- )
+ {
+ DecodeRawSignificance( dataValue, stateValue, mask );
+ dataValue += iBlockDataWidth;
+ stateValue += iStateWidth;
+ }
+ }
+ dataRow += iDataSamplesPerStripe;
+ stateRow += iStateSamplesPerStripe;
+ }
+
+ // Deal with the last stripe separately
+ // Scan column by column in each stripe
+ dataCol = dataRow;
+ stateCol = stateRow;
+
+ // Line index
+ TInt32 l = 0;
+
+ // Scan column by column in each stripe
+ for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
+ {
+ stateValue = stateCol;
+ dataValue = dataCol;
+
+ l = iLastStripeHeight;
+ DecodeRawSignificance( dataValue, stateValue, mask );
+ if ( --l <= 0 )
+ {
+ continue; //lint !e960 Continue is OK, no need to go end of for.
+ }
+
+ dataValue += iBlockDataWidth;
+ stateValue += iStateWidth;
+ DecodeRawSignificance( dataValue, stateValue, mask );
+ if ( --l <= 0 )
+ {
+ continue; //lint !e960 Continue is OK, no need to go end of for.
+ }
+
+ dataValue += iBlockDataWidth;
+ stateValue += iStateWidth;
+ DecodeRawSignificance( dataValue, stateValue, mask );
+ if ( --l <= 0 )
+ {
+ continue; //lint !e960 Continue is OK, no need to go end of for.
+ }
+
+ dataValue += iBlockDataWidth;
+ stateValue += iStateWidth;
+ DecodeRawSignificance( dataValue, stateValue, mask );
+
+ }
+
+ // If there is predictable termination, check for errors
+ if ( iTerminateThisPass && iPredictableTerminationUsed )
+ {
+ iErrorState = iMQDecoder.iInputStream.CheckPrediction();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::RefinementPass
+// Perform the refinement pass
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::RefinementPass()
+ {
+ // To reset the effects of the approximation done in significance and
+ // normalization passes we have the resetmask.
+ TInt32 resetMask = ( -1 ) << ( iCurrentBitplane + 1 );
+ TUint32 mask = ( ( TUint32 )( 1 << iCurrentBitplane ) ) >> 1;
+
+ TPrecInt* dataRow = &( iData[0][0] );
+ TInt16* stateRow = CONST_CAST( TInt16*, GetFirstStateRow() );
+
+ TPrecInt* dataCol = 0;
+ TPrecInt* dataValue = 0;
+ TInt16* stateCol = 0;
+ TInt16* stateValue = 0;
+
+ // Column index in the stripe
+ TInt32 col = 0;
+ TInt32 row = 0;
+
+ // Code stripe by stripe
+ for ( TInt32 s = iNumStripes - 1; s > 0; s-- )
+ {
+ // If using stripe causal context formation, reset necessary bits
+ // in state of first line in next stripe ( not on last
+ // stripe ).
+ if ( iVerticalCausalContextUsed )
+ {
+ dataCol = dataRow + 2 * iBlockDataWidth;
+ stateCol = stateRow + iStateSamplesPerStripe - iStateWidth - 1;
+ GetCausal( dataCol, stateCol );
+ }
+
+ // Scan column by column in each stripe
+ dataCol = dataRow;
+ stateCol = stateRow;
+
+ // Scan column by column in each stripe
+ for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
+ {
+ dataValue = dataCol;
+ stateValue = stateCol;
+
+ for ( row = KStripeHeight; row > 0; row-- )
+ {
+ DecodeRefinement( dataValue, stateValue, mask, resetMask );
+ dataValue += iBlockDataWidth;
+ stateValue += iStateWidth;
+ }
+ }
+ dataRow += iDataSamplesPerStripe;
+ stateRow += iStateSamplesPerStripe;
+ }
+
+ // Deal with the last stripe separately
+ // Scan column by column in each stripe
+ dataCol = dataRow;
+ stateCol = stateRow;
+
+ // Scan column by column in the last stripe
+ for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
+ {
+ dataValue = dataCol;
+ stateValue = stateCol;
+
+ for ( row = iLastStripeHeight; row > 0; row-- )
+ {
+ DecodeRefinement( dataValue, stateValue, mask, resetMask );
+ if ( row > 1 )
+ {
+ dataValue += iBlockDataWidth;
+ }
+ stateValue += iStateWidth;
+ }
+ }
+
+ // If there is predictable termination, check for errors
+ if ( iTerminateThisPass && iPredictableTerminationUsed )
+ {
+ iErrorState = iMQDecoder.MqCheckPrediction();
+ }
+
+ // Reset the MQ context states if we need to
+ if ( iResetContexts )
+ {
+ iMQDecoder.ResetMqContexts();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::LazyRefinementPass
+// Perform the lazy refinement pass
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::LazyRefinementPass()
+ {
+ TInt32 resetMask = ( -1 ) << ( iCurrentBitplane + 1 );
+ TUint32 mask = ( ( TUint32 )( 1 << iCurrentBitplane ) ) >> 1;
+ TPrecInt* dataRow = &( iData[0][0] );
+ TInt16* stateRow = CONST_CAST( TInt16*, GetFirstStateRow() );
+ TPrecInt* dataCol = 0;
+ TPrecInt* dataValue = 0;
+ TInt16* stateCol = 0;
+ TInt16* stateValue = 0;
+
+ // Column index in the stripe
+ TInt32 col = 0;
+ TInt32 row = 0;
+
+ // Code stripe by stripe
+ for ( TInt32 s = iNumStripes - 1; s > 0; s-- )
+ {
+ // If using stripe causal context formation, reset necessary bits
+ // in state of first line in next stripe ( not on last
+ // stripe ).
+ if ( iVerticalCausalContextUsed )
+ {
+ dataCol = dataRow + 2 * iBlockDataWidth;
+ stateCol = stateRow + iStateSamplesPerStripe - iStateWidth - 1;
+ GetCausal( dataCol, stateCol );
+ }
+
+ // Scan column by column in each stripe
+ dataCol = dataRow;
+ stateCol = stateRow;
+
+ // Scan column by column in each stripe
+ for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
+ {
+ dataValue = dataCol;
+ stateValue = stateCol;
+ for ( row = KStripeHeight; row > 0; row-- )
+ {
+ DecodeRawRefinement( dataValue, stateValue, mask, resetMask );
+ dataValue += iBlockDataWidth;
+ stateValue += iStateWidth;
+ }
+ }
+ dataRow += iDataSamplesPerStripe;
+ stateRow += iStateSamplesPerStripe;
+ }
+
+ // Deal with the last stripe separately
+ // Scan column by column in each stripe
+ dataCol = dataRow;
+ stateCol = stateRow;
+
+ // Scan column by column in each stripe
+ for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
+ {
+ dataValue = dataCol;
+ stateValue = stateCol;
+
+ for ( row = iLastStripeHeight; row > 0; row-- )
+ {
+ DecodeRawRefinement( dataValue, stateValue, mask, resetMask );
+ dataValue += iBlockDataWidth;
+ stateValue += iStateWidth;
+ }
+ stateValue = stateCol;
+ dataValue = dataCol;
+ }
+
+ // If there is predictable termination, check for errors
+ if ( iTerminateThisPass && iPredictableTerminationUsed )
+ {
+ iErrorState = iMQDecoder.iInputStream.CheckPrediction();
+ }
+
+ // Because this is always terminated, reset stream
+ iMQDecoder.iInputStream.ResetInputStream();
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::CleanupPass
+// Perform the cleanup pass
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kEntropyDecoder::CleanupPass( TUint8 aSegSymbols )
+ {
+ TInt32 zcCoding = 0;
+
+ // Symbol to be coded
+ TInt32 symbol = 0;
+
+ TPrecInt mask = ( 1 << iCurrentBitplane ) | ( 1 << ( iCurrentBitplane - 1 ) );
+
+ TPrecInt* dataRow = &( iData[0][0] );
+ TInt16* stateRow = CONST_CAST( TInt16*, GetFirstStateRow() );
+ TPrecInt* dataCol = 0;
+ TPrecInt* dataValue = 0;
+ TInt16* stateCol = 0;
+ TInt16* stateValue = 0;
+
+ // Column index in the stripe
+ TInt32 col = 0;
+ TInt32 row = 0;
+
+ // Code stripe by stripe
+ for ( TInt32 s = iNumStripes - 1; s > 0; s-- )
+ {
+ // If using stripe causal context formation, reset necessary bits
+ // in state of first line in next stripe
+ if ( iVerticalCausalContextUsed )
+ {
+ dataCol = dataRow + 2 * iBlockDataWidth;
+ stateCol = stateRow + iStateSamplesPerStripe - iStateWidth - 1;
+ GetCausal( dataCol, stateCol );
+ }
+
+ // Scan column by column in each stripe
+ dataCol = dataRow;
+ stateCol = stateRow;
+
+ for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
+ {
+ stateValue = stateCol;
+ dataValue = dataCol;
+
+ // If sample is insignificant and not yet visited in the
+ // current bitplane, then apply the normalization pass
+ if ( ( *stateValue == 0 ) &&
+ ( stateValue += iStateWidth, ( *stateValue ) == 0 ) && //lint !e960 Comma is OK.
+ ( stateValue += iStateWidth, ( *stateValue ) == 0 ) && //lint !e960 Comma is OK.
+ ( stateValue += iStateWidth, ( *stateValue ) == 0 ) ) //lint !e960 Comma is OK.
+ {
+ // Use RLC
+ if ( iMQDecoder.MqDecodeSymbol( KRlcContext ) != 0 ) //some sample( s ) not zero
+ {
+ // Decode the symbol most significant bit first
+ symbol = (TUint8)( iMQDecoder.MqDecodeSymbol( KUniformContext ) << 1 ); // MSB
+ symbol |= (TUint8)( iMQDecoder.MqDecodeSymbol( KUniformContext ) & 0x01 ); // LSB
+
+ // Update data and state pointers
+ stateValue = stateCol + symbol * iStateWidth;
+ dataValue = dataCol + symbol * iBlockDataWidth;
+
+ // Set zcCoding flag to zero
+ zcCoding = 0;
+ row = KStripeHeight - symbol;
+ }
+ else // All samples zero
+ {
+ // Move to next column
+ continue; //lint !e960 Continue is OK, no need to go end of for.
+ }
+ }
+ else // No RLC used
+ {
+ stateValue = stateCol;
+
+ // Set zcCoding flag to one
+ zcCoding = 1;
+ row = KStripeHeight;
+ }
+
+ for ( ; row > 0; row-- )
+ {
+ DecodeNormalization( dataValue, stateValue, mask, zcCoding );
+ dataValue += iBlockDataWidth;
+ stateValue += iStateWidth;
+ }
+ }
+ dataRow += iDataSamplesPerStripe;
+ stateRow += iStateSamplesPerStripe;
+ }
+
+ // Deal with last stripe separately
+ // Scan column by column in each stripe
+ dataCol = dataRow;
+ stateCol = stateRow;
+
+ // Scan column by column in each stripe
+ for ( col = iBlockWidth; col > 0; col--, stateCol++, dataCol++ )
+ {
+ stateValue = stateCol;
+ dataValue = dataCol;
+
+ // If sample is insignificant and not yet visited in the
+ // current bitplane, then apply the normalization pass
+ if( ( iLastStripeHeight == KStripeHeight ) && ( *stateValue ==0 ) &&
+ ( stateValue += iStateWidth, ( *stateValue ) == 0 ) && //lint !e960 Comma is OK.
+ ( stateValue += iStateWidth, ( *stateValue ) == 0 ) && //lint !e960 Comma is OK.
+ ( stateValue += iStateWidth, ( *stateValue ) == 0 ) ) //lint !e960 Comma is OK.
+ {
+ // Use RLC:
+ if ( iMQDecoder.MqDecodeSymbol( KRlcContext ) != 0 ) //some sample( s ) not zero
+ {
+ // Decode the symbol most significant bit first
+ symbol = ( TUint8 )( iMQDecoder.MqDecodeSymbol( KUniformContext ) << 1 ); // MSB
+ symbol |= ( TUint8 )( iMQDecoder.MqDecodeSymbol( KUniformContext ) & 0x01 ); // LSB
+
+ // Update data and state pointers
+ stateValue = stateCol + symbol * iStateWidth;
+ dataValue = dataCol + symbol * iBlockDataWidth;
+
+ // Set zcCoding flag to zero
+ zcCoding = 0;
+ row = KStripeHeight - symbol;
+ }
+ else // All samples zero
+ {
+ // Move to next column
+ continue; //lint !e960 Continue is OK, no need to go end of for.
+ }
+ }
+ else // No RLC used
+ {
+ row = iLastStripeHeight;
+ stateValue = stateCol;
+
+ // Set zcCoding flag to one
+ zcCoding = 1;
+ }
+
+ for ( ; row > 0; row-- )
+ {
+ DecodeNormalization( dataValue, stateValue, mask, zcCoding );
+ if ( row > 1 )
+ {
+ dataValue += iBlockDataWidth;
+ }
+ stateValue += iStateWidth;
+ }
+ }
+
+ // Decode a segment marker if we need to
+ if ( aSegSymbols )
+ {
+ symbol = (TUint8)( iMQDecoder.MqDecodeSymbol( KUniformContext ) << 3 );
+ symbol |= (TUint8)( iMQDecoder.MqDecodeSymbol( KUniformContext ) << 2 );
+ symbol |= (TUint8)( iMQDecoder.MqDecodeSymbol( KUniformContext ) << 1 );
+ symbol |= (TUint8)( iMQDecoder.MqDecodeSymbol( KUniformContext ) );
+
+ if ( symbol != KSegmentationMarker )
+ {
+ iErrorState = EEntropyCodingError;
+ }
+ }
+
+ // If there is predictable termination, check for errors
+ if ( iTerminateThisPass && iPredictableTerminationUsed )
+ {
+ iErrorState = iMQDecoder.MqCheckPrediction();
+ }
+
+ // Reset the MQ context states if we need to
+ if ( iResetContexts )
+ {
+ iMQDecoder.ResetMqContexts();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CJ2kEntropyDecoder::GetFirstStateRow
+// Get the first state row
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+const TInt16* CJ2kEntropyDecoder::GetFirstStateRow() const
+ {
+ return iStates + ( iStateWidth + 1 );
+ }
+