videoeditorengine/vedengine/src/VedVideoClipInfoImp.cpp
author Mikael Laine <mikael.laine@ixonos.com>
Fri, 29 Jan 2010 14:08:33 +0200
changeset 0 951a5db380a0
permissions -rw-r--r--
Committing the Video Editor package under the Eclipse Public License

/*
* Copyright (c) 2010 Ixonos Plc.
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the "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:
* Ixonos Plc
*
* Description:  
*
*/




#include "VedVideoClipInfoImp.h"
#include "movieprocessor.h"
#include <fbs.h>
#include <ecom/ecom.h>
#include "audclipinfo.h"
#include "audcommon.h"
#include "VedVideoClip.h"

// Print macro
#ifdef _DEBUG
#include <e32svr.h>
#define PRINT(x) RDebug::Print x
#else
#define PRINT(x)
#endif


EXPORT_C CVedVideoClipInfo* CVedVideoClipInfo::NewL(const TDesC& aFileName,
                                                    MVedVideoClipInfoObserver& aObserver)
    {
    PRINT(_L("CVedVideoClipInfo::NewL"));

    CVedVideoClipInfoImp* self = (CVedVideoClipInfoImp*)NewLC(aFileName, aObserver);
    self->iVideoClipIsStandalone = ETrue;
    CleanupStack::Pop(self);
    PRINT(_L("CVedVideoClipInfo::NewL out"));
    return self;
    }
    
EXPORT_C CVedVideoClipInfo* CVedVideoClipInfo::NewLC(const TDesC& aFileName,
                                                     MVedVideoClipInfoObserver& aObserver)
    {
    PRINT(_L("CVedVideoClipInfo::NewLC in"));

    CVedVideoClipInfoImp* self = new (ELeave) CVedVideoClipInfoImp(NULL);
    CleanupStack::PushL(self);
    self->ConstructL(aFileName, aObserver);

    PRINT(_L("CVedVideoClipInfo::NewLC out"));
    return self;
    }

EXPORT_C CVedVideoClipInfo* CVedVideoClipInfo::NewL(RFile* aFileHandle,
                                                    MVedVideoClipInfoObserver& aObserver)
    {
    PRINT(_L("CVedVideoClipInfo::NewL"));

    CVedVideoClipInfoImp* self = (CVedVideoClipInfoImp*)NewLC(aFileHandle, aObserver);
    self->iVideoClipIsStandalone = ETrue;
    CleanupStack::Pop(self);
    PRINT(_L("CVedVideoClipInfo::NewL out"));
    return self;
    }
    
EXPORT_C CVedVideoClipInfo* CVedVideoClipInfo::NewLC(RFile* aFileHandle,
                                                     MVedVideoClipInfoObserver& aObserver)
    {
    PRINT(_L("CVedVideoClipInfo::NewLC in"));

    CVedVideoClipInfoImp* self = new (ELeave) CVedVideoClipInfoImp(NULL);
    CleanupStack::PushL(self);
    self->ConstructL(aFileHandle, aObserver);

    PRINT(_L("CVedVideoClipInfo::NewLC out"));
    return self;
    }


CVedVideoClipInfo* CVedVideoClipInfoImp::NewL(CAudClipInfo* aAudClipInfo, 
                                              const TDesC& aFileName, MVedVideoClipInfoObserver& aObserver)
    {
    CVedVideoClipInfoImp* self = new (ELeave) CVedVideoClipInfoImp(aAudClipInfo);
    CleanupStack::PushL(self);
    if (aAudClipInfo) 
        {
        self->ConstructL(aAudClipInfo->FileName(), aObserver);
        }
    else
        {
        self->ConstructL(aFileName, aObserver);
        }
    self->iVideoClipIsStandalone = EFalse;
    CleanupStack::Pop(self);
    return self;
    }
    
