mmserv/thumbnailengine/TneProcessorSrc/TNEDecoderWrap.cpp
changeset 0 71ca22bcf22a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmserv/thumbnailengine/TneProcessorSrc/TNEDecoderWrap.cpp	Tue Feb 02 01:08:46 2010 +0200
@@ -0,0 +1,1077 @@
+/*
+* Copyright (c) 2006 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:   TNE decoder wrapper
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <devvideoconstants.h>
+#include "TNEDecoderWrap.h"
+#include "ctrsettings.h"
+
+// MACROS
+#define TRASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CTRANSCODERVIDEODECODERCLIENT"), -10010))
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CTNEDecoderWrap* CTNEDecoderWrap::NewL(MThumbnailObserver* aObserver)
+{
+    PRINT((_L("CTNEDecoderWrap::NewL(), In")))
+    CTNEDecoderWrap* self = new (ELeave) CTNEDecoderWrap(aObserver);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+
+    PRINT((_L("CTNEDecoderWrap::NewL(), Out")))
+    return self;
+}
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::CTNEDecoderWrap
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CTNEDecoderWrap::CTNEDecoderWrap(MThumbnailObserver* aObserver)
+{    
+    iObserver = aObserver;
+    iDevVideoPlay = NULL;
+    iCompresedFormat = NULL;
+    iClockSource = NULL;
+    iUid = TUid::Null();
+    iHwDeviceId = THwDeviceId(0);
+    iInputBuffer = NULL;
+    iCodedBuffer = NULL;
+    iDecodedPicture = NULL;
+    iFatalError = KErrNone;
+    iDataUnitType = EDuCodedPicture;
+    iStop = EFalse;
+    iState = ETRNone;
+    iLastTimestamp = -1;
+}
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::ConstructL()
+{
+    iDevVideoPlay = CMMFDevVideoPlay::NewL(*this);
+    
+    // Support for AVC
+   	iClockSource = CSystemClockSource::NewL();
+   	iInputFrameNum = 1;	
+}
+
+
+// ---------------------------------------------------------
+// CTNEDecoderWrap::~CTNEDecoderWrap()
+// Destructor
+// ---------------------------------------------------------
+//
+CTNEDecoderWrap::~CTNEDecoderWrap()
+{
+    PRINT((_L("CTNEDecoderWrap::~CTNEDecoderWrap(), In")))
+
+    if (iDevVideoPlay)
+    {
+        delete iDevVideoPlay;
+        iDevVideoPlay = NULL;
+    }
+
+    iInputBuffer = NULL;
+    
+    if (iClockSource)
+    {
+    	delete iClockSource;
+    	iClockSource = 0;
+    }
+     
+    
+    if (iCompresedFormat)
+    {
+        delete iCompresedFormat;
+    }
+        
+    iAcceleratedDecoders.Reset();
+    iAcceleratedDecoders.Close();
+
+    PRINT((_L("CTNEDecoderWrap::~CTNEDecoderWrap(), Out")))
+}
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::SupportsCodec
+// Checks whether this coded is supported
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CTNEDecoderWrap::SupportsCodec(const TDesC8& aFormat, const TDesC8& aShortFormat)
+{
+    TBool supports = EFalse;
+    TBuf8<256> mime;
+    
+    if (iDevVideoPlay)
+    {
+        RArray<TUid> decoders;
+        
+        TRAPD( status, iDevVideoPlay->FindDecodersL(aShortFormat, 0/*aPreProcType*/, decoders, EFalse/*aExactMatch*/) );
+
+        if( ( status != KErrNone ) || ( decoders.Count() <= 0 ) )
+        {
+            PRINT((_L("CTNEDecoderWrap::SupportsCodec(), status[%d]"), status))
+            supports = EFalse;
+        }
+        else
+        {
+            // Keep mime type given by codec fo future use
+            iMimeType = aFormat;
+            iShortMimeType = aShortFormat;
+            supports = ETrue;
+        }
+
+        decoders.Reset();
+        decoders.Close();
+    }
+
+    return supports;
+}
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::SetDecoderParametersL
+// Sets codec parameters
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::SetDecoderParametersL(TInt aDecoderLevel, const TTRVideoFormat& aFormat)
+{
+    PRINT((_L("CTNEDecoderWrap::SetDecoderParametersL(), In")))
+    RArray<TUid> decoders;
+    TBool codecAcceleration = EFalse;
+    TInt status = KErrNone;
+    iCodecLevel = aDecoderLevel;
+    iFormat = aFormat;
+
+	// Find the list of decoders 
+    iDevVideoPlay->FindDecodersL(iShortMimeType, 0/*aPreProcType*/, decoders, EFalse/*aExactMatch*/);
+
+    // Input format
+    if (!iCompresedFormat)
+    {
+        TRAP(status, iCompresedFormat = CCompressedVideoFormat::NewL( iMimeType ));
+        
+        if (status != KErrNone)
+        {
+            // Reset decoder's list
+            decoders.Reset();
+            decoders.Close();
+            User::Leave(status);
+        }
+    }
+
+    // get decoder info
+    for ( TInt i = 0; i < decoders.Count(); i ++ )
+    {
+        TRAP( status, codecAcceleration = CheckDecoderInfoL(decoders[i]) );
+
+        if (status == KErrNone)
+        {
+            if (codecAcceleration != KTRAccelerationPriorityDecoder) 
+            {
+                // Use the first available software decoder
+                iUid = decoders[i];
+
+                // Keep the list of non-checked codecs for future use
+                i = i + 1;
+                for (; i < decoders.Count(); i ++)
+                {
+                    iCheckDecoders.Insert(decoders[i], iCheckDecoders.Count() );
+                }
+
+                break;
+            }
+            else
+            {
+                // Keep track of accelerated decoder to the list of "good" decoders
+                iAcceleratedDecoders.Insert( decoders[i], iAcceleratedDecoders.Count() );
+            }
+        }
+    }
+        
+    decoders.Reset();
+    decoders.Close();
+        
+    if (iUid == TUid::Null())
+    {
+        // Check others "good"
+        if ( iAcceleratedDecoders.Count() <= 0 )
+        {
+            PRINT((_L("CTNEDecoderWrap::SetDecoderParametersL(), No suitable decoders found")))
+            User::Leave(KErrNotSupported);
+        }
+        else
+        {
+            // Select the accelerated as no ARM decoder is available
+            iUid = iAcceleratedDecoders[0];
+            iAcceleratedDecoders.Remove(0);
+        }
+    }
+
+    PRINT((_L("CTNEDecoderWrap::SetDecoderParametersL(), Out")))
+}
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::CheckDecoderInfoL
+// Checks coded info
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CTNEDecoderWrap::CheckDecoderInfoL(TUid aUid)
+{
+    CVideoDecoderInfo* decoderInfo = NULL; // Decoder info for retrieving capabilities
+    TInt status = KErrNone;
+    TBool accelerated = EFalse;
+
+    // Check decoder
+    PRINT((_L("CTNEDecoderWrap::CheckDecoderInfoL(), getting info from [0x%x]"), aUid.iUid ))
+    decoderInfo = iDevVideoPlay->VideoDecoderInfoLC( aUid );
+
+    if (!decoderInfo)
+	{
+        PRINT((_L("CTNEDecoderWrap::CheckDecoderInfoL(), getting info from [0x%x] failed[%d]"), aUid.iUid, status ))
+        User::Leave(KErrNotSupported);
+	}
+    else 
+	{
+        // Check max rate for requested image format
+        TSize maxSize = decoderInfo->MaxPictureSize();
+
+        if ( (iFormat.iSize.iWidth > maxSize.iWidth) || (iFormat.iSize.iHeight > maxSize.iHeight) )
+        {
+            PRINT((_L("CTNEDecoderWrap::CheckDecoderInfoL(), Picture size is not supported")))
+            status = KErrNotSupported;
+        }
+	}
+        
+    accelerated = decoderInfo->Accelerated();
+
+    // Delete codec info
+    CleanupStack::PopAndDestroy(decoderInfo);
+
+    if (status != KErrNone)
+    {
+        User::Leave(status);
+    }
+
+    return accelerated;
+}
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::InitializeL
+// Initializes decoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::InitializeL()
+    {
+    PRINT((_L("CTNEDecoderWrap::InitializeL(), In")))
+    TUint maxBufferSize = 0;
+    TInt status = KErrNone;
+
+	iState = ETRInitializing;
+
+    switch(iFormat.iDataType)
+        {
+        case ETRDuCodedPicture:
+            {
+            iDataUnitType = EDuCodedPicture;
+            break;
+            }
+
+        case ETRDuVideoSegment:
+            {
+            iDataUnitType = EDuVideoSegment;
+            break;
+            }
+
+        default:
+            {
+            // Should never happend. Decoder does not support uncompressed input format. 
+            TRASSERT(0);
+            }
+        }
+
+    iBufferOptions.iMinNumInputBuffers = KTRDecoderMinNumberOfBuffers;
+
+    // Select decoder first
+    this->SelectDecoderL();
+
+    // Set now output format for this device    
+    TRAP(status, iDevVideoPlay->SetOutputFormatL(iHwDeviceId, iUncompressedFormat));
+    
+    // 3. Buffer options
+    iBufferOptions.iPreDecodeBufferSize = 0;            // "0" - use default decoder value
+    iBufferOptions.iMaxPostDecodeBufferSize = 0;        // No limitations
+    iBufferOptions.iPreDecoderBufferPeriod = 0;
+    iBufferOptions.iPostDecoderBufferPeriod = 0;
+    
+    // Check max coded picture size for specified codec level
+    switch(iCodecLevel)
+        {
+        case KTRH263CodecLevel10:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel10;
+            break;
+            }
+
+        case KTRH263CodecLevel20:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel20;
+            break;
+            }
+
+        case KTRH263CodecLevel30:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel30;
+            break;
+            }
+
+        case KTRH263CodecLevel40:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel40;
+            break;
+            }
+
+        case KTRH263CodecLevel50:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel50;
+            break;
+            }
+
+        case KTRH263CodecLevel60:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel60;
+            break;
+            }
+
+        case KTRH263CodecLevel70:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel70;
+            break;
+            }
+
+        case KTRMPEG4CodecLevel0:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel0;
+            break;
+            }
+            
+        case KTRMPEG4CodecLevel1:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel1;
+            break;
+            }
+            
+        case KTRMPEG4CodecLevel2:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel2;
+            break;
+            }
+            
+        case KTRMPEG4CodecLevel3:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel3;
+            break;
+            }
+
+        case KTRMPEG4CodecLevel0b:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel0b;
+            break;
+            }
+
+        case KTRMPEG4CodecLevel4a:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel4a;
+            break;
+            }
+
+        default:
+            {
+            maxBufferSize = KTRMaxBufferSizeLevel0;
+            break;
+            }
+        }
+
+    iBufferOptions.iMaxInputBufferSize = maxBufferSize;
+    
+    PRINT((_L("CTNEDecoderWrap::InitializeL(), InputBufferSize[%d], NumberOfBuffers[%d]"), 
+               iBufferOptions.iMaxInputBufferSize, iBufferOptions.iMinNumInputBuffers ))
+
+    iDevVideoPlay->SetBufferOptionsL(iBufferOptions);
+
+    // Initialize devVideoPlay
+    iDevVideoPlay->Initialize();
+
+    PRINT((_L("CTNEDecoderWrap::InitializeL(), Out")))
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::SelectDecoderL
+// Selects decoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::SelectDecoderL()
+{
+    PRINT(( _L("CTNEDecoderWrap::SelectDecoderL(), In") ))
+    TInt status = KErrNone;
+    TBool accelerated = EFalse;
+    TBool exit = EFalse;
+
+
+    if (iUid != TUid::Null())
+	{
+        TRAP( status, iHwDeviceId = iDevVideoPlay->SelectDecoderL(iUid) );
+	}
+    else
+	{
+        // Most likely an error exists, if iUid == NULL; 
+        status = KErrAlreadyExists;
+	}
+
+    while ( !exit )
+	{
+        if (status == KErrNone)
+		{
+            // To get Output format list devvideoplay requires to define output format first. 
+            iDevVideoPlay->SetInputFormatL(iHwDeviceId, *iCompresedFormat, iDataUnitType, EDuElementaryStream, ETrue);
+
+            // It's time to check input format support (since the plugin is loaded to the memory)
+            iUncompressedFormat.iDataFormat = EYuvRawData;
+            
+            TUncompressedVideoFormat uncFormat;
+            TBool found = EFalse;
+            TInt pattern1, pattern2;
+                    
+            pattern1 = EYuv420Chroma1;
+            pattern2 = EYuv420Chroma2;
+                
+            RArray<TUncompressedVideoFormat> supportedOutputFormats; 
+            TRAP(status, iDevVideoPlay->GetOutputFormatListL( iHwDeviceId, supportedOutputFormats ));
+            
+            TInt formatCount = 0;
+            if (status == KErrNone)
+            {
+                formatCount = supportedOutputFormats.Count();
+                PRINT((_L("CTNEDecoderWrap::InitializeL(), formatCount[%d]"), formatCount ))
+            }
+                
+            if (formatCount <= 0)
+            {
+                supportedOutputFormats.Close();
+                status = KErrAlreadyExists;
+                PRINT((_L("CTNEDecoderWrap::InitializeL(), There are no supported output formats") ))
+                //User::Leave(KErrNotSupported);
+            }
+            else
+            {
+                // Check the most important paramers
+                for ( TInt i = 0; i < formatCount; i ++ )
+                {
+                    uncFormat = supportedOutputFormats[i];
+                    PRINT((_L("CTNEDecoderWrap::InitializeL(), pattern[%d]"), uncFormat.iYuvFormat.iPattern ))
+                    
+                    if ( (uncFormat.iDataFormat == iUncompressedFormat.iDataFormat) && 
+                         ( (uncFormat.iYuvFormat.iPattern == pattern1) || 
+                           (uncFormat.iYuvFormat.iPattern == pattern2) ) )
+                        {
+                        // Assign the rest of parameters
+                        iUncompressedFormat = uncFormat;
+                        found = ETrue;
+                        exit = ETrue;
+                        supportedOutputFormats.Close();
+                        break;
+                        }
+                }
+
+                if (!found)
+                {
+                    supportedOutputFormats.Close();
+                    PRINT((_L("CTNEDecoderWrap::InitializeL(), Supported format is not found") ))
+                    //User::Leave(KErrNotSupported);
+                }
+            }
+        }
+        else
+        {
+            // Take another codec and try again
+            // Reset Uid
+            iUid = TUid::Null();
+
+            // Check codecs
+            for ( TInt i = 0; i < iCheckDecoders.Count(); i ++ )
+            {
+            	TRAP( status, accelerated = CheckDecoderInfoL(iCheckDecoders[i]) );
+
+            	if (status == KErrNone)
+                {
+                	if (accelerated != KTRAccelerationPriorityDecoder) // The rule is defined based on study
+                	{
+                     	// pick the first ARM decoder
+                    	iUid = iCheckDecoders[i];
+                    	iCheckDecoders.Remove(i);
+                            
+                     	// Keep the list of non-checked codecs for future use
+                     	// nothing to do, they are already are in the list
+                    	break;
+                	}
+                 	else
+                	{
+                    	// its a DSP based decoder add it to the accelerated decoder array 
+                    	iAcceleratedDecoders.Insert( iAcceleratedDecoders[i], iAcceleratedDecoders.Count() );
+                    }
+                }
+            }
+                
+            if ( iUid == TUid::Null() )
+            {
+                // There are no ARM decoders in the system, use the accelerated ones
+                if (iAcceleratedDecoders.Count() > 0)
+                {
+                    // decoders were already checked, take the first from the list
+                    iUid = iAcceleratedDecoders[0];
+                    iAcceleratedDecoders.Remove(0);
+                }
+                else
+                {
+                    PRINT((_L("CTNEDecoderWrap::SelectDecoderL(), No suitable accelerated decoders found")))
+                    User::Leave(KErrNotSupported);
+                }
+            }
+                
+            status = KErrNone;
+            TRAP(status, iHwDeviceId = iDevVideoPlay->SelectDecoderL(iUid));
+        }
+    }
+
+    PRINT((_L("CTNEDecoderWrap::SelectDecoderL(), Out")))
+}
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::MdvpoInitComplete
+// Notifies for initialization complete with init status
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::MdvpoInitComplete(TInt /*aError*/)
+    {
+		iState = ETRInitialized;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::StartL
+// Starts decoding
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::StartL()
+    {
+    PRINT((_L("CTNEDecoderWrap::StartL(), In")))
+
+    // Start decoding
+    if (iFatalError == KErrNone)
+        {
+        iDevVideoPlay->Start();
+        }
+
+    if (!iInputBuffer)
+        {
+        // Get buffer from the decoder to fill
+        iInputBuffer = iDevVideoPlay->GetBufferL(iBufferOptions.iMaxInputBufferSize);
+        }
+    
+    // Reset iStop    
+    iStop = EFalse;
+    iState = ETRRunning;
+    
+    // Reset ts monitor
+    iLastTimestamp = -1;
+
+    PRINT((_L("CTNEDecoderWrap::StartL(), Out")))
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::MdvpoNewBuffers()
+// New buffers are available
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::MdvpoNewBuffers()
+    {
+    TInt status = KErrNone;
+
+
+    if (iStop)
+        {
+        PRINT((_L("CTNEDecoderWrap::MdvpoNewBuffers(), Stop was already called, nothing to do")))
+        return;
+        }
+
+    // One or more new empty input buffers are available
+    if (!iInputBuffer)
+        {
+        // Get buffer from the decoder to fill
+        TRAP(status, iInputBuffer = iDevVideoPlay->GetBufferL(iBufferOptions.iMaxInputBufferSize));
+        
+        if (status != KErrNone)
+            {
+            PRINT((_L("CTNEDecoderWrap::MdvpoNewBuffers(), GetBufferL status[%d]"), status))
+            iObserver->MNotifyThumbnailReady(status);
+            return;
+            }
+
+        if (!iInputBuffer)
+            {
+            PRINT((_L("CTNEDecoderWrap::MdvpoNewBuffers(), There are available buffer, but decoder returned NULL")))
+            return;
+            }
+        }
+
+    if (iCodedBuffer)
+        {
+        // Send coded buffer, since the client has already done request
+        TRAP(status, this->SendBufferL(iCodedBuffer));
+
+        // Reset buffer
+        iCodedBuffer = NULL;
+
+        if (status != KErrNone)
+            {
+            PRINT((_L("CTNEDecoderWrap::MdvpoNewBuffers(), Send buffer error[%d]"), status))
+            iObserver->MNotifyThumbnailReady(status);
+            return;
+            }
+        }
+        
+    if ((iInputBuffer) && (iState == ETRRunning))
+    	{
+			// If InputBuffer is available send 
+			// more encoded packets to the decoder
+            iObserver->MSendEncodedBuffer();
+    	}
+    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::WriteCodedBufferL
+// Writes coded data to decoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::WriteCodedBufferL(TVideoBuffer* aBuffer)
+    {
+    PRINT((_L("CTNEDecoderWrap::WriteCodedBufferL(), In")))
+    TVideoBuffer::TBufferType bufferType;
+    
+    if (!aBuffer)
+        {
+        PRINT((_L("CTNEDecoderWrap::WriteCodedBufferL(), Input buffer is invalid, Leave")))
+        User::Leave(KErrArgument);
+        }
+
+    if (iFatalError != KErrNone)
+        {
+        PRINT((_L("CTNEDecoderWrap::WriteCodedBufferL(), FatalError was reported by decoder")))
+        
+        // Return coded buffer
+        iObserver->MReturnCodedBuffer(aBuffer);
+        return;
+        }
+    
+    TTimeIntervalMicroSeconds ts = aBuffer->TimeStamp();
+        
+    if ( ts <= iLastTimestamp)
+        {
+        // Prevent propagation of the error now
+        PRINT((_L("CTNEDecoderWrap::WriteCodedBufferL(), Client sends invalid data (ts field), Leave")))
+        User::Leave(KErrArgument);
+        }
+    else
+        {
+        iLastTimestamp = ts;
+        }
+    
+    if (aBuffer->BufferSize() <= 0)
+        {
+        PRINT((_L("CTNEDecoderWrap::WriteCodedBufferL(), Input data buffer is invalid (empty), Leave")))
+        User::Leave(KErrArgument);
+        }
+        
+    bufferType = aBuffer->Type();
+        
+    if ( ( bufferType != TVideoBuffer::EVideoH263 ) && 
+         ( bufferType != TVideoBuffer::EVideoMPEG4 ) )
+        {
+        PRINT((_L("CTNEDecoderWrap::WriteCodedBufferL(), [%d] This data type is not supported, Leave"), aBuffer->Type() ))
+        User::Leave(KErrNotSupported);
+        }
+
+    if (!iInputBuffer)
+        {
+        // Request new empty buffer
+        iInputBuffer = iDevVideoPlay->GetBufferL(iBufferOptions.iMaxInputBufferSize);
+        }
+
+    if (iInputBuffer)
+        {
+        this->SendBufferL(aBuffer);
+        }
+    else
+        {
+        iCodedBuffer = aBuffer;
+        }
+
+    PRINT((_L("CTNEDecoderWrap::WriteCodedBufferL(), Out")))
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::SendBufferL
+// Sends buffer to decoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::SendBufferL(TVideoBuffer* aBuffer)
+    {
+    PRINT((_L("CTNEDecoderWrap::SendBufferL(), In")))
+
+    PRINT((_L("CTNEDecoderWrap::SendBufferL(), iInputBuffer[%d], aBuffer[%d]"), iInputBuffer->iData.MaxLength(), 
+               aBuffer->BufferSize() ))
+
+    if ( iInputBuffer->iData.MaxLength() < aBuffer->BufferSize() )
+        {
+        PRINT((_L("CTNEDecoderWrap::SendBufferL(), buffer length exceeds max length")))
+        User::Leave(KErrOverflow);
+        }
+
+    iInputBuffer->iData.Copy( aBuffer->Data().Ptr(), aBuffer->BufferSize() );
+    iInputBuffer->iData.SetLength( aBuffer->BufferSize() );
+
+    // Data unit presentation timestamp. Valid if EPresentationTimestamp is set in the options. 
+    // If the input bitstream does not contain timestamp information, this field should be valid, 
+    // otherwise pictures cannot be displayed at the correct time. If the input bitstream contains 
+    // timestamp information (such as the TR syntax element of H.263 bitstreams) and valid 
+    // iPresentationTimestamp is provided, the value of iPresentationTimestamp is used in playback.    
+    iInputBuffer->iOptions = TVideoInputBuffer::EPresentationTimestamp;
+    iInputBuffer->iPresentationTimestamp = aBuffer->TimeStamp();
+ 
+ // @@ HARI AVC
+    iInputBuffer->iSequenceNumber = iInputFrameNum;
+    iInputFrameNum++;
+    iInputBuffer->iDecodingTimestamp = aBuffer->TimeStamp();
+    iInputBuffer->iPresentationTimestamp  = TTimeIntervalMicroSeconds(iClockSource->Time().Int64() + 1000000);
+
+ 
+    /*Other data: TBC*/
+
+    // Write data to decoder
+    iDevVideoPlay->WriteCodedDataL(iInputBuffer);
+
+    // Reset InputBuffer ptr
+    iInputBuffer = NULL;
+
+    // FIXME return buffer only after it's writtent to decoder (client could write next buffer synchronously from observer call)
+    // Return buffer to the client immediately after copying
+    iObserver->MReturnCodedBuffer(aBuffer);
+
+    PRINT((_L("CTNEDecoderWrap::SendBufferL(), Out")))
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::MdvpoNewPictures
+// New decoded pictures available from decoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::MdvpoNewPictures()
+    {
+    TInt status = KErrNone;
+
+
+    // 1 or more decoded pictures are available
+    if (!iDecodedPicture)
+        {
+        // Get new picture
+        TRAP(status, iDecodedPicture = iDevVideoPlay->NextPictureL());
+
+        if (status != KErrNone)
+            {
+            PRINT((_L("CTNEDecoderWrap::MdvpoNewPictures(), NextPicture status[%d]"), status))
+            iObserver->MNotifyThumbnailReady(status);
+            return;
+            }
+
+        if (!iDecodedPicture)
+            {
+            // Error: DevVideo notified of new buffers, but returns NULL
+            PRINT((_L("CTNEDecoderWrap::MdvpoNewPictures(), DevVideo notified of new buffers, but returns NULL")))
+            iObserver->MNotifyThumbnailReady(KErrAlreadyExists);
+            return;
+            }
+
+        // Send new picture to the client
+        iObserver->MPictureFromDecoder(iDecodedPicture);
+        }
+    else
+        {
+        // Previous picture still was not returned by the client, nothing to do. 
+        // FIXME SetActive();
+        }
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::ReturnPicture
+// Returns picture 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::ReturnPicture(TVideoPicture* aPicture)
+    {
+    PRINT((_L("CTNEDecoderWrap::ReturnPicture(), In")))
+    TInt status = KErrNone;
+
+
+    iDevVideoPlay->ReturnPicture(aPicture);
+
+    // Reset decoded picture
+    iDecodedPicture = NULL;
+
+    TRAP(status, iDecodedPicture = iDevVideoPlay->NextPictureL());
+
+    if (status != KErrNone)
+        {
+        PRINT((_L("CTNEDecoderWrap::ReturnPicture(), NextPicture status[%d]"), status))
+        iObserver->MNotifyThumbnailReady(status);
+        return;
+        }
+
+    if (iDecodedPicture)
+        {
+        // Send new picture to the client
+        iObserver->MPictureFromDecoder(iDecodedPicture);
+        }
+
+    PRINT((_L("CTNEDecoderWrap::ReturnPicture(), Out")))
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::StopL
+// Stops decoding synchronously
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::StopL()
+    {
+    PRINT((_L("CTNEDecoderWrap::StopL(), In")))
+
+    if (iFatalError == KErrNone)
+        {
+        iDevVideoPlay->Stop();
+        }
+        
+    iStop = ETrue;
+    iState = ETRStopped;
+        
+    PRINT((_L("CTNEDecoderWrap::StopL(), Out")))
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::AsyncStopL
+// Stops decoding asynchronously
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::AsyncStopL()
+    {
+    PRINT((_L("CTNEDecoderWrap::StopL(), Async In")))
+
+    if (iFatalError == KErrNone)
+        {
+        iDevVideoPlay->InputEnd();
+        }
+        
+    iStop = ETrue;
+    iState = ETRStopped;
+
+    PRINT((_L("CTNEDecoderWrap::StopL(), Async Out")))
+    }
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::GetNumInputFreeBuffers
+// returns the number of buffers that can be sent to 
+// decoder
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint CTNEDecoderWrap::GetNumInputFreeBuffers()
+{
+	TUint inputFreeBuffers = iDevVideoPlay->NumFreeBuffers();
+	
+	return inputFreeBuffers;
+}
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::MdvpoStreamEnd
+// Indicates when stream end is reached
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::MdvpoStreamEnd()
+    {
+    PRINT((_L("CTNEDecoderWrap::MdvpoStreamEnd()")))    
+    }
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::MdvpoReturnPicture
+// Returns a used input video picture back to the caller. The picture memory can be re-used or freed (only relevant to postprocessor)
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::MdvpoReturnPicture(TVideoPicture* /*aPicture*/)
+    {
+    PRINT((_L("CTNEDecoderWrap::MdvpoReturnPicture()")))
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::MdvpoSupplementalInformation
+// Sends SupplementalInformation
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::MdvpoSupplementalInformation(const TDesC8& /*aData*/, 
+                                                         const TTimeIntervalMicroSeconds& /*aTimestamp*/, 
+                                                         const TPictureId& /*aPictureId*/)
+    {
+    PRINT((_L("CTNEDecoderWrap::MdvpoSupplementalInformation()")))
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::MdvpoPictureLoss
+// Back channel information from the decoder, indicating a picture loss without specifying the lost picture
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::MdvpoPictureLoss()
+    {
+    PRINT((_L("CTNEDecoderWrap::MdvpoPictureLoss(), report an error")))
+    iObserver->MNotifyThumbnailReady(KErrAbort);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::MdvpoPictureLoss
+// Back channel information from the decoder, indicating the pictures that have been lost
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::MdvpoPictureLoss(const TArray< TPictureId >& /*aPictures*/)
+    {
+    PRINT((_L("CTNEDecoderWrap::MdvpoPictureLoss(), pictureId: report an error")))
+    iObserver->MNotifyThumbnailReady(KErrAbort);
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::MdvpoSliceLoss
+// Reports that slice is lost
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::MdvpoSliceLoss(TUint /*aFirstMacroblock*/, TUint /*aNumMacroblocks*/, 
+                                           const TPictureId& /*aPicture*/)
+    {
+    PRINT((_L("CTNEDecoderWrap::MdvpoSliceLoss()")))
+    // This error is not considered a s fatal for decoder or application, nothing to do
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::MdvpoReferencePictureSelection
+// Back channel information from the decoder, indicating a reference picture selection request.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::MdvpoReferencePictureSelection(const TDesC8& /*aSelectionData*/)
+    {
+    PRINT((_L("CTNEDecoderWrap::MdvpoReferencePictureSelection()")))
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::MdvpoTimedSnapshotComplete
+// Called when a timed snapshot request has been completed. 
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::MdvpoTimedSnapshotComplete(TInt /*aError*/, TPictureData* /*aPictureData*/, 
+                                                       const TTimeIntervalMicroSeconds& /*aPresentationTimestamp*/, 
+                                                       const TPictureId& /*aPictureId*/)
+    {
+    PRINT((_L("CTNEDecoderWrap::MdvpoTimedSnapshotComplete()")))
+    }
+
+
+// -----------------------------------------------------------------------------
+// CTNEDecoderWrap::MdvpoFatalError
+// Reports the fatal error to the client
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CTNEDecoderWrap::MdvpoFatalError(TInt aError)
+    {
+    PRINT((_L("CTNEDecoderWrap::MdvpoFatalError(), error[%d]"), aError))
+    iFatalError = aError;
+    iObserver->MNotifyThumbnailReady(iFatalError);
+    }
+
+
+
+
+// End of file