imagingmodules/jp2kcodec/Src/JP2KPacket.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Sat, 20 Feb 2010 00:07:53 +0200
branchRCL_3
changeset 4 3993b8f65362
parent 0 469c91dae73b
permissions -rw-r--r--
Revision: 201002 Kit: 201007

/*
* 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 <icl/imagecodec.h>
#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::SetNumOfBlocksL
// Set the number of blocks
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kPacket::SetNumOfBlocksL( TSize& aCodeBlock )
    {
    TInt32 x0 = TJ2kUtils::FloorL( iPacketCanvas.iTl.iX, aCodeBlock.iWidth ) * aCodeBlock.iWidth;
    TInt32 y0 = TJ2kUtils::FloorL( iPacketCanvas.iTl.iY, aCodeBlock.iHeight ) * aCodeBlock.iHeight;
    TInt32 x1 = TJ2kUtils::CeilL( iPacketCanvas.iTl.iX + iPacketCanvas.Width(), aCodeBlock.iWidth ) * aCodeBlock.iWidth;
    TInt32 y1 = TJ2kUtils::CeilL( 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();
                            User::LeaveIfNull(subband);
                            }
                        }
                    }

                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();
                    User::LeaveIfNull(subband); 
                    }
                }
            }
        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 );
        CJ2kCodeBlock *codeBlock = 0;
        
        CJ2kPacket * packet = CONST_CAST( CJ2kPacket*, &subband->PacketAt( aSubband.LastPacketProcessed() ) );
        
        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;
    }