CVedVideoClipInfo* CVedVideoClipInfoImp::NewL(CAudClipInfo* aAudClipInfo, 
                                              RFile* aFileHandle, MVedVideoClipInfoObserver& aObserver)
    {
    CVedVideoClipInfoImp* self = new (ELeave) CVedVideoClipInfoImp(aAudClipInfo);
    CleanupStack::PushL(self);
    if (aAudClipInfo) 
        {
        self->ConstructL(aAudClipInfo->FileHandle(), aObserver);
        }
    else
        {
        self->ConstructL(aFileHandle, aObserver);
        }
    self->iVideoClipIsStandalone = EFalse;
    CleanupStack::Pop(self);
    return self;
    }
    

CVedVideoClipInfoImp::CVedVideoClipInfoImp(CAudClipInfo* aAudClipInfo)
        : iReady(EFalse), iAudClipInfoOwnedByVideoClipInfo(EFalse), iAudClipInfo(aAudClipInfo)
    {
    }


void CVedVideoClipInfoImp::ConstructL(const TDesC& aFileName,
                                   MVedVideoClipInfoObserver& aObserver)
    {
    PRINT(_L("CVedVideoClipInfo::ConstructL in"));

    iFileName = HBufC::NewL(aFileName.Length());
    *iFileName = aFileName;

    iFrameOperation = CVedVideoClipFrameOperation::NewL(this);

    iInfoOperation = CVedVideoClipInfoOperation::NewL(this, aObserver);
    
    PRINT(_L("CVedVideoClipInfo::ConstructL out"));
    }
    
void CVedVideoClipInfoImp::ConstructL(RFile* aFileHandle,
                                   MVedVideoClipInfoObserver& aObserver)
    {
    PRINT(_L("CVedVideoClipInfo::ConstructL in"));

    iFileName = HBufC::NewL(1);
    iFileHandle = aFileHandle;

    iFrameOperation = CVedVideoClipFrameOperation::NewL(this);

    iInfoOperation = CVedVideoClipInfoOperation::NewL(this, aObserver);
    
    PRINT(_L("CVedVideoClipInfo::ConstructL out"));
    }
    

CVedVideoClipInfoImp::~CVedVideoClipInfoImp()
    {
    PRINT(_L("CVedVideoClipInfo::~CVedVideoClipInfoImp in"));

    delete iInfoOperation;
    delete iFrameOperation;

    User::Free(iVideoFrameInfoArray);
    delete iFileName;

    REComSession::FinalClose();

    if (iAudClipInfoOwnedByVideoClipInfo) 
        {
        delete iAudClipInfo;
        }

    PRINT(_L("CVedVideoClipInfo::~CVedVideoClipInfoImp out"));
    }


TPtrC CVedVideoClipInfoImp::DescriptiveName() const 
    {
    return *iFileName;
    }

CVedVideoClipGenerator* CVedVideoClipInfoImp::Generator() const
    {
    // Always panic
    TVedPanic::Panic(TVedPanic::EVideoClipInfoNoGeneratorAssociated);
    
    // This will never be reached.
    return NULL;
    }


TVedVideoClipClass CVedVideoClipInfoImp::Class() const 
    {
    return EVedVideoClipClassFile;
    }


TInt CVedVideoClipInfoImp::GenerateVideoFrameInfoArrayL() 
    {
    PRINT(_L("CVedVideoClipInfoImp::GenerateVideoFrameInfoArrayL in"));

    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    TInt error = KErrNone;

    if ( !iVideoFrameInfoArrayReady )
        {
        CMovieProcessor* processor = CMovieProcessor::NewL();
        CleanupStack::PushL(processor);
        TRAP( error, processor->GenerateVideoFrameInfoArrayL(*iFileName, iFileHandle, iVideoFrameInfoArray));
        CleanupStack::PopAndDestroy(processor);

        if ( (error == KErrNone) && iVideoFrameInfoArray )
            {
            iVideoFrameInfoArrayReady = ETrue;            
            }
        else
            {
            PRINT((_L("CVedVideoClipInfoImp::GenerateVideoFrameInfoArrayL Error=%d"), error));
            }
        }

    PRINT(_L("CVedVideoClipInfoImp::GenerateVideoFrameInfoArrayL out"));
    return error;
    }


