diff -r 000000000000 -r 469c91dae73b imagingmodules/jp2kcodec/Src/JP2KPacket.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/imagingmodules/jp2kcodec/Src/JP2KPacket.cpp Thu Dec 17 09:22:31 2009 +0200 @@ -0,0 +1,1430 @@ +/* +* 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: JP2KPacket class used to collect packet related +* information such as tag tree and list of codeblocks. +* +*/ + + +// INCLUDE FILES +#include +#include "JP2KImageUtils.h" +#include "JP2KStreamReader.h" +#include "JP2KTileInfo.h" +#include "JP2KImageInfo.h" +#include "JP2KCodeBlock.h" +#include "JP2KPacket.h" +#include "JP2KSubband.h" +#include "JP2KComponentInfo.h" + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS + +// MACROS + +// LOCAL CONSTANTS AND MACROS + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// FORWARD DECLARATIONS + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CJ2kPacket::CJ2kPacket +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CJ2kPacket::CJ2kPacket( TUint16 aLayer ) : + iTagTreeLevel(1), + iLayer(aLayer), + iCodeBlockList(1) + { + } + +// Destructor +CJ2kPacket::~CJ2kPacket() + { + delete iIncluded; + iIncluded = 0; + + delete iTagTreeInfo; + iTagTreeInfo = 0; + + delete iIncTagTreeValue; + iIncTagTreeValue = 0; + + delete iIncTagTreeState; + iIncTagTreeState = 0; + + delete iMsbTagTreeValue; + iMsbTagTreeValue = 0; + + delete iMsbTagTreeState; + iMsbTagTreeState = 0; + + iCodeBlockList.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::SetPacketCanvas +// Set the canvas of the packet +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::SetPacketCanvas( TInt32 aX, TInt32 aY, TInt32 aWidth, TInt32 aHeight ) + { + iPacketCanvas.iTl = TPoint( aX, aY ); + iPacketCanvas.SetWidth( aWidth ); + iPacketCanvas.SetHeight( aHeight ); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::SetNumOfBlocks +// Set the number of blocks +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::SetNumOfBlocks( TSize& aCodeBlock ) + { + TInt32 x0 = TJ2kUtils::Floor( iPacketCanvas.iTl.iX, aCodeBlock.iWidth ) * aCodeBlock.iWidth; + TInt32 y0 = TJ2kUtils::Floor( iPacketCanvas.iTl.iY, aCodeBlock.iHeight ) * aCodeBlock.iHeight; + TInt32 x1 = TJ2kUtils::Ceil( iPacketCanvas.iTl.iX + iPacketCanvas.Width(), aCodeBlock.iWidth ) * aCodeBlock.iWidth; + TInt32 y1 = TJ2kUtils::Ceil( iPacketCanvas.iTl.iY + iPacketCanvas.Height(), aCodeBlock.iHeight ) * aCodeBlock.iHeight; + iCodeBlockSize.iWidth = ( x1 - x0 ) / aCodeBlock.iWidth; + iCodeBlockSize.iHeight = ( y1 - y0 ) / aCodeBlock.iHeight; + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::BuildInclusiveInfoL +// Build the inclusive information of the packet +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::BuildInclusiveInfoL() + { + TInt entries = ( iLayer % 8 ) ? ( ( iLayer / 8 ) + 1 ) : ( iLayer / 8 ); + iIncluded = HBufC8::NewMaxL( entries ); + iIncluded->Des().FillZ(); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::BuildCodeBlocksL +// Build the codeblocks in the packet +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::BuildCodeBlocksL( TInt32 aX, TInt32 aY, TSize& aCodeBlock ) + { + TUint16 numOfBlocks = NumOfBlocks(); + + if ( numOfBlocks ) + { + BuildTagtreeL(); + + TInt32 x0 = 0; + TInt32 y0 = 0; + TInt32 x1 = 0; + TInt32 y1 = 0; + TInt32 origX = aX; + TUint16 index = 0; + + while ( index < numOfBlocks ) + { + x0 = Max( aX, iPacketCanvas.iTl.iX ); + y0 = Max( aY, iPacketCanvas.iTl.iY ); + x1 = Min( aX + aCodeBlock.iWidth, iPacketCanvas.iTl.iX + iPacketCanvas.Width() ) - x0; + y1 = Min( aY + aCodeBlock.iHeight, iPacketCanvas.iTl.iY + iPacketCanvas.Height() ) - y0; + if ( x1 > 0 && y1 > 0 ) + { + CJ2kCodeBlock *block = new ( ELeave ) CJ2kCodeBlock; + CleanupStack::PushL( block ); + User::LeaveIfError( iCodeBlockList.Append( block ) ); + CleanupStack::Pop( 1 ); + iCodeBlockList[index]->SetCodeBlockCanvas( x0, y0, x1, y1 ); + + // Initialize the codeblock + iCodeBlockList[index]->InitializeL( iLayer ); + ++index; + } + + aX += aCodeBlock.iWidth; + if ( aX >= iPacketCanvas.iTl.iX + iPacketCanvas.Width() ) + { + aX = origX; + aY += aCodeBlock.iHeight; + } + } + } + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::ReadPacketHeaderL +// Read the packet header +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::ReadPacketHeaderL( CJ2kTileInfo& aTile, CJ2kComponentInfo& aComponent, CJ2kSubband& aSubband ) + { + if ( IsIncludedL( aTile.LastLayerProcessed() ) ) + { + return EFalse; + } + + TUint8 incomplete = ETrue; + if ( LastCodeBlockProcessed() == 0 ) + { + if ( ReadSOP_EPHMarker( aComponent, aTile ) ) + { + return incomplete; + } + } + + TJ2kStreamReader& reader = CONST_CAST( TJ2kStreamReader&, aTile.StreamReader() ); + TUint8 *rollbackPtr = CONST_CAST( TUint8*, reader.iPtr ); + + if ( !StartReadBit( aTile ) ) + { + TUint8 bit = 0; + + if ( LastCodeBlockProcessed() == 0 ) + { + if ( !IsRecoverFromIncomplete() ) + { + ReadBit( bit, aTile ); + if ( bit == 0 ) + { + // Empty packet + incomplete = EFalse; + } + } + } + + if ( incomplete ) + { + // Packet header has not been processed yet + if ( !IsHeader() ) + { + TUint8 isBackup = IsBackupNeeded( aTile ); + + CJ2kSubband *subband = &aSubband; + if ( subband->SubbandResLevel() > 0 ) + { + if ( subband->LastSubbandProcessed() == CJ2kSubband::EBandLL ) + { + subband->SetLastSubbandProcessed( CJ2kSubband::EBandHL ); + } + else + { + // Move to last subband processed + while ( subband->SubbandType() != aSubband.LastSubbandProcessed() ) + { + subband = subband->NextSubbandRaster(); + } + } + } + + TUint16 bandIndex = 0; + TUint16 cbIndex = 0; + TUint16 cbYIndex = 0; + TUint16 xIndex = 0; + TUint16 yIndex = 0; + TUint16 incValue = 0; + TUint16 msbValue = 0; + TUint16 index = 0; + TUint16 layer = aTile.LastLayerProcessed(); + TUint16 numPass = 0; + TUint16 codePass = 0; + TUint16 numSegment = 0; + TUint8 recoverIncTag = 0; + TUint8 recoverMsbTag = 0; + TUint8 firstRecovery = ETrue; + TUint8 recoverData = 0; + TUint8 recoverPos = 0; + TUint8 recoverNextPos = 0; + TUint8 origPassIndex = 0; + TUint8 origLengthBits = 0; + TInt8 origLastPass = 0; + TUint32 origDataLength = 0; + + HBufC16 *recoverIncTagTreeValue = 0; + HBufC16 *recoverIncTagTreeState = 0; + HBufC16 *recoverMsbTagTreeValue = 0; + HBufC16 *recoverMsbTagTreeState = 0; + + if ( IsRecoverFromIncomplete() ) + { + recoverData = reader.iData; + recoverPos = reader.iPos; + recoverNextPos = reader.iNextPos; + } + + CJ2kPacket *packet = CONST_CAST( CJ2kPacket*, &subband->PacketAt( aSubband.LastPacketProcessed() ) ); + CJ2kCodeBlock *codeBlock; + incomplete = EFalse; + do + { + if ( aComponent.QuantizationStyle() != 1 ) + { + bandIndex = subband->SubbandTreeIndex(); + } + + for ( yIndex = 0; yIndex < packet->NumOfBlocksY(); ++yIndex ) + { + cbYIndex = (TUint16)( yIndex * packet->NumOfBlocksX() ); + for ( xIndex = 0; xIndex < packet->NumOfBlocksX(); ++xIndex ) + { + cbIndex = (TUint16)( cbYIndex + xIndex ); + if ( cbIndex < packet->LastCodeBlockProcessed() || + ( packet->IsMatch() && cbIndex == packet->LastCodeBlockProcessed() ) ) + { + // Has been processed, skip to the next codeblock + continue; //lint !e960 Using continue saves a lot of code here. + } + else + { + packet->ResetMatch(); + recoverIncTag = recoverMsbTag = EFalse; + codeBlock = CONST_CAST( CJ2kCodeBlock*, &packet->CodeBlockAt( cbIndex ) ); + + TPtr16 numSegPtr = codeBlock->iNumSegment->Des(); + + origPassIndex = codeBlock->iPassIndex; + origLastPass = codeBlock->iLastPass; + if ( codeBlock->iLastPass < 0 && codeBlock->iPassIndex == 0 ) + { + if ( isBackup ) + { + packet->BackupIncTagtreeL( recoverIncTagTreeValue, recoverIncTagTreeState ); + recoverIncTag = ETrue; + } + msbValue = (TUint16)0; + incomplete = packet->DecodeIncTagtree( aTile, xIndex, yIndex, incValue ); + if ( !incomplete ) + { + if ( incValue <= layer ) + { + if ( isBackup ) + { + packet->BackupMsbTagtreeL( recoverMsbTagTreeValue, recoverMsbTagTreeState ); + recoverMsbTag = ETrue; + } + incomplete = packet->DecodeMsbTagtree( aTile, xIndex, yIndex, msbValue ); + } + else + { + packet->SetLastCodeBlockProcessed( cbIndex ); + firstRecovery = EFalse; + recoverData = reader.iData; + recoverPos = reader.iPos; + recoverNextPos = reader.iNextPos; + recoverIncTag = recoverMsbTag = EFalse; + rollbackPtr = CONST_CAST( TUint8*, reader.iPtr ); + + // Move on to the next codeblock + continue; //lint !e960 Using continue saves a lot of code here. + } + } + + if ( incomplete ) + { + // Underflow, should backup the iterator position + if ( cbIndex > packet->LastCodeBlockProcessed() ) + { + // Next read should match the codeblock index + packet->SetMatch(); + } + + if ( !firstRecovery ) + { + SetRecoverFromIncomplete(); + reader.iData = recoverData; + reader.iPos = recoverPos; + reader.iNextPos = recoverNextPos; + } + else + { + if ( IsRecoverFromIncomplete() ) + { + reader.iData = recoverData; + reader.iPos = recoverPos; + reader.iNextPos = recoverNextPos; + } + } + + if ( isBackup ) + { + if ( recoverIncTag ) + { + packet->RestoreIncTagtree( recoverIncTagTreeValue, recoverIncTagTreeState ); + } + if ( recoverMsbTag ) + { + packet->RestoreMsbTagtree( recoverMsbTagTreeValue, recoverMsbTagTreeState ); + } + // Release memory + packet->FreeBackupTagtree( recoverIncTagTreeValue, recoverIncTagTreeState, + recoverMsbTagTreeValue, recoverMsbTagTreeState ); + } + reader.iPtr = rollbackPtr; + + // Return from the packet header decoding + return incomplete; + } + + codeBlock->iLastPass = 0; + numSegPtr[layer] = 1; + + codeBlock->iEmptyBitplane = (TUint8)msbValue; + + if ( aComponent.RoiShift() > 0 ) + { + numPass = (TUint16)( ( aComponent.MagnitudeBits( bandIndex ) + aComponent.RoiShift() ) * 3 + 1 ); + } + else + { + numPass = (TUint16)( ( aComponent.MagnitudeBits( bandIndex ) - msbValue ) * 3 + 1 ); + } + + if ( codeBlock->iDataSize == 0 || codeBlock->iDataSize->Length() < numPass ) + { + if ( codeBlock->iDataSize == 0 ) + { + codeBlock->iDataSize = HBufC16::NewMaxL( numPass ); + codeBlock->iDataSize->Des().FillZ(); + codeBlock->iPassesPerSegment = HBufC16::NewMaxL( numPass ); + codeBlock->iPassesPerSegment->Des().FillZ(); + } + else + { + incValue = ( TUint16 )( numPass - codeBlock->iDataSize->Length() ); + codeBlock->iDataSize = codeBlock->iDataSize->ReAllocL( numPass ); + codeBlock->iPassesPerSegment = codeBlock->iPassesPerSegment->ReAllocL( numPass ); + while ( incValue-- ) + { + codeBlock->iDataSize->Des().Append( 0 ); + codeBlock->iPassesPerSegment->Des().Append( 0 ); + } + } + } + } + else + { + incomplete = ReadBit( bit, aTile ); + if ( incomplete ) + { + // Underflow, should backup the iterator position + if ( cbIndex > packet->LastCodeBlockProcessed() ) + { + // Next read should match the codeblock index + packet->SetMatch(); + } + + if ( !firstRecovery ) + { + SetRecoverFromIncomplete(); + reader.iData = recoverData; + reader.iPos = recoverPos; + reader.iNextPos = recoverNextPos; + } + else + { + if ( IsRecoverFromIncomplete() ) + { + reader.iData = recoverData; + reader.iPos = recoverPos; + reader.iNextPos = recoverNextPos; + } + } + + if ( isBackup ) + { + // Release memory + packet->FreeBackupTagtree( recoverIncTagTreeValue, recoverIncTagTreeState, + recoverMsbTagTreeValue, recoverMsbTagTreeState ); + } + reader.iPtr = rollbackPtr; + + // Return from the packet header decoding + return incomplete; + } + + numSegPtr[layer] = bit; + + if ( bit == 0 ) + { + packet->SetLastCodeBlockProcessed( cbIndex ); + firstRecovery = EFalse; + recoverData = reader.iData; + recoverPos = reader.iPos; + recoverNextPos = reader.iNextPos; + recoverIncTag = recoverMsbTag = EFalse; + rollbackPtr = CONST_CAST( TUint8*, reader.iPtr ); + + // Move on to the next codeblock + continue; //lint !e960 Using continue saves a lot of code here. + } + } + + incomplete = ReadBit( bit, aTile ); + codePass = (TUint16)0; + if ( !incomplete ) + { + if ( bit ) // 1 + { + incomplete = ReadBit( bit, aTile ); + if ( !incomplete ) + { + if ( bit ) // 11 + { + incomplete = ReadBits( bit, 2, aTile ); + if ( !incomplete ) + { + if ( bit == 0x03 ) // 1111 + { + incomplete = ReadBits( bit, 5, aTile ); + if ( !incomplete ) + { + if ( bit == 0x1f ) // 1111 11111 + { + incomplete = ReadBits( bit, 7, aTile ); + if ( !incomplete ) + { + codePass = (TUint16)( 0x25 + bit ); + } + } + else + { + // 1111 XXXXX, at least one of them is not 1 + codePass = (TUint16)( 6 + bit ); + } + } + } + else + { + // 11XX + codePass = (TUint16)( 3 + bit ); + } + } + } + else + { + // 10 + codePass = 2; + } + } + } + else + { + // 0 + codePass = 1; + } + } + + if ( incomplete ) + { + // Underflow, restore the original codeblock information + codeBlock->iPassIndex = origPassIndex; + codeBlock->iLastPass = origLastPass; + + // Underflow, should backup the iterator position + if ( cbIndex > packet->LastCodeBlockProcessed() ) + { + // Next read should match the codeblock index + packet->SetMatch(); + } + + if ( !firstRecovery ) + { + SetRecoverFromIncomplete(); + reader.iData = recoverData; + reader.iPos = recoverPos; + reader.iNextPos = recoverNextPos; + } + else + { + if ( IsRecoverFromIncomplete() ) + { + reader.iData = recoverData; + reader.iPos = recoverPos; + reader.iNextPos = recoverNextPos; + } + } + + if ( isBackup ) + { + if ( recoverIncTag ) + { + packet->RestoreIncTagtree( recoverIncTagTreeValue, + recoverIncTagTreeState ); + } + if ( recoverMsbTag ) + { + packet->RestoreMsbTagtree( recoverMsbTagTreeValue, + recoverMsbTagTreeState ); + } + // Release memory + packet->FreeBackupTagtree( recoverIncTagTreeValue, recoverIncTagTreeState, + recoverMsbTagTreeValue, recoverMsbTagTreeState ); + } + reader.iPtr = rollbackPtr; + + // Return from the packet header decoding + return incomplete; + } + + if ( codeBlock->iPassIndex == 0 ) + { + codeBlock->iLastPass = -1; + } + + numSegment = 1; + + if ( aComponent.IsTermination() ) + { + numSegment = codePass; + } + else if ( aComponent.IsACByPass() ) + { + if ( ( codeBlock->iLastPass + codePass ) >= KFirstLazyPassIndex ) + { + for ( index = 1; index < codePass; ++index ) + { + if ( ( index + codeBlock->iLastPass ) >= KFirstLazyPassIndex ) + { + if ( ( ( index + codeBlock->iLastPass ) % 3 ) != 1 ) + { + ++numSegment; + } + } + } + } + } + + numSegPtr[layer] = numSegment; //lint !e961 no else is needed here at the end of if...else if + + origLengthBits = codeBlock->iLengthBits; + origDataLength = codeBlock->iDataLength; + incomplete = ReadBit( bit, aTile ); + if ( !incomplete ) + { + // Skip all 1 bits + while ( bit ) + { + ++codeBlock->iLengthBits; + incomplete = ReadBit( bit, aTile ); + if ( incomplete ) + { + // Underflow + // Set bit to zero to break from the while-loop + bit = 0; + } + } + } + + if ( !incomplete ) + { + TUint8 bits = 0; + TUint32 tmpBits = 0; + TPtr16 numPassesPerSegPtr = codeBlock->iPassesPerSegment->Des(); + TPtr16 numDataSizePtr = codeBlock->iDataSize->Des(); + + if ( numSegment == 1 ) + { + bits = (TUint8)( codeBlock->iLengthBits + TJ2kUtils::Log2( codePass ) ); + + incomplete = ReadBits( tmpBits, bits, aTile ); + if ( !incomplete ) + { + numPassesPerSegPtr[codeBlock->iPassIndex] = codePass; + numDataSizePtr[codeBlock->iPassIndex++] = (TUint16)tmpBits; + + codeBlock->iDataLength += tmpBits; + codeBlock->iLastPass = (TUint8)( codeBlock->iLastPass + codePass ); + if ( tmpBits > 0 ) + { + SetBodyIncomplete(); + } + } + } + else + { + TUint16 totalCodePass = codePass; + TUint16 tmpCodePass; + for ( index = 0; index < numSegment; ++index ) + { + if ( aComponent.IsTermination() ) + { + tmpCodePass = 1; + } + else + { + if ( codeBlock->iLastPass < KFirstLazyPassIndex ) + { + tmpCodePass = (TUint16)( KFirstLazyPassIndex - ( TInt )codeBlock->iLastPass ); + } + else + { + tmpCodePass = (TUint16)( ( codeBlock->iLastPass % 3 ) ? 1 : ( ( totalCodePass > 1 ) ? 2 : 1 ) ); + } + } + bits = (TUint8)( codeBlock->iLengthBits + TJ2kUtils::Log2( tmpCodePass ) ); + incomplete = ReadBits( tmpBits, bits, aTile ); + if ( !incomplete ) + { + numPassesPerSegPtr[codeBlock->iPassIndex] = tmpCodePass; + numDataSizePtr[codeBlock->iPassIndex++] = (TUint16)tmpBits; + + codeBlock->iDataLength += tmpBits; + codeBlock->iLastPass = (TUint8)( codeBlock->iLastPass + tmpCodePass ); + totalCodePass = (TUint16)( totalCodePass - tmpCodePass ); + if ( tmpBits > 0 ) + { + SetBodyIncomplete(); + } + } + else + { + index = numSegment; // break from the for-loop + } + } + } + } + + if ( incomplete ) + { + // Underflow, restore the original codeblock information + codeBlock->iPassIndex = origPassIndex; + codeBlock->iLastPass = origLastPass; + codeBlock->iLengthBits = origLengthBits; + codeBlock->iDataLength = origDataLength; + + // Underflow, should backup the iterator position + if ( cbIndex > packet->LastCodeBlockProcessed() ) + { + // Next read should match the codeblock index + packet->SetMatch(); + } + + if ( !firstRecovery ) + { + SetRecoverFromIncomplete(); + reader.iData = recoverData; + reader.iPos = recoverPos; + reader.iNextPos = recoverNextPos; + } + else + { + if ( IsRecoverFromIncomplete() ) + { + reader.iData = recoverData; + reader.iPos = recoverPos; + reader.iNextPos = recoverNextPos; + } + } + + if ( isBackup ) + { + if ( recoverIncTag ) + { + packet->RestoreIncTagtree( recoverIncTagTreeValue, + recoverIncTagTreeState ); + } + if ( recoverMsbTag ) + { + packet->RestoreMsbTagtree( recoverMsbTagTreeValue, + recoverMsbTagTreeState ); + } + + // Release memory + packet->FreeBackupTagtree( recoverIncTagTreeValue, + recoverIncTagTreeState, + recoverMsbTagTreeValue, + recoverMsbTagTreeState ); + } + reader.iPtr = rollbackPtr; + + // Return from the packet header decoding + return incomplete; + } + + } + + packet->SetLastCodeBlockProcessed( cbIndex ); + firstRecovery = EFalse; + recoverData = reader.iData; + recoverPos = reader.iPos; + recoverNextPos = reader.iNextPos; + recoverIncTag = recoverMsbTag = EFalse; + rollbackPtr = CONST_CAST( TUint8*, reader.iPtr ); + } // end of xIndex + } // end of yIndex + + packet->SetLastCodeBlockProcessed( 0 ); + packet->ResetMatch(); + ResetRecoverFromIncomplete(); + subband = subband->NextSubbandRaster(); + if ( subband ) + { + if ( isBackup ) + { + // Sibling may have different tag tree level, so release memory here + packet->FreeBackupTagtree( recoverIncTagTreeValue, recoverIncTagTreeState, + recoverMsbTagTreeValue, recoverMsbTagTreeState ); + } + packet = CONST_CAST( CJ2kPacket*, &subband->PacketAt( aSubband.LastPacketProcessed() ) ); + aSubband.SetLastSubbandProcessed( (TUint8)subband->SubbandType() ); + } + + } while ( subband ); + + if ( !incomplete ) + { + // Packet header has been completely processed + SetHeader(); + SetIncluded( aTile.LastLayerProcessed() ); + AlignReader( aTile ); + aSubband.SetLastSubbandProcessed( CJ2kSubband::EBandLL ); + } + if ( isBackup ) + { + // Release memory + packet->FreeBackupTagtree( recoverIncTagTreeValue, recoverIncTagTreeState, + recoverMsbTagTreeValue, recoverMsbTagTreeState ); + } + } + else + { + // Packet has been processed + reader.iPtr = rollbackPtr; + } + } + + if ( !incomplete ) + { + if ( aComponent.IsEPHMarkerUsed() ) + { + ReadEPHMarker( aTile ); + } + } + } + return incomplete; + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::ReadPacketBodyL +// Read the packet body +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::ReadPacketBodyL( CJ2kTileInfo& aTile, CJ2kComponentInfo& aComponent, CJ2kSubband& aSubband ) + { + TUint8 incomplete = EFalse; + if ( LastCodeBlockProcessed() == 0 ) + { + if ( ReadSOP_EPHMarker( aComponent, aTile, EFalse ) ) + { + return ETrue; + } + } + + TJ2kStreamReader& reader = CONST_CAST( TJ2kStreamReader&, aTile.StreamReader() ); + + // Packet body has not been processed yet + if ( !IsBody() ) + { + SetBodyIncomplete(); + + CJ2kSubband *subband = &aSubband; + if ( subband->SubbandResLevel() > 0 ) + { + if ( subband->LastSubbandProcessed() == CJ2kSubband::EBandLL ) + { + subband->SetLastSubbandProcessed( CJ2kSubband::EBandHL ); + } + else + { + // Move to last subband processed + while ( subband->SubbandType() != aSubband.LastSubbandProcessed() ) + { + subband = subband->NextSubbandRaster(); + } + } + } + TUint16 xIndex = 0; + TUint16 yIndex = 0; + TUint16 cbIndex = 0; + TUint16 cbYIndex = 0; + TUint16 index = 0; + TUint16 cblkLength = 0; + TUint16 layer = aTile.LastLayerProcessed(); + TInt32 totalLength = 0; + TUint8 *rollbackPtr = CONST_CAST( TUint8*, reader.iPtr ); + + CJ2kPacket *packet = CONST_CAST( CJ2kPacket*, &subband->PacketAt( aSubband.LastPacketProcessed() ) ); + CJ2kCodeBlock *codeBlock = 0; + do + { + + for ( yIndex = 0; yIndex < packet->NumOfBlocksY(); ++yIndex ) + { + cbYIndex = (TUint16)( yIndex * packet->NumOfBlocksX() ); + for ( xIndex = 0; xIndex < packet->NumOfBlocksX(); ++xIndex ) + { + cbIndex = (TUint16)( cbYIndex + xIndex ); + if ( cbIndex < packet->LastCodeBlockProcessed() || + ( packet->IsMatch() && cbIndex == packet->LastCodeBlockProcessed() ) ) + { + // Has been processed, skip to the next codeblock + continue; //lint !e960 Using continue saves a lot of code here. + } + else + { + packet->ResetMatch(); + codeBlock = CONST_CAST( CJ2kCodeBlock*, &packet->CodeBlockAt( cbIndex ) ); + + if ( ( *codeBlock->iNumSegment )[layer] > 0 ) + { + TUint tempLength = 0; + TUint8 skip = 0; + + if ( !aTile.IsSpeedup() ) + { + // If this resolution level is not required in decoding, skip storing the data to save memory + if ( aTile.LastLevelProcessed() > (TUint8)( aTile.NumOfLevelsPOC() - aTile.ImageInfo().LevelDrop() ) ) + skip = 1; + } + + tempLength = codeBlock->iDataLength; + + if ( tempLength ) + { + // Find out which segment has been processed + totalLength = codeBlock->iDataLength - tempLength; + { + for ( index = 1; index <= ( *codeBlock->iNumSegment )[layer]; ++index ) + { + totalLength -= ( *codeBlock->iDataSize )[codeBlock->iPassIndex - index]; + if ( totalLength <= 0 ) + { + break; //lint !e960 break usage saves code here. + } + } + } + } + else + { + index = ( *codeBlock->iNumSegment )[layer]; + } + + for ( ; index > 0; --index ) + { + cblkLength = ( *codeBlock->iDataSize )[codeBlock->iPassIndex - index]; + if ( ( reader.iPtrEnd - reader.iPtr ) < cblkLength ) + { + // Underflow, rollback the iterator position + reader.iPtr = rollbackPtr; + incomplete = ETrue; + if ( cbIndex > packet->LastCodeBlockProcessed() ) + { + // Next read should match the codeblock index + packet->SetMatch(); + } + + return incomplete; + } + else + { + + // Store data only if the resolution level is not skipped + if( !skip ) + { + TPtr8 data = codeBlock->DataL()->Des(); + data.Append( reader.iPtr, cblkLength ); + } + + reader.iPtr += cblkLength; + } + // Save the iterator position + rollbackPtr = CONST_CAST( TUint8*, reader.iPtr ); + } + } + } + packet->SetLastCodeBlockProcessed( cbIndex ); + + // Save the iterator position + rollbackPtr = CONST_CAST( TUint8*, reader.iPtr ); + } // end of xIndex + } // end of yIndex + + packet->SetLastCodeBlockProcessed( 0 ); + packet->ResetMatch(); + subband = subband->NextSubbandRaster(); + if ( subband ) + { + packet = CONST_CAST( CJ2kPacket*, &subband->PacketAt( aSubband.LastPacketProcessed() ) ); + aSubband.SetLastSubbandProcessed( (TUint8)subband->SubbandType() ); + } + + } while ( subband ); + + SetBody(); + ResetBodyIncomplete(); + aSubband.SetLastSubbandProcessed( CJ2kSubband::EBandLL ); + } + + return incomplete; + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::ResetInternalFlags +// Reset the internal flags +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::ResetInternalFlags() + { + ResetHeader(); + ResetBody(); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::BuildTagtreeL +// Build the tag tree +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::BuildTagtreeL() + { + TUint32 width = iCodeBlockSize.iWidth; + TUint32 height = iCodeBlockSize.iHeight; + + while ( width != 1 || height != 1 ) + { + width = ( width + 1 ) >> 1; + height = ( height + 1 ) >> 1; + ++iTagTreeLevel; + } + + TInt size = 0; + TInt sizeIndex = 0; + width = iCodeBlockSize.iWidth; + height = iCodeBlockSize.iHeight; + + iTagTreeInfo = HBufC16::NewMaxL( iTagTreeLevel + 1 ); + TPtr16 tmpPtr = ( iTagTreeInfo->Des() ); + tmpPtr[0] = (TUint16)sizeIndex; + + for ( TUint8 index = 0; index < iTagTreeLevel; ++index ) + { + size = width * height; + sizeIndex += size; + tmpPtr[index + 1] = (TUint16)sizeIndex; + } + + TChar fillChar( 0xffff ); + + iIncTagTreeValue = HBufC16::NewMaxL( sizeIndex ); + iIncTagTreeValue->Des().Fill( fillChar, iIncTagTreeValue->Length() ); + iIncTagTreeState = HBufC16::NewMaxL( sizeIndex ); + iIncTagTreeState->Des().FillZ(); + + iMsbTagTreeValue = HBufC16::NewMaxL( sizeIndex ); + iMsbTagTreeValue->Des().Fill( fillChar, iIncTagTreeValue->Length() ); + iMsbTagTreeState = HBufC16::NewMaxL( sizeIndex ); + iMsbTagTreeState->Des().FillZ(); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::DecodeIncTagtree +// Decode the included tag tree +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::DecodeIncTagtree( CJ2kTileInfo& aTile, TUint32 aWidth, TUint32 aHeight, TUint16& aValue ) + { + TUint8 bit = 2; + TInt16 parentState = 0; + TUint8 contCoding = 1; + TUint16 idx = 0; + TUint16 layer = (TUint16)( aTile.LastLayerProcessed() + 1 ); + + for ( TInt16 index = TInt16( iTagTreeLevel - 1 ); index >= 0; --index ) + { + idx = (TUint16)( ( aHeight >> index ) * ( (TUint32)( iCodeBlockSize.iWidth + ( 1 << index ) - 1 ) >> index ) + ( aWidth >> index ) ); + if ( ( IncTagState( index, idx ) < parentState ) && IncTagValue( index, idx ) == 0xffff ) + { + SetIncTagState( index, idx, (TUint16)( parentState - contCoding ) ); + } + + while ( contCoding && IncTagState( index, idx ) < layer && IncTagValue( index, idx ) == 0xffff ) + { + if ( ReadBit( bit, aTile ) ) + { + return ETrue; + } + + if ( bit == 1 ) + { + SetIncTagValue( index, idx, IncTagState( index, idx ) ); + } + IncrementIncTagState( index, idx ); + } + parentState = IncTagState( index, idx ); + if ( bit == 0 || IncTagValue( index, idx ) == 0xffff ) + { + contCoding = 0; + } + } + aValue = IncTagValue( 0, idx ); + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::DecodeMsbTagtree +// Decode the msb tag tree +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::DecodeMsbTagtree( CJ2kTileInfo& aTile, TUint32 aWidth, TUint32 aHeight, TUint16& aValue ) + { + TUint8 bit = 2; + TInt16 parentState = 0; + TUint8 contCoding = 1; + TUint16 idx = 0; + TUint16 layer = 0xffff; + + for ( TInt16 index = (TUint16)( iTagTreeLevel - 1 ); index >= 0; --index ) + { + idx = (TUint16)( ( aHeight >> index ) * ( (TUint32)( iCodeBlockSize.iWidth + ( 1 << index ) - 1 ) >> index ) + ( aWidth >> index ) ); + + if ( ( MsbTagState( index, idx ) < parentState ) && MsbTagValue( index, idx ) == 0xffff ) + { + SetMsbTagState( index, idx, (TUint16)( ( parentState - contCoding ) ) ); + } + + while ( contCoding && MsbTagState( index, idx ) < layer && MsbTagValue( index, idx ) == 0xffff ) + { + if ( ReadBit( bit, aTile ) ) + { + return ETrue; + } + + if ( bit == 1 ) + { + SetMsbTagValue( index, idx, MsbTagState( index, idx ) ); + } + IncrementMsbTagState( index, idx ); + } + parentState = MsbTagState( index, idx ); + if ( bit == 0 || MsbTagValue( index, idx ) == 0xffff ) + { + contCoding = 0; + } + } + aValue = MsbTagValue( 0, idx ); + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::BackupIncTagtreeL +// Backup the included tag tree +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::BackupIncTagtreeL( HBufC16*& aTagValue, HBufC16*& aTagState ) + { + if ( aTagValue && aTagState ) + { + if ( aTagValue->Des().MaxLength() < iIncTagTreeValue->Length() ) + { + aTagValue = aTagValue->ReAllocL( iIncTagTreeValue->Length() ); + } + if ( aTagState->Des().MaxLength() < iIncTagTreeState->Length() ) + { + aTagState = aTagState->ReAllocL( iIncTagTreeState->Length() ); + } + } + else + { + aTagValue = HBufC16::NewMaxLC( iIncTagTreeValue->Length() ); + aTagState = HBufC16::NewMaxLC( iIncTagTreeState->Length() ); + } + *aTagValue = *iIncTagTreeValue; + *aTagState = *iIncTagTreeState; + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::BackupMsbTagtreeL +// Backup the msb tag tree +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::BackupMsbTagtreeL( HBufC16*& aTagValue, HBufC16*& aTagState ) + { + if ( aTagValue && aTagState ) + { + if ( aTagValue->Des().MaxLength() < iMsbTagTreeValue->Length() ) + { + aTagValue = aTagValue->ReAllocL( iMsbTagTreeValue->Length() ); + } + if ( aTagState->Des().MaxLength() < iMsbTagTreeState->Length() ) + { + aTagState = aTagState->ReAllocL( iMsbTagTreeState->Length() ); + } + } + else + { + aTagValue = HBufC16::NewMaxLC( iMsbTagTreeValue->Length() ); + aTagState = HBufC16::NewMaxLC( iMsbTagTreeState->Length() ); + } + *aTagValue = *iMsbTagTreeValue; + *aTagState = *iMsbTagTreeState; + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::RestoreIncTagtree +// Restore the included tag tree +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::RestoreIncTagtree( HBufC16 *aTagValue, HBufC16 *aTagState ) + { + *iIncTagTreeValue = *aTagValue; + *iIncTagTreeState = *aTagState; + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::RestoreMsbTagtree +// Restore the msb tag tree +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::RestoreMsbTagtree( HBufC16 *aTagValue, HBufC16 *aTagState ) + { + *iMsbTagTreeValue = *aTagValue; + *iMsbTagTreeState = *aTagState; + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::FreeBackupTagtree +// Release the temporary backup memory +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::FreeBackupTagtree( HBufC16*& aIncTagValue, HBufC16*& aIncTagState, + HBufC16*& aMsbTagValue, HBufC16*& aMsbTagState ) + { + TInt count = 0; + if ( aIncTagValue ) + { + delete aIncTagValue; + aIncTagValue = 0; + ++count; + } + if ( aIncTagState ) + { + delete aIncTagState; + aIncTagState = 0; + ++count; + } + if ( aMsbTagValue ) + { + delete aMsbTagValue; + aMsbTagValue = 0; + ++count; + } + if ( aMsbTagState ) + { + delete aMsbTagState; + aMsbTagState = 0; + ++count; + } + CleanupStack::Pop( count ); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::IsIncludedL +// Is the layer has been included in previous packet +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::IsIncludedL( TUint16 aLayer ) + { + TInt entries = ( iLayer % 8 ) ? ( ( iLayer / 8 ) + 1 ) : ( iLayer / 8 ); + if ( iIncluded == 0 || iIncluded->Des().MaxLength() < entries ) + { + if ( iIncluded ) + { + TInt diff = entries - iIncluded->Length(); + iIncluded = iIncluded->ReAllocL( entries ); + while ( diff-- ) + { + iIncluded->Des().Append( (TUint8)0 ); + } + } + else + { + iIncluded = HBufC8::NewMaxL( entries ); + iIncluded->Des().FillZ(); + } + } + return IncludedAt( aLayer ); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::IncludedAt +// Get the inclusive information at specific layer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::IncludedAt( TUint16 aLayer ) const + { + TInt entry = aLayer / 8; + TInt bit = aLayer % 8; + return (TUint8)( ( iIncluded->Des() )[entry] & ( 0x01 << bit ) ); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::SetIncluded +// Set the inclusive information at specific layer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::SetIncluded( TUint16 aLayer ) + { + TInt entry = aLayer / 8; + TInt bit = aLayer % 8; + TPtr8 tmpPtr = iIncluded->Des(); + tmpPtr[entry] |= ( 0x01 << bit ); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::IsBackupNeeded +// Is tag tree backup is required for underflow recovery +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::IsBackupNeeded( CJ2kTileInfo& aTile ) + { + return !( aTile.IsPPT() || aTile.ImageInfo().IsPPM() ); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::StartReadBit +// Read a bit from the packet header stream +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::StartReadBit( CJ2kTileInfo& aTile ) + { + return ( !IsRecoverFromIncomplete() ) ? + aTile.PacketHeaderReader().StartReadBit() : + (TUint8)EFalse; + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::ReadBit +// Read a bit from the packet header stream +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::ReadBit( TUint8& aBit, CJ2kTileInfo& aTile ) + { + return aTile.PacketHeaderReader().ReadBit( aBit ); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::ReadBits +// Read some bits from the packet header stream +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::ReadBits( TUint8& aBit, TUint8 aBitLen, CJ2kTileInfo& aTile ) + { + return aTile.PacketHeaderReader().ReadBits( aBit, aBitLen ); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::ReadBits +// Read some bits from the packet header stream +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::ReadBits( TUint32& aBit, TUint8 aBitLen, CJ2kTileInfo& aTile ) + { + return aTile.PacketHeaderReader().ReadBits( aBit, aBitLen ); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::AlignReader +// Align the stream to the next byte boundary if necessary +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CJ2kPacket::AlignReader( CJ2kTileInfo& aTile ) + { + aTile.PacketHeaderReader().AlignReader(); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::ReadSOPMarker +// Try to consume the SOP marker if there is one +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::ReadSOPMarker( CJ2kTileInfo& aTile ) + { + // SOP may be inside the CodeStream only + return CONST_CAST( TJ2kStreamReader&, aTile.StreamReader() ).ReadSOPMarker(); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::ReadEPHMarker +// Try to consume the EPH marker if there is one +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::ReadEPHMarker( CJ2kTileInfo& aTile ) + { + // EPH may be inside PPT or PPM or CodeStream + return aTile.PacketHeaderReader().ReadEPHMarker(); + } + +// ----------------------------------------------------------------------------- +// CJ2kPacket::ReadSOP_EPHMarker +// Try to re-align stream to next byte boundary if necessary, +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TUint8 CJ2kPacket::ReadSOP_EPHMarker( CJ2kComponentInfo& aComponent, CJ2kTileInfo& aTile, TBool aSOP ) + { + TJ2kStreamReader& reader = CONST_CAST( TJ2kStreamReader&, aTile.StreamReader() ); + + TUint8 incomplete = reader.TryReAlignReader(); + incomplete = reader.TryReadEPHMarker(); + + if ( !incomplete && aSOP && aComponent.IsSOPMarkerUsed() && ( !IsHeader() || !IsBody() ) ) + { + incomplete = ReadSOPMarker( aTile ); + } + + return incomplete; + }