TInt CVedVideoClipInfoImp::GetVideoFrameIndexL(TTimeIntervalMicroSeconds aTime)
    {
    PRINT(_L("CVedVideoClipInfoImp::GetVideoFrameIndex in"));

    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));
    __ASSERT_ALWAYS((aTime >= TTimeIntervalMicroSeconds(0)) && (aTime <= Duration()), 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalVideoFrameTime));

    /* Use binary search to find the right frame. */

    TInt start = 0;
    TInt end = iVideoFrameCount - 1;
    TInt index = -1;
    TBool always = ETrue;

    while( always )
        {
        index = start + ((end - start) / 2);

        TTimeIntervalMicroSeconds startTime = VideoFrameStartTimeL(index);
        TTimeIntervalMicroSeconds endTime = VideoFrameEndTimeL(index);
        if (index < (VideoFrameCount() - 1))
            {
            endTime = TTimeIntervalMicroSeconds(endTime.Int64() - 1);
            }

        if (aTime < startTime)
            {
            end = index - 1;
            }
        else if (aTime > endTime)
            {
            start = index + 1;
            }
        else
            {
            always = EFalse;
            }
        }

    PRINT(_L("CVedVideoClipInfoImp::GetVideoFrameIndex out"));
    return index;
    }


void CVedVideoClipInfoImp::GetFrameL(MVedVideoClipFrameObserver& aObserver, 
                                     TInt aIndex,
                                     TSize* const aResolution,
                                     TDisplayMode aDisplayMode,
                                     TBool aEnhance,
                                     TInt aPriority)
    {
    PRINT(_L("CVedVideoClipInfoImp::GetFrameL in"));

    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    iFrameOperation->StartL(aObserver, aIndex, aResolution, aDisplayMode, aEnhance, aPriority);
    
    PRINT(_L("CVedVideoClipInfoImp::GetFrameL out"));
    }


void CVedVideoClipInfoImp::CancelFrame()
    {
    PRINT(_L("CVedVideoClipInfoImp::CancelFrame in"));

    if ( !iReady )
        {
        PRINT(_L("CVedVideoClipInfoImp::CancelFrame not even info ready yet, cancel it and get out"));
        iInfoOperation->Cancel();
        return;
        }

    iFrameOperation->Cancel();

    PRINT(_L("CVedVideoClipInfoImp::CancelFrame out"));
    }




TPtrC CVedVideoClipInfoImp::FileName() const
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    return *iFileName;
    }
    
RFile* CVedVideoClipInfoImp::FileHandle() const
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    return iFileHandle;
    }


TVedVideoFormat CVedVideoClipInfoImp::Format() const
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    return iFormat;
    }


TVedVideoType CVedVideoClipInfoImp::VideoType() const
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    return iVideoType;
    }


TSize CVedVideoClipInfoImp::Resolution() const
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    return iResolution;
    }


TBool CVedVideoClipInfoImp::HasAudio() const
    {
    
    if (!iReady)  
        {
        if (iVideoClipIsStandalone)
            return EFalse;
        }

    if (iAudClipInfo == 0) 
        {
        return EFalse;
        }
    return ((iAudClipInfo->Properties().iAudioType != EAudTypeUnrecognized)
        && (iAudClipInfo->Properties().iAudioType != EAudNoAudio));
    }


TVedAudioType CVedVideoClipInfoImp::AudioType() const
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    if (iAudClipInfo == 0) 
        {
        return EVedAudioTypeNoAudio;
        }

    TVedAudioType vedAudioType = EVedAudioTypeUnrecognized;
    if (iAudClipInfo->Properties().iAudioType == EAudAMR)
        {
        vedAudioType = EVedAudioTypeAMR;
        }
    else if (iAudClipInfo->Properties().iAudioType == EAudAMRWB)
        {
        vedAudioType = EVedAudioTypeAMRWB;
        }
    else if (iAudClipInfo->Properties().iAudioType == EAudMP3)
        {
        vedAudioType = EVedAudioTypeMP3;
        }
    else if (iAudClipInfo->Properties().iAudioType == EAudAAC_MPEG4 )
        {
        vedAudioType = EVedAudioTypeAAC_LC;
        }
    else if (iAudClipInfo->Properties().iAudioType == EAudWAV)
        {
        vedAudioType = EVedAudioTypeWAV;
        }
    else if (iAudClipInfo->Properties().iAudioType == EAudNoAudio)
    	{
    	vedAudioType = EVedAudioTypeNoAudio;
    	}
        
    return vedAudioType;
    }

TVedAudioChannelMode CVedVideoClipInfoImp::AudioChannelMode() const
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    if (iAudClipInfo == 0) 
        {
        return EVedAudioChannelModeUnrecognized;
        }

    TVedAudioChannelMode vedChannelMode = EVedAudioChannelModeUnrecognized;
    if (iAudClipInfo->Properties().iChannelMode == EAudStereo)
        {
        vedChannelMode = EVedAudioChannelModeStereo;
        }
    else if (iAudClipInfo->Properties().iChannelMode == EAudSingleChannel)
        {
        vedChannelMode = EVedAudioChannelModeSingleChannel;
        }
    else if (iAudClipInfo->Properties().iChannelMode == EAudDualChannel)
        {
        vedChannelMode = EVedAudioChannelModeDualChannel;
        }

    return vedChannelMode;
    }

TInt CVedVideoClipInfoImp::AudioSamplingRate() const
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    if (iAudClipInfo == 0) 
        {
        return 0;
        }

    return iAudClipInfo->Properties().iSamplingRate;
    }


TTimeIntervalMicroSeconds CVedVideoClipInfoImp::Duration() const
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    return iDuration;
    }


TInt CVedVideoClipInfoImp::VideoFrameCount() const
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    return iVideoFrameCount;
    }


TTimeIntervalMicroSeconds CVedVideoClipInfoImp::VideoFrameStartTimeL(TInt aIndex)
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));
    __ASSERT_ALWAYS(((aIndex >= 0) && (aIndex < iVideoFrameCount)),
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalVideoFrameIndex));

    if ( !iVideoFrameInfoArrayReady )
        {
        User::LeaveIfError(GenerateVideoFrameInfoArrayL());
        }

    TInt64 startTime = TInt64(iVideoFrameInfoArray[aIndex].iStartTime) * TInt64(1000);
    return TTimeIntervalMicroSeconds(startTime);
    }


TTimeIntervalMicroSeconds CVedVideoClipInfoImp::VideoFrameEndTimeL(TInt aIndex)
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));
    __ASSERT_ALWAYS(((aIndex >= 0) && (aIndex < iVideoFrameCount)),
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalVideoFrameIndex));

    if ( !iVideoFrameInfoArrayReady )
        {
        User::LeaveIfError(GenerateVideoFrameInfoArrayL());
        }

    if (aIndex < (iVideoFrameCount - 1))
        {
        return (TInt64(iVideoFrameInfoArray[aIndex + 1].iStartTime) * TInt64(1000));
        }
    else
        {
        return iDuration;
        }
    }


TTimeIntervalMicroSeconds CVedVideoClipInfoImp::VideoFrameDurationL(TInt aIndex)
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));
    __ASSERT_ALWAYS(((aIndex >= 0) && (aIndex < iVideoFrameCount)),
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalVideoFrameIndex));

    if ( !iVideoFrameInfoArrayReady )
        {
        User::LeaveIfError(GenerateVideoFrameInfoArrayL());
        }


    TInt64 duration = - (TInt64(iVideoFrameInfoArray[aIndex].iStartTime) * TInt64(1000));
    if (aIndex < (iVideoFrameCount - 1))
        {
        duration += TInt64(iVideoFrameInfoArray[aIndex + 1].iStartTime) * TInt64(1000);
        }
    else
        {
        duration += iDuration.Int64();
        }

    return TTimeIntervalMicroSeconds(duration);
    }


TInt CVedVideoClipInfoImp::VideoFrameSizeL(TInt aIndex)
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));
    __ASSERT_ALWAYS(((aIndex >= 0) && (aIndex < iVideoFrameCount)),
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalVideoFrameIndex));

    if ( !iVideoFrameInfoArrayReady )
        {
        User::LeaveIfError(GenerateVideoFrameInfoArrayL());
        }


    return iVideoFrameInfoArray[aIndex].iSize;
    }


TBool CVedVideoClipInfoImp::VideoFrameIsIntraL(TInt aIndex)
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));
    __ASSERT_ALWAYS(((aIndex >= 0) && (aIndex < iVideoFrameCount)),
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalVideoFrameIndex));

    if ( !iVideoFrameInfoArrayReady )
        {
        User::LeaveIfError(GenerateVideoFrameInfoArrayL());
        }

    if (iVideoFrameInfoArray[aIndex].iFlags & KVedVideoFrameInfoFlagIntra)
        {
        return ETrue;
        }
    else
        {
        return EFalse;
        }
    }

void CVedVideoClipInfoImp::SetTranscodeFactor(TVedTranscodeFactor aFactor)
    {
    iTimeFactor.iStreamType = aFactor.iStreamType;
    iTimeFactor.iTRes = aFactor.iTRes;
    }

TVedTranscodeFactor CVedVideoClipInfoImp::TranscodeFactor()
    {
    return iTimeFactor;
    }

TBool CVedVideoClipInfoImp::IsMMSCompatible()
    {
    __ASSERT_ALWAYS(iReady, 
                    TVedPanic::Panic(TVedPanic::EVideoClipInfoNotReady));

    TAudType audioType;
    if (iAudClipInfo == 0) 
        {
        audioType = EAudNoAudio;
        }
    else
        {
        audioType = iAudClipInfo->Properties().iAudioType;
        }

    return ( ( iFormat == EVedVideoFormat3GPP ) &&
             ( iVideoType == EVedVideoTypeH263Profile0Level10 ) &&
             ( audioType == EAudAMR ) );
    }


CVedVideoClipInfoOperation* CVedVideoClipInfoOperation::NewL(CVedVideoClipInfoImp* aInfo,
                                                             MVedVideoClipInfoObserver& aObserver)
    {
    PRINT(_L("CVedVideoClipInfoOperation::NewL in"));

    CVedVideoClipInfoOperation* self = 
        new (ELeave) CVedVideoClipInfoOperation(aInfo, aObserver);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);

    PRINT(_L("CVedVideoClipInfoOperation::NewL out"));
    return self;
    }


CVedVideoClipInfoOperation::CVedVideoClipInfoOperation(CVedVideoClipInfoImp* aInfo,
                                                       MVedVideoClipInfoObserver& aObserver)
        : CActive(EPriorityStandard), iInfo(aInfo), iMovieProcessorError(KErrNone)
    {
    PRINT(_L("CVedVideoClipInfoOperation::CVedVideoClipInfoOperation in"));

    iObserver = &aObserver;
    CActiveScheduler::Add(this);

    PRINT(_L("CVedVideoClipInfoOperation::CVedVideoClipInfoOperation out"));
    }


void CVedVideoClipInfoOperation::ConstructL()
    {
    PRINT(_L("CVedVideoClipInfoOperation::ConstructL in"));

    iGettingAudio = EFalse;

    SetActive();
    TRequestStatus* status = &iStatus;
    User::RequestComplete(status, KErrNone);

    PRINT(_L("CVedVideoClipInfoOperation::ConstructL out"));
    }


CVedVideoClipInfoOperation::~CVedVideoClipInfoOperation()
    {
    Cancel();
    }


void CVedVideoClipInfoOperation::RunL()
    {
    PRINT(_L("CVedVideoClipInfoOperation::RunL in"));    
 
    if (iGettingAudio) 
        {
        if (iMovieProcessorError == KErrNone || iMovieProcessorError == KErrNoAudio) 
            {
            iInfo->iReady = ETrue;
            iMovieProcessorError = KErrNone;
            }
        iObserver->NotifyVideoClipInfoReady(*iInfo, iMovieProcessorError);
        }
    else
        {
        CMovieProcessor* processor = CMovieProcessor::NewL();
        TVedAudioType audioType = EVedAudioTypeUnrecognized;
        TVedAudioChannelMode audioChannelMode = EVedAudioChannelModeUnrecognized;
        TInt audioSamplingRate;
        TRAP(iMovieProcessorError,
             processor->GetVideoClipPropertiesL(*iInfo->iFileName, 
                                                iInfo->iFileHandle,
                                                iInfo->iFormat,
                                                iInfo->iVideoType,
                                                iInfo->iResolution,
                                                audioType,
                                                iInfo->iDuration,
                                                iInfo->iVideoFrameCount,
                                                audioSamplingRate,
                                                audioChannelMode));    
        delete processor;
        processor = 0;                
        
        if (iMovieProcessorError != KErrNone) 
            {
            iObserver->NotifyVideoClipInfoReady(*iInfo, iMovieProcessorError);
            }
        else if (iInfo->iAudClipInfo || !iInfo->iVideoClipIsStandalone)
            {
            if (iMovieProcessorError == KErrNone) 
                {
                iInfo->iReady = ETrue;
                }
            iObserver->NotifyVideoClipInfoReady(*iInfo, iMovieProcessorError);
            }
        else
            {
            
            if (iInfo->iFileHandle)
                iInfo->iAudClipInfo = CAudClipInfo::NewL(iInfo->iFileHandle, *this);
            else
                iInfo->iAudClipInfo = CAudClipInfo::NewL(*iInfo->iFileName, *this);
            
            iInfo->iAudClipInfoOwnedByVideoClipInfo = ETrue;
            iGettingAudio = ETrue;
            }
        }
    PRINT(_L("CVedVideoClipInfoOperation::RunL out"));
    }

void CVedVideoClipInfoOperation::NotifyClipInfoReady(CAudClipInfo& /*aInfo*/, TInt aError)
    {
    SetActive();
    TRequestStatus* status = &iStatus;
    User::RequestComplete(status, KErrNone);
    
    iMovieProcessorError = aError;
    }

void CVedVideoClipInfoOperation::DoCancel()
    {
    }


CVedVideoClipFrameOperation* CVedVideoClipFrameOperation::NewL(CVedVideoClipInfoImp* aInfo)
    {
    PRINT(_L("CVedVideoClipFrameOperation::NewL in"));

    CVedVideoClipFrameOperation* self = 
        new (ELeave) CVedVideoClipFrameOperation(aInfo);
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);

    PRINT(_L("CVedVideoClipFrameOperation::NewL out"));
    return self;
    }


CVedVideoClipFrameOperation::CVedVideoClipFrameOperation(CVedVideoClipInfoImp* aInfo)
        : CActive(EPriorityIdle), iInfo(aInfo)
    {
    PRINT(_L("CVedVideoClipFrameOperation::CVedVideoClipFrameOperation in"));
    CActiveScheduler::Add(this);
    PRINT(_L("CVedVideoClipFrameOperation::CVedVideoClipFrameOperation out"));
    }


void CVedVideoClipFrameOperation::ConstructL()
    {
    }


CVedVideoClipFrameOperation::~CVedVideoClipFrameOperation()
    {
    Cancel();
    }


void CVedVideoClipFrameOperation::StartL(MVedVideoClipFrameObserver& aObserver,
                                         TInt aIndex,
                                         TSize* const aResolution, 
                                         TDisplayMode aDisplayMode,
                                         TBool aEnhance,
                                         TInt aPriority)
    {
    PRINT(_L("CVedVideoClipFrameOperation::StartL in"));

    __ASSERT_ALWAYS(!IsActive(), 
        TVedPanic::Panic(TVedPanic::EVideoClipInfoFrameOperationAlreadyRunning));
    __ASSERT_DEBUG(iProcessor == 0, TVedPanic::Panic(TVedPanic::EInternal));

    TSize resolution;
    if (aResolution != 0)
        {
        __ASSERT_ALWAYS(aResolution->iWidth > 0, 
            TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalFrameResolution));
        __ASSERT_ALWAYS(aResolution->iHeight > 0, 
            TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalFrameResolution));

        resolution = *aResolution;
        }
    else
        {
        resolution = iInfo->Resolution();
        }

    __ASSERT_ALWAYS(((aIndex >= 0) && (iInfo->VideoFrameCount() == 0) || 
                                      (aIndex < iInfo->VideoFrameCount()) || 
                                      (aIndex == KFrameIndexBestThumb) ), 
            TVedPanic::Panic(TVedPanic::EVideoClipInfoIllegalVideoFrameIndex));

    iIndex = aIndex;
    
    iFactor.iStreamType = EVedVideoBitstreamModeUnknown;
    iFactor.iTRes = 0;

    CMovieProcessor* processor = CMovieProcessor::NewLC();  

    processor->StartThumbL(iInfo->FileName(), iInfo->FileHandle(), aIndex, resolution, aDisplayMode,
                           aEnhance);

    /* Initialization OK. This method cannot leave any more. Start processing. */

    CleanupStack::Pop(processor);

    iProcessor = processor;
    iObserver = &aObserver;

    SetPriority(aPriority);
    SetActive();
    TRequestStatus* status = &iStatus;
    User::RequestComplete(status, KErrNone);

    PRINT(_L("CVedVideoClipFrameOperation::StartL out"));
    }


void CVedVideoClipFrameOperation::RunL()
    {
    PRINT(_L("CVedVideoClipFrameOperation::RunL in"));

    __ASSERT_DEBUG(iProcessor != 0, TVedPanic::Panic(TVedPanic::EInternal));
    __ASSERT_DEBUG(iObserver != 0, TVedPanic::Panic(TVedPanic::EInternal));
    
    TInt err = KErrNone;
    
    if (!iThumbRequestPending)
        TRAP(err, iProcessor->ProcessThumbL(iStatus, &iFactor));
    
    if (err != KErrNone)
        {
        delete iProcessor;
        iProcessor = 0;
        
        MVedVideoClipFrameObserver* observer = iObserver;
        iObserver = 0;
        observer->NotifyVideoClipFrameCompleted(*iInfo, err, NULL);
        return;
        }
        
    if (!iThumbRequestPending)
    {        
        iInfo->SetTranscodeFactor(iFactor);
        iThumbRequestPending = ETrue;
        iStatus = KRequestPending;
        SetActive();        
        return;
    }
    else
    {
        MVedVideoClipFrameObserver* observer = iObserver;
        iObserver = 0;
                
        if (iStatus == KErrNone)
        {
            CFbsBitmap* frame = 0;
            iProcessor->FetchThumb(frame);
            observer->NotifyVideoClipFrameCompleted(*iInfo, KErrNone, frame);            
        }
        else
        {
            observer->NotifyVideoClipFrameCompleted(*iInfo, iStatus.Int(), NULL);            
        }
        iThumbRequestPending = EFalse;
        delete iProcessor;
        iProcessor = 0;
    }      
        
    PRINT(_L("CVedVideoClipFrameOperation::RunL out"));
    }


void CVedVideoClipFrameOperation::DoCancel()
    {
    if (iProcessor != 0)
        {
        delete iProcessor;
        iProcessor = 0;
        
        // Cancel our internal request
        if ( iStatus == KRequestPending )
        {
            PRINT((_L("CVedVideoClipFrameOperation::DoCancel() cancel request")));
            TRequestStatus *status = &iStatus;
            User::RequestComplete(status, KErrCancel);
        }
        iThumbRequestPending = EFalse;

        MVedVideoClipFrameObserver* observer = iObserver;
        iObserver = 0;
        observer->NotifyVideoClipFrameCompleted(*iInfo, KErrCancel, NULL);
        }
    }