--- a/videoeditorengine/vedengine/videoprocessor/src/videoprocessor.cpp Fri Jan 29 14:08:33 2010 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,6628 +0,0 @@
-/*
-* 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:
-* Implementation for video processor.
-*
-*/
-
-
-// Include Files
-
-#include "vedcommon.h"
-#include "movieprocessorimpl.h"
-#include "statusmonitor.h"
-#include "activequeue.h"
-#include "dataprocessor.h"
-#include "h263dmai.h" // CVedH263Dec
-#include "mp4parser.h"
-#include "videoencoder.h"
-#include "videoprocessor.h"
-#include "mpeg4timer.h"
-#include "vedvolreader.h"
-#include "vedvideosettings.h"
-#include "vedavcedit.h"
-
-// Local constants
-const TUint KInitialDataBufferSize = 8192; // initial frame data buffer size
-const TUint KH263StartCodeLength = 3; // H.263 picture start code length
-const TUint KMPEG4StartCodeLength = 4; // MPEG4 picture start code length
-//const TUint KMaxEncodingDelay = 500000; // time to wait for encoding to complete in microsec.
-const TUint KDefaultTimeIncrementResolution = 30000;
-const TUint KAVCNotCodedFrameBuffer = 128;
-const TUint KMaxItemsInProcessingQueue = 3; // note! this must be synchronized with KTRMinNumberOfBuffersCodedPicture setting in transcoder!
-
-
-#ifdef _DEBUG
-const TInt KErrorCode = CVideoProcessor::EDecoderFailure;
-#else
-const TInt KErrorCode = KErrGeneral;
-#endif
-
-// An assertion macro wrapper to clean up the code a bit
-#define VDASSERT(x, n) __ASSERT_DEBUG(x, User::Panic(_L("CVideoProcessor"), EInternalAssertionFailure+n))
-
-// Debug print macro
-
-#ifdef _DEBUG
-#include <e32svr.h>
-#define PRINT(x) RDebug::Print x;
-#else
-#define PRINT(x)
-#endif
-
-// ================= STATIC FUNCTIONS =======================
-
-// ---------------------------------------------------------
-// AddBits
-// Static helper function to add bits to byte-buffer
-// ---------------------------------------------------------
-//
-static void AddBits(TUint8* aBuf, TInt& aBitIndex, TInt& aByteIndex, TInt aBits, TInt aNrOfBits)
- {
- // aBitIndex = 8 => first bit in the left
- // aBitIndex = 1 => last bit in the right
- while ( aBitIndex < aNrOfBits )
- {
- // divide into n bytes
- aBuf[aByteIndex++] |= TUint8( aBits >> (aNrOfBits-aBitIndex) );
- aNrOfBits -= aBitIndex;
- aBitIndex = 8;
- }
- // all bits fit into 1 byte
- aBitIndex -= aNrOfBits;
- aBuf[aByteIndex] |= TUint8( aBits << aBitIndex );
- if (aBitIndex == 0)
- {
- aBitIndex = 8;
- aByteIndex++;
- }
- }
-
-
-
-// ================= MEMBER FUNCTIONS =======================
-
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::NewL
-// Symbian two-phased constructor.
-// ---------------------------------------------------------
-//
-
-CVideoProcessor* CVideoProcessor::NewL(CActiveQueue *anInputQueue,
- CVideoProcessor::TStreamParameters *aStreamParameters,
- CMovieProcessorImpl* aProcessor,
- CStatusMonitor *aStatusMonitor,
- CVedAVCEdit *aAvcEdit,
- TBool aThumbnailMode,
- TInt aPriority)
-{
- CVideoProcessor *self = new (ELeave) CVideoProcessor(anInputQueue,
- aStreamParameters,
- aProcessor,
- aStatusMonitor,
- aAvcEdit,
- aThumbnailMode,
- aPriority);
-
- CleanupStack::PushL(self);
- self->ConstructL();
- CleanupStack::Pop();
-
- return self;
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::CVideoProcessor
-// Constructor.
-// ---------------------------------------------------------
-//
-CVideoProcessor::CVideoProcessor(CActiveQueue *anInputQueue,
- TStreamParameters *aStreamParameters,
- CMovieProcessorImpl* aProcessor,
- CStatusMonitor *aStatusMonitor,
- CVedAVCEdit *aAvcEdit,
- TBool aThumbnailMode,
- TInt aPriority) : CVideoDecoder(aPriority),
- iWriteDes(0,0),
- iThumbnailMode(aThumbnailMode)
-{
-
- // Remember the objects
- iQueue = anInputQueue;
- iMonitor = aStatusMonitor;
- iProcessor = aProcessor;
- iAvcEdit = aAvcEdit;
-
- // Remember the stream parameters
- iVideoWidth = aStreamParameters->iWidth;
- iVideoHeight = aStreamParameters->iHeight;
-
- // Color Toning
- iFirstFrameQp = 0;
-
- iTiming = aStreamParameters->iTiming;
- // Reset state
- iReaderSet = EFalse;
- iDecoding = EFalse;
- iStreamEnd = EFalse;
- iPreviousFrameIncluded = EFalse;
- iFrameOperation = EDecodeAndWrite;
-
- iTrPrevious = -1;
-
- iFirstFrameFlag = ETrue;
- iDecodePending = EFalse;
-
- iTranscoderStarted = EFalse;
- iDecodingSuspended = EFalse;
-
- iStartTransitionColor = EColorNone;
- iEndTransitionColor = EColorNone;
- iStartNumberOfTransitionFrames = KNumTransitionFrames;
- iEndNumberOfTransitionFrames = KNumTransitionFrames;
- iNextTransitionNumber = -1;
- iProcessingComplete = EFalse;
- iStreamEndRead = EFalse;
-
- iPreviousTimeStamp = TTimeIntervalMicroSeconds(-1);
-
- iFirstRead = ETrue;
-
- iThumbDecoded = EFalse;
-
- iMaxItemsInProcessingQueue = KMaxItemsInProcessingQueue;
-
- iDataFormat = EDataUnknown;
-
- iLastWrittenFrameNumber = -1;
-
- iInitializing = ETrue;
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::~CVideoProcessor()
-// Destructor
-// ---------------------------------------------------------
-//
-CVideoProcessor::~CVideoProcessor()
-{
-
- // If we are decoding, stop
- if (iDecoding)
- Stop();
-
- // Remove from being a reader
- if (iReaderSet)
- {
- // Return current block and all
- // blocks from input queue
- if (iBlock)
- {
- if (iQueue)
- iQueue->ReturnBlock(iBlock);
- }
-
- if (iQueue)
- iBlock = iQueue->ReadBlock();
-
- while (iBlock)
- {
- if (iQueue)
- {
- iQueue->ReturnBlock(iBlock);
- iBlock = iQueue->ReadBlock();
- }
- }
- iBlockPos = 0;
-
- if (iQueue)
- iQueue->RemoveReader();
- }
- Cancel();
-
- if (iTransCoder)
- {
- if (iTranscoderStarted)
- {
- TRAPD(error, iTransCoder->StopL());
- if (error != KErrNone) { }
- }
- delete iTransCoder;
- iTransCoder = 0;
- }
-
- iFrameInfoArray.Reset();
-
- // Close the decoder instance if one has been opened
- if (iDecoder)
- delete iDecoder;
- iDecoder = 0;
-
- // Deallocate buffers
- if (iDataBuffer)
- User::Free(iDataBuffer);
-
- if (iOutVideoFrameBuffer)
- User::Free(iOutVideoFrameBuffer);
-
- if (iFrameBuffer)
- User::Free(iFrameBuffer);
-
- if ( iColorTransitionBuffer )
- User::Free( iColorTransitionBuffer );
-
- if ( iOrigPreviousYUVBuffer )
- User::Free( iOrigPreviousYUVBuffer );
-
- if (iMediaBuffer)
- delete iMediaBuffer;
- iMediaBuffer = 0;
-
- if (iDecoderSpecificInfo)
- delete iDecoderSpecificInfo;
- iDecoderSpecificInfo = 0;
-
- if (iOutputVolHeader)
- delete iOutputVolHeader;
- iOutputVolHeader = 0;
-
- if (iDelayedBuffer)
- delete iDelayedBuffer;
- iDelayedBuffer = 0;
-
- if (iMPEG4Timer)
- delete iMPEG4Timer;
- iMPEG4Timer = 0;
-
- if (iTimer)
- delete iTimer;
- iTimer = 0;
-
- if (iNotCodedFrame)
- delete iNotCodedFrame;
- iNotCodedFrame = 0;
-
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::ConstructL()
-// Symbian 2nd phase constructor can leave.
-// ---------------------------------------------------------
-//
-void CVideoProcessor::ConstructL()
-{
- // Set as a reader to the input queue
- iQueue->SetReader(this, NULL);
- iReaderSet = ETrue;
-
- // Add us to active scheduler
- CActiveScheduler::Add(this);
-
- iMediaBuffer = new (ELeave)CCMRMediaBuffer;
-
- // Allocate buffers
- iDataBuffer = (TUint8*) User::AllocL(KInitialDataBufferSize);
- iBufferLength = KInitialDataBufferSize;
-
- if ( iThumbnailMode )
- {
- TSize a = iProcessor->GetMovieResolution();
- TInt length = a.iWidth*a.iHeight;
-
- length += (length>>1);
- iFrameBuffer = (TUint8*)User::AllocL(length);
- }
-
- TSize size(iVideoWidth, iVideoHeight);
-
- if (!iThumbnailMode)
- {
- // Open a decoder instance
- iDecoder = CVedH263Dec::NewL(size, 1 /*iReferencePicturesNeeded*/);
-
- // create timer
- iTimer = CCallbackTimer::NewL(*this);
- }
-
- // Make us active
- SetActive();
- iStatus = KRequestPending;
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::Start
-// Starts decoding
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::Start()
-{
- if ( iDecoding )
- return;
-
- // Activate the object if we have data
- if ( (!iDecodePending) && (iStatus == KRequestPending) && iQueue->NumDataBlocks() )
- {
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- }
-
- iDecoding = ETrue;
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::Stop
-// Stops decoding
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-
-void CVideoProcessor::Stop()
-{
- iDecoding = EFalse;
-
- if (iTimer)
- iTimer->CancelTimer();
-
- if (iTranscoderStarted)
- {
- TRAPD(error, iTransCoder->StopL());
- if (error != KErrNone) { }
- iTranscoderStarted = EFalse;
- }
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::RunL
-// Standard active object running method
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-
-void CVideoProcessor::RunL()
-{
- PRINT((_L("CVideoProcessor::RunL() in")))
-
- // Don't decode if we aren't decoding
- if (!iDecoding)
- {
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
- PRINT((_L("CVideoProcessor::RunL() out from !iDecoding branch")))
- return;
- }
-
- if (iTranscoderInitPending)
- {
- iTranscoderInitPending = EFalse;
- if (iStatus != KErrNone)
- {
- if (!iThumbnailMode)
- {
- VDASSERT(iMonitor, 101);
- iMonitor->Error(iStatus.Int());
- }
- else
- {
- iProcessor->NotifyThumbnailReady(iStatus.Int());
- }
-
- return;
- }
- // at this point we have already read a frame,
- // so now start processing
- iTransCoder->StartL();
-
- // stop if a fatal error has occurred in starting
- // the transcoder (decoding stopped in MtroFatalError)
- if (!iDecoding)
- return;
-
- iTranscoderStarted = ETrue;
-
- if (!iThumbnailMode)
- {
- ProcessFrameL();
- if (iDecodePending)
- return;
- }
- else
- {
- ProcessThumb(ETrue);
- return;
- }
- }
-
- if (iDecodePending)
- {
- iDecodePending = EFalse;
-
- if (iThumbnailMode)
- {
- if (iThumbDecoded)
- {
- PRINT((_L("CVideoProcessor::RunL() - thumb decoded")))
- ProcessThumb(EFalse);
- }
- else
- {
- PRINT((_L("CVideoProcessor::RunL() - thumb not decoded")))
- ReadAndWriteThumbFrame();
- }
- return;
- }
- }
-
- if (iProcessingComplete)
- {
- PRINT((_L("CVideoProcessor::RunL() iProcessingComplete == ETrue")))
- VDASSERT(iMonitor, 102);
- iMonitor->ClipProcessed();
- return;
- }
-
- if (iFirstColorTransitionFrame)
- {
- Process2ndColorTransitionFrameL();
- return;
- }
-
- while (!iDecodePending && !iDelayedWrite && !iTranscoderInitPending &&
- ReadFrame() )
- {
- // process it
- if ( ProcessFrameL() )
- {
- // clip processed up until cut-out time, stop
- if (iFrameInfoArray.Count())
- {
- PRINT((_L("CVideoProcessor::RunL() - stream end reached, wait for frames")));
- iStreamEnd = iStreamEndRead = ETrue;
-
- // if there are still frames to be encoded, start timer
- // since encoder may skip the rest of the frames
- if ( IsNextFrameBeingEncoded() )
- {
- PRINT((_L("CVideoProcessor::RunL(), set timer")));
- if ( !iTimer->IsPending() )
- iTimer->SetTimer( TTimeIntervalMicroSeconds32( iMaxEncodingDelay ) );
- }
- return;
- }
-
- iTimer->CancelTimer();
- if (iTranscoderStarted)
- {
- iTransCoder->StopL();
- iTranscoderStarted = EFalse;
- }
- VDASSERT(iMonitor, 103);
- iMonitor->ClipProcessed();
- PRINT((_L("CVideoProcessor::RunL() out from ProcessFrameL == ETrue")))
- return;
- }
- }
-
- if ( !iDecodePending && !iDelayedWrite && !iTranscoderInitPending )
- {
-
- // We didn't get a frame
- if (iStreamEnd)
- {
- iStreamEndRead = ETrue;
- PRINT((_L("CVideoProcessor::RunL() - stream end reached")));
- if (iFrameInfoArray.Count())
- {
- PRINT((_L("CVideoProcessor::RunL() - stream end reached, wait for frames")));
- // wait until frames have been processed
-
- // if there are still frames to be encoded, start timer
- // since encoder may skip the rest of the frames
- if ( IsNextFrameBeingEncoded() )
- {
- PRINT((_L("CVideoProcessor::RunL(), set timer")));
- if ( !iTimer->IsPending() )
- iTimer->SetTimer( TTimeIntervalMicroSeconds32( iMaxEncodingDelay ) );
- }
- return;
- }
- else
- {
- iTimer->CancelTimer();
- VDASSERT(iMonitor, 104);
- iMonitor->ClipProcessed();
- }
- }
- else
- {
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
- }
- }
-
- PRINT((_L("CVideoProcessor::RunL() out")))
-
-}
-
-// -----------------------------------------------------------------------------
-// CVideoProcessor::RunError
-// Called by the AO framework when RunL method has leaved
-// (other items were commented in a header).
-// -----------------------------------------------------------------------------
-//
-TInt CVideoProcessor::RunError(TInt aError)
-{
-
- if ((aError == CVedH263Dec::EDecoderNoIntra) || (aError == CVedH263Dec::EDecoderCorrupted))
- {
- if (!iThumbnailMode)
- iMonitor->Error(KErrCorrupt);
- else
- iProcessor->NotifyThumbnailReady(KErrCorrupt);
- }
- else
- {
- if (!iThumbnailMode)
- iMonitor->Error(aError);
- else
- iProcessor->NotifyThumbnailReady(aError);
- }
-
- return KErrNone;
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::Process2ndColorTransitionFrameL
-// Processes the second frame of a color transition double frame
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TBool CVideoProcessor::Process2ndColorTransitionFrameL()
-{
-
- TFrameInformation frameInfo;
- frameInfo.iTranscoderMode = EFullWithIM;
- frameInfo.iFrameNumber = iFrameNumber;
- frameInfo.iEncodeFrame = ETrue;
- frameInfo.iKeyFrame = EFalse;
- frameInfo.iTransitionFrame = ETrue;
- frameInfo.iTransitionPosition = EPositionStartOfClip;
- frameInfo.iTransitionColor = iStartTransitionColor;
- frameInfo.iTransitionFrameNumber = iTransitionFrameNumber;
- frameInfo.iModificationApplied = EFalse;
- frameInfo.iRepeatFrame = ETrue;
-
- TInt duration;
- // get timestamp
- iProcessor->GetNextFrameDuration(duration, frameInfo.iTimeStamp, iTimeStampIndex, iTimeStampOffset);
- iTimeStampIndex++;
-
- frameInfo.iTimeStamp += iCutInTimeStamp;
-
- TTimeIntervalMicroSeconds ts = (iProcessor->GetVideoTimeInMsFromTicks(frameInfo.iTimeStamp, EFalse)) * 1000;
-
- if (ts <= iPreviousTimeStamp)
- {
- // adjust timestamp so that its bigger than ts of previous frame
- TReal frameRate = iProcessor->GetVideoClipFrameRate();
- VDASSERT(frameRate > 0.0, 105);
- TInt64 durationMs = TInt64( ( 1000.0 / frameRate ) + 0.5 );
- durationMs /= 2; // add half the duration of one frame
-
- ts = TTimeIntervalMicroSeconds( iPreviousTimeStamp.Int64() + durationMs*1000 );
-
- frameInfo.iTimeStamp = iProcessor->GetVideoTimeInTicksFromMs( ts.Int64()/1000, EFalse );
-
- ts = iProcessor->GetVideoTimeInMsFromTicks(frameInfo.iTimeStamp, EFalse) * 1000;
-
- PRINT((_L("CVideoProcessor::Process2ndColorTransitionFrameL() - adjusted timestamp, prev = %d, new = %d"),
- I64INT( iPreviousTimeStamp.Int64() ) / 1000, I64INT( ts.Int64() ) / 1000));
-
- }
-
-
- iFrameInfoArray.Append(frameInfo);
-
- iPreviousTimeStamp = ts;
-
- iFirstColorTransitionFrame = EFalse;
-
- CCMRMediaBuffer::TBufferType bt =
- (iDataFormat == EDataH263) ? CCMRMediaBuffer::EVideoH263 : CCMRMediaBuffer::EVideoMPEG4;
-
- if (!iNotCodedFrame)
- GenerateNotCodedFrameL();
-
- PRINT((_L("CVideoProcessor::Process2ndColorTransitionFrameL() - sending not coded")));
-
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
- if (iDataFormat == EDataAVC)
- {
- TPtr8 ptr(iNotCodedFrame->Des());
-
- TInt length = iNotCodedFrame->Length();
- iAvcEdit->ProcessAVCBitStreamL((TDes8&)(ptr), length, 0 /*dummy*/, EFalse );
- ptr.SetLength(length);
- iDataLength = iCurrentFrameLength = length;
- }
-#endif
-
- iMediaBuffer->Set( TPtrC8(iNotCodedFrame->Des().Ptr(), iNotCodedFrame->Length()),
- bt,
- iNotCodedFrame->Length(),
- EFalse,
- ts );
-
- iDecodePending = ETrue;
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
-
- PRINT((_L("CVideoProcessor::Process2ndColorTransitionFrameL() - WriteCodedBuffer, frame #%d, timestamp %d ms"),
- iFrameNumber, I64INT( ts.Int64() ) / 1000 ));
- iTransCoder->WriteCodedBufferL(iMediaBuffer);
-
- iFrameNumber++;
-
- return ETrue;
-
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::GenerateNotCodedFrameL
-// Generate bitstream for not coded frame
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::GenerateNotCodedFrameL()
-{
-
- TSize resolution = iProcessor->GetVideoClipResolution();
-
- if (iDataFormat == EDataH263)
- {
- // H.263 QCIF picture header
- TInt headerSize = 7;
- TUint8 notCodedH263[] = { 0x00, 0x00, 0x80, 0x02, 0x0a, 0x0c, 0x3f };
- TUint8 lsbMask[8] = { 255, 254, 252, 248, 240, 224, 192, 128 };
-
-
- if ( resolution == TSize(128,96) )
- notCodedH263[4] = 0x06; // set source format as sub-QCIF
-
- else if ( resolution == TSize(352, 288) )
- notCodedH263[4] = 0x0e; // set source format as CIF
-
- else if ( resolution != TSize(176,144) )
- User::Panic(_L("CVideoProcessor"), EInternalAssertionFailure);
-
- TInt numMBs = ( resolution.iWidth / 16 ) * ( resolution.iHeight / 16 );
-
- // one COD bit for each MB, the last byte of the pic header already contains 6 MB bits
- TInt bitsLeft = numMBs - 6;
-
- TInt bufSize = headerSize + ( bitsLeft / 8 ) + ( bitsLeft % 8 != 0 );
-
- VDASSERT(!iNotCodedFrame, 117);
- iNotCodedFrame = (HBufC8*) HBufC8::NewL(bufSize);
-
- TPtr8 buf(iNotCodedFrame->Des());
- buf.Copy(notCodedH263, headerSize);
-
- TInt index = headerSize;
- TUint8* ptr = const_cast<TUint8*>(buf.Ptr());
-
- // set COD bit to 1 for all macroblocks
- while (bitsLeft >= 8)
- {
- ptr[index++] = 0xff;
- bitsLeft -= 8;
- }
-
- if (bitsLeft)
- {
- TUint8 val = 0;
- val |= lsbMask[8 - bitsLeft];
- ptr[index] = val;
- }
- buf.SetLength(bufSize);
- }
-
- else if (iDataFormat == EDataMPEG4)
- {
- VDASSERT(iDataFormat == EDataMPEG4, 115);
-
- TUint8 vopStartCodeMPEG4[] = { 0x00, 0x00, 0x01, 0xb6 };
-
- TInt headerSize = 4;
-
- // calculate the number of bits needed for vop_time_increment
- TInt numTiBits;
- for (numTiBits = 1; ((iInputTimeIncrementResolution - 1) >> numTiBits) != 0; numTiBits++)
- {
- }
-
- VDASSERT(numTiBits <= 16, 116);
-
- TInt numMBs = ( resolution.iWidth / 16 ) * ( resolution.iHeight / 16 );
-
- // get VOP size
- // vop_start_code: 32
- // vop_coding_type + modulo_time_base + marker_bit: 4
- // no. of bits for vop_time_increment
- // marker_bit + vop_coded bit: 2
- // rounding_type: 1
- // intra_dc_vlc_thr: 3
- // vop_quant: 5
- // vop_fcode_forward: 3
- // not_coded for each MB: numMBs
- TInt bufSizeBits = headerSize * 8 + 4 + numTiBits + 2 + 1 + 3 + 5 + 3 + numMBs;//DP mode not included!
- if ( (iInputStreamMode == EVedVideoBitstreamModeMPEG4DP)
- || (iInputStreamMode == EVedVideoBitstreamModeMPEG4DP_RVLC)
- || (iInputStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP)
- || (iInputStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC)
- )
- {
- // Motion marker in DP mode
- bufSizeBits+=17;
- }
- TInt bufSize = ( bufSizeBits / 8 ) + 1; // always 1-8 stuffing bits
-
- VDASSERT(!iNotCodedFrame, 118);
- iNotCodedFrame = (HBufC8*) HBufC8::NewL(bufSize);
-
- TPtr8 buf(iNotCodedFrame->Des());
- buf.SetLength(bufSize);
- buf.FillZ();
- buf.SetLength(0);
- buf.Copy(vopStartCodeMPEG4, headerSize);
-
- TUint8* ptr = const_cast<TUint8*>(buf.Ptr());
- TInt shift = 8;
- TInt index = headerSize;
- AddBits(ptr, shift, index, 1, 2); // vop_coding_type
- AddBits(ptr, shift, index, 0, 1); // modulo_time_base
- AddBits(ptr, shift, index, 1, 1); // marker_bit
-
- // vop_time_increment is left to zero (skip FillZ bits)
- AddBits(ptr, shift, index, 0, numTiBits);
-
- // marker (1 bit; 1)
- AddBits(ptr, shift, index, 1, 1);
- // vop_coded (1 bit; 1=coded)
- AddBits(ptr, shift, index, 1, 1);
-
- // vop_rounding_type (1 bit) (0)
- AddBits(ptr, shift, index, 0, 1);
-
- // intra_dc_vlc_thr (3 bits) (0 = Intra DC, but don't care)
- AddBits(ptr, shift, index, 0, 3);
-
- // vop_quant (5 bits) (1-31)
- AddBits(ptr, shift, index, 10, 5);
-
- // vop_fcode_forward (3 bits) (1-7, 0 forbidden)
- AddBits(ptr, shift, index, 1, 3);
-
- // Macroblocks
-
- // one COD bit for each MB
- TInt bitsLeft = numMBs;
-
- // set COD bit to 1 for all macroblocks (== not coded)
- while (bitsLeft >= 8)
- {
- AddBits(ptr, shift, index, 0xff, 8);
- bitsLeft -= 8;
- }
-
- TUint8 lsb[8] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
- if (bitsLeft)
- {
- TUint8 val = 0;
- val = lsb[8 - bitsLeft];
- AddBits(ptr, shift, index, val, bitsLeft);
- }
- // If DP mode is used, should add motion marker here: 1 11110000 00000001
- if ( (iInputStreamMode == EVedVideoBitstreamModeMPEG4DP)
- || (iInputStreamMode == EVedVideoBitstreamModeMPEG4DP_RVLC)
- || (iInputStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP)
- || (iInputStreamMode == EVedVideoBitstreamModeMPEG4Resyn_DP_RVLC)
- )
- {
- AddBits(ptr, shift, index, 0x01, 1);
- AddBits(ptr, shift, index, 0xf0, 8);
- AddBits(ptr, shift, index, 0x01, 8);
- }
-
- // insert stuffing in last byte
- TUint8 stuffing[8] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f };
- ptr[bufSize - 1] |= stuffing[shift-1];
-
- buf.SetLength(bufSize);
-
- }
- else
- {
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
-
- VDASSERT(iDataFormat == EDataAVC, 115);
-
- VDASSERT(!iNotCodedFrame, 118);
- iNotCodedFrame = (HBufC8*) HBufC8::NewL(KAVCNotCodedFrameBuffer);
-
- TPtr8 buf( const_cast<TUint8*>(iNotCodedFrame->Des().Ptr()),
- KAVCNotCodedFrameBuffer, KAVCNotCodedFrameBuffer );
-
- TInt len = iAvcEdit->GenerateNotCodedFrame( buf, iModifiedFrameNumber++ );
-
- if (len == 0)
- User::Leave(KErrArgument);
-
- TPtr8 temp(iNotCodedFrame->Des());
- temp.SetLength(len);
-#else
- VDASSERT(0, 190);
-#endif
- }
-
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::ProcessFrameL
-// Processes one input frame
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TBool CVideoProcessor::ProcessFrameL()
- {
-
-
- PRINT((_L("CVideoProcessor::ProcessFrameL() begin")));
-
- VDASSERT(iCurrentFrameLength,1);
-
- TInt frameInRange = 0;
- TInt frameDuration = 0;
- TBool keyFrame = EFalse;
- TTimeIntervalMicroSeconds startCutTime = TTimeIntervalMicroSeconds(0);
- TTimeIntervalMicroSeconds endCutTime = TTimeIntervalMicroSeconds(0);
- TTimeIntervalMicroSeconds frameTime = TTimeIntervalMicroSeconds(0);
-
- TInt trP = iProcessor->GetTrPrevNew();
- TInt trD = iProcessor->GetTrPrevOrig();
-
- // transitions
- iTransitionFrame = 0; // is this a transition frame?
- iTransitionPosition = EPositionNone;
- iTransitionColor = EColorNone;
- iFirstTransitionFrame = 0; // is this the first transition frame in this instance?
- TBool endColorTransitionFrame = EFalse;
-
- TBool decodeCurrentFrame = 0; // do we need to decode frame for transition effect?
-
- // book-keeping
- startCutTime = iProcessor->GetStartCutTime();
- endCutTime = iProcessor->GetEndCutTime();
- iRepeatFrame = EFalse;
-
- if(iInitializing)
- {
-
- // determine if we need to do full transcoding
- iFullTranscoding = DetermineResolutionChange() || DetermineFrameRateChange() ||
- DetermineBitRateChange();
-
- // Do full transcoding for MPEG-4 => H.263. MPEG-4 => MPEG-4 and H.263 => MPEG-4 can be done in compressed domain
- if ( iProcessor->GetCurrentClipVideoType() == EVedVideoTypeMPEG4SimpleProfile &&
- iProcessor->GetOutputVideoType() != EVedVideoTypeMPEG4SimpleProfile )
- iFullTranscoding = ETrue;
-
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
- // Do full transcoding for AVC => H.263/MPEG-4
- if ( iProcessor->GetCurrentClipVideoType() == EVedVideoTypeAVCBaselineProfile &&
- iProcessor->GetOutputVideoType() != EVedVideoTypeAVCBaselineProfile )
- iFullTranscoding = ETrue;
-
- // Do full transcoding for H.263/MPEG-4 => AVC
- if ( iProcessor->GetCurrentClipVideoType() != EVedVideoTypeAVCBaselineProfile &&
- iProcessor->GetOutputVideoType() == EVedVideoTypeAVCBaselineProfile )
- iFullTranscoding = ETrue;
-
- // Do color effects for AVC in spatial domain
- if ( iProcessor->GetOutputVideoType() == EVedVideoTypeAVCBaselineProfile &&
- iProcessor->GetColorEffect() != EVedColorEffectNone )
- iFullTranscoding = ETrue;
-#endif
-
- // determine transition parameters for the clip
- DetermineClipTransitionParameters(iTransitionEffect,iStartOfClipTransition,
- iEndOfClipTransition,iStartTransitionColor,iEndTransitionColor);
-
- if (!iTransCoder)
- {
- // initialize transcoder, normal mode
- CreateAndInitializeTranscoderL(iProcessor->GetCurrentClipVideoType(), CTRTranscoder::EFullTranscoding);
- return EFalse;
- }
-
- if ( iColorTransitionBuffer )
- {
- User::Free( iColorTransitionBuffer );
- iColorTransitionBuffer = 0;
- }
-
- if ( iOrigPreviousYUVBuffer )
- {
- User::Free( iOrigPreviousYUVBuffer );
- iOrigPreviousYUVBuffer = 0;
- }
-
- iFirstFrameInRange = 0;
- iFirstIncludedFrameNumber = -1;
- iTimeStampIndex = 0;
- iTimeStampOffset = 0;
- //iProcessor->iOutputFramesInClip=0;
- iPreviousFrameIncluded = EFalse;
- iNumberOfFrames = iProcessor->GetClipNumberOfFrames();
-
- // calculate number of included frames
- if(iTransitionEffect)
- {
- GetNumberOfTransitionFrames(startCutTime, endCutTime);
- }
- iInitializing = EFalse;
- }
-
- TInt startFrame = iProcessor->GetOutputNumberOfFrames() - iNumberOfFrames;
- TInt absFrameNumber = startFrame + iFrameNumber;
-
- VDASSERT(startCutTime <= endCutTime,2);
-
- // microseconds
- frameTime = TTimeIntervalMicroSeconds(iProcessor->GetVideoTimeInMsFromTicks(
- iProcessor->VideoFrameTimeStamp(absFrameNumber), EFalse) * 1000);
- keyFrame = iProcessor->VideoFrameType(absFrameNumber);
-
- TInt cur = absFrameNumber;
- TInt next = cur+1;
-
- TTimeIntervalMicroSeconds frameDurationInMicroSec(0);
-
- // frameDuration is in ticks, with timescale of the current input clip
- if(next >= iProcessor->GetOutputNumberOfFrames())
- {
- frameDurationInMicroSec =
- (iProcessor->GetVideoTimeInMsFromTicks(iProcessor->GetVideoClipDuration(), EFalse) * TInt64(1000)) - frameTime.Int64();
-
- frameDuration = I64INT(iProcessor->GetVideoClipDuration() - iProcessor->VideoFrameTimeStamp(cur) );
- }
- else
- {
- frameDuration = I64INT( iProcessor->VideoFrameTimeStamp(next) - iProcessor->VideoFrameTimeStamp(cur) );
- frameDurationInMicroSec =
- TTimeIntervalMicroSeconds(iProcessor->GetVideoTimeInMsFromTicks(TInt64(frameDuration), EFalse) * 1000);
- }
-
- TTimeIntervalMicroSeconds frameEndTime =
- TTimeIntervalMicroSeconds( frameTime.Int64() + frameDurationInMicroSec.Int64() );
-
- // endCutTime is in TTimeIntervalMicroSeconds
-
- // check if frame is in range for decoding/editing
- frameInRange = ((frameEndTime <= endCutTime) ? 1 : 0);
- if(frameInRange)
- {
-
- // transition is applied only for frame included in the output movie
- if(frameTime >= startCutTime)
- {
- // find the offset for the first included frame in the clip
- if(!iFirstFrameInRange)
- {
- iFirstFrameInRange = 1;
- iFirstIncludedFrameNumber = iFrameNumber;
- iModifiedFrameNumber = iFrameNumber + 1; // +1 since number is incremented after modifying
- }
- TInt relativeIncludedFrameNumber = iFrameNumber - iFirstIncludedFrameNumber;
-
- if(iTransitionEffect)
- {
- // check if this is a transition frame & set transition parameters
- SetTransitionFrameParams(relativeIncludedFrameNumber, decodeCurrentFrame);
- }
- }
-
- // check if this is an end color transition frame
- if ( iTransitionFrame && iTransitionPosition == EPositionEndOfClip &&
- iEndTransitionColor == EColorTransition )
- {
- endColorTransitionFrame = ETrue;
- iFrameToEncode = EFalse;
- }
-
- // check if we need to include this frame into output movie
- if (frameTime < startCutTime)
- {
- // decode, but do not include in output movie
- // iPreviousFrameIncluded = EFalse;
- iFrameToEncode = EFalse;
- iFrameOperation = EDecodeNoWrite;
- // for decoding frames not writable to output movie, do not decode
- // with any effects, because all information is need at P->I conversion
- }
- else // include in output movie
- {
-
- // check if we need to encode it again as I-frame
- if (iFullTranscoding || (!iPreviousFrameIncluded && !keyFrame) || iTransitionFrame)
- {
- // need to decode as P and encode as I
-
- if (!endColorTransitionFrame)
- iFrameToEncode = ETrue;
-
- iFrameOperation = EDecodeNoWrite;
- // for first decoding of P frame in a clip, do not decode with any effects;
- // instead, apply the effects in the spatial domain after decoding it as P;
- // then feed it to the encoder with the applied special effects
- }
- else
- {
-
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
- // check if we need to encode AVC frames after
- // encoded cut frame or starting transition
- if (iDataFormat == EDataAVC && iEncodeUntilIDR)
- {
- TPtr8 ptr(iDataBuffer, iCurrentFrameLength, iBufferLength);
-
- if (iAvcEdit->IsNALUnitIDR(ptr))
- iEncodeUntilIDR = 0;
- else
- {
- // encode
- iFrameOperation = EDecodeNoWrite;
- if (!endColorTransitionFrame)
- iFrameToEncode = ETrue;
- }
- }
-#endif
-
- if (!iEncodeUntilIDR)
- {
- // just copy the frame data as it is
-
- TInt colorEffect = TColorEffect2TInt(iProcessor->GetColorEffect());
-
- iFrameToEncode = EFalse;
- if(decodeCurrentFrame)
- iFrameOperation = EDecodeAndWrite;
- else
- iFrameOperation = (colorEffect==0/*None*/ ? EWriteNoDecode : EDecodeAndWrite);
- }
- }
- iPreviousFrameIncluded = ETrue;
- }
-
- }
- else
- {
- // no need to include frame in output movie
- iPreviousFrameIncluded = EFalse;
- iFrameToEncode = EFalse;
- iFrameOperation = ENoDecodeNoWrite;
-
- // stop processing
- return ETrue;
- }
-
- TBool modeChanged = GetModeChangeL(); // do we need to change the current mode?
-
- /* added to handle Mp4Specific size problem */
- if(modeChanged && !iFullTranscoding)
- {
- iProcessor->SetClipModeChanged(modeChanged); //if it is not set, it will be default false
- }
-
- if (iFrameOperation == EDecodeAndWrite)
- PRINT((_L("CVideoProcessor::ProcessFrameL() frame operation = EDecodeAndWrite")));
- if (iFrameOperation == EWriteNoDecode)
- PRINT((_L("CVideoProcessor::ProcessFrameL() frame operation = EWriteNoDecode")));
- if (iFrameOperation == EDecodeNoWrite)
- PRINT((_L("CVideoProcessor::ProcessFrameL() frame operation = EDecodeNoWrite")));
- if (iFrameOperation == ENoDecodeNoWrite)
- PRINT((_L("CVideoProcessor::ProcessFrameL() frame operation = ENoDecodeNoWrite")));
-
- PRINT((_L("CVideoProcessor::ProcessFrameL() iFrameToEncode = %d"), iFrameToEncode));
-
- TBool volHeaderIncluded = EFalse;
-
- if( (iFrameOperation == EDecodeAndWrite) || (iFrameOperation == EWriteNoDecode) ||
- ((iFrameOperation == EDecodeNoWrite) && !iFullTranscoding && iFirstFrameFlag) )
- // the last line is to enable processing of the 1st frame also if it would be decoded with transcoder,
- // to enable processing of the MPEG-4 VOL header by vedh263d.
- {
-
- TPtr8 ptr(0,0);
- TBool doCompressedDomainTC = modeChanged || iProcessor->GetColorEffect() != EVedColorEffectNone;
-
- // If we need to do compressed domain bitstream manipulation at some
- // point of the clip, all frames must be decoded by vedh263d to be
- // able to start bitstream modification in the middle of the clip, e.g.
- // after a transition. If we are processing MPEG-4, all frames are
- // manipulated by the decoder for changing timing information
-
- if ( doCompressedDomainTC || (iDataFormat == EDataMPEG4 /*&& !iTransitionFrame*/) )
- {
- // use h263decoder to do bitstream modification
-
- // (if this is an end color transition frame, iFrameOperation is
- // EDecodeNoWrite && iFrameToEncode == 0
-
- TInt frameOp = 1; // EDecodeAndWrite
-
- if ( iFrameOperation == EDecodeNoWrite )
- frameOp = 2;
-
- if ( iFrameOperation == EWriteNoDecode && !modeChanged )
- frameOp = 3; // EWriteNoDecode
-
- TInt frameSize;
-
- if (iDataFormat == EDataMPEG4 && iFirstFrameFlag)
- {
- InsertDecoderSpecificInfoL();
- volHeaderIncluded = ETrue;
- }
-
- // use h263decoder to do compressed domain transcoding
- PRINT((_L("CVideoProcessor::ProcessFrameL() decode using vedh263d")));
- DecodeFrameL(frameOp, modeChanged, frameSize);
- ptr.Set(iOutVideoFrameBuffer, frameSize, frameSize);
- }
- else
- {
- // copy bitstream directly
- ptr.Set(iDataBuffer, iCurrentFrameLength, iCurrentFrameLength);
- }
-
- if (iFrameOperation == EDecodeAndWrite || iFrameOperation == EWriteNoDecode)
- {
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
- if (iDataFormat == EDataAVC && iTransitionEffect &&
- iStartTransitionColor == EColorTransition)
- {
- if (!(iAvcEdit->IsNALUnitIDR(ptr)))
- {
- // modify frame number
- VDASSERT( (iFrameNumber > iFirstIncludedFrameNumber), 182 );
- iAvcEdit->ModifyFrameNumber(ptr, iModifiedFrameNumber++);
- PRINT((_L("CVideoProcessor::ProcessFrameL() modified frame no. => #%d"), iModifiedFrameNumber - 1));
- }
- else
- iModifiedFrameNumber = 1; // this frame is IDR, start numbering from zero
- }
-#endif
- // Write to file
- if ( WriteFrameToFileL(ptr, frameDuration, absFrameNumber) )
- return ETrue;
- }
-
- if (iFrameOperation == EWriteNoDecode ||
- (iFrameOperation == EDecodeAndWrite && !decodeCurrentFrame && doCompressedDomainTC))
- {
- // NOTE: The 2nd condition is for B&W & compr.domain TC
-
- // if we are doing only compressed domain transcoding, theres no need to
- // decode the frame using transcoder
-
- // Throw away the data for this frame:
- VDASSERT(iDataLength >= iCurrentFrameLength,4);
- Mem::Copy(iDataBuffer, iDataBuffer + iCurrentFrameLength,
- iDataLength - iCurrentFrameLength);
- iDataLength = iDataLength - iCurrentFrameLength;
- iCurrentFrameLength = 0;
-
- // update and fetch the new Time Code for MPEG4 ES
- if (iProcessor->GetOutputVideoType() == EVedVideoTypeMPEG4SimpleProfile &&
- frameInRange && (frameTime >= startCutTime) )
-
- {
- iMPEG4Timer->UpdateMPEG4Time(absFrameNumber, iFrameNumber, iProcessor->GetSlowMotionSpeed());
- }
-
- iFrameNumber++;
- return EFalse;
- }
- }
-
- // process using transcoder
- if (iFrameOperation == EDecodeNoWrite || iFrameOperation == EDecodeAndWrite)
- {
- WriteFrameToTranscoderL(absFrameNumber, keyFrame, volHeaderIncluded);
- }
-
- // update and fetch the new Time Code for MPEG4 ES
- if (iProcessor->GetOutputVideoType() == EVedVideoTypeMPEG4SimpleProfile &&
- frameInRange && (frameTime >= startCutTime) )
- {
- iMPEG4Timer->UpdateMPEG4Time(absFrameNumber, iFrameNumber, iProcessor->GetSlowMotionSpeed());
- }
-
- iProcessor->SetTrPrevNew(trP);
- iProcessor->SetTrPrevOrig(trD);
-
- if (!iFirstColorTransitionFrame)
- iFrameNumber++;
-
- PRINT((_L("CVideoProcessor::ProcessFrameL() end")));
-
- return EFalse;
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::WriteFrameToFileL
-// Write frame to file
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TBool CVideoProcessor::WriteFrameToFileL(TPtr8& aBuf, TInt aDurationInTicks, TInt aFrameNumber)
-{
-
- // if there's a frame waiting to be encoded, we must not
- // write this frame now. It will be written after all to-be-encoded
- // frames have been written. New frames must not be processed
- // until the delayed write has been completed
-
- iDelayedWrite = !IsEncodeQueueEmpty();
-
- if (iDelayedWrite)
- {
- PRINT((_L("CVideoProcessor::WriteFrameToFileL() delayed write")));
- // save frame for later writing
- if (iDelayedBuffer)
- delete iDelayedBuffer;
- iDelayedBuffer = 0;
-
- iDelayedBuffer = (HBufC8*) HBufC8::NewL(aBuf.Length());
-
- TPtr8 db(iDelayedBuffer->Des());
- db.Copy(aBuf);
-
- iDelayedTimeStamp = iProcessor->VideoFrameTimeStamp(aFrameNumber) + iTimeStampOffset;
- iDelayedKeyframe = iProcessor->VideoFrameType(aFrameNumber);
- iDelayedFrameNumber = iFrameNumber;
- if ( IsNextFrameBeingEncoded() )
- {
- // start timer to wait for encoding to complete
- if ( !iTimer->IsPending() )
- iTimer->SetTimer( TTimeIntervalMicroSeconds32( iMaxEncodingDelay ) );
- }
- }
- else
- {
- // write now
- TInt error = iProcessor->WriteVideoFrameToFile(aBuf,
- ( iProcessor->VideoFrameTimeStamp(aFrameNumber) + iTimeStampOffset ),
- aDurationInTicks, iProcessor->VideoFrameType(aFrameNumber), EFalse, EFalse, EFalse );
-
- // If movie has reached maximum size then stop processing
- if (error == KErrCompletion)
- {
- iFrameInfoArray.Reset();
- return ETrue;
- }
-
- // save frame number
- iLastWrittenFrameNumber = iFrameNumber;
-
- User::LeaveIfError(error);
- }
-
- return EFalse;
-
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::WriteFrameToTranscoderL
-// Write frame to transcoder
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::WriteFrameToTranscoderL(TInt aFrameNumber, TBool aKeyFrame, TBool aVolHeaderInBuffer)
-{
-
- VDASSERT(iDataFormat != EDataUnknown, 30);
-
- // TODO: new buffertype for H.264
- CCMRMediaBuffer::TBufferType bt =
- (iDataFormat == EDataH263) ? CCMRMediaBuffer::EVideoH263 : CCMRMediaBuffer::EVideoMPEG4;
-
- // insert dec. specific info header to beginning of buffer if it has not been sent
- if (!iDecoderSpecificInfoSent &&
- ( iDataFormat == EDataAVC || (iDataFormat == EDataMPEG4 && !aVolHeaderInBuffer) ) )
- {
- PRINT((_L("CVideoProcessor::WriteFrameToTranscoderL() - insert header"), iTranscoderMode));
- InsertDecoderSpecificInfoL();
- }
-
- // determine transcoder mode for this frame
- TTranscoderMode mode;
-
- if (iFrameToEncode)
- {
- if ( iTransitionFrame || (iProcessor->GetColorEffect() != EVedColorEffectNone) )
- {
- PRINT((_L("CVideoProcessor::WriteFrameToTranscoderL() encode current frame with intermediate modification")));
- mode = EFullWithIM;
- }
- else
- {
- PRINT((_L("CVideoProcessor::WriteFrameToTranscoderL() encode current frame")));
- mode = EFull;
- }
- }
- else
- {
- PRINT((_L("CVideoProcessor::WriteFrameToTranscoderL() only decode current frame")));
- mode = EDecodeOnly;
- }
-
- PRINT((_L("CVideoProcessor::WriteFrameToTranscoderL() iTranscoderMode %d"), iTranscoderMode));
- if (iTranscoderMode != mode)
- {
- if (mode == EDecodeOnly)
- {
- iTransCoder->EnableEncoder(EFalse);
- iTransCoder->EnablePictureSink(ETrue);
- }
- else if (mode == EFull)
- {
- iTransCoder->EnableEncoder(ETrue);
- iTransCoder->EnablePictureSink(EFalse);
- }
- else
- {
- iTransCoder->EnableEncoder(ETrue);
- iTransCoder->EnablePictureSink(ETrue);
- }
- iTranscoderMode = mode;
- }
-
- if (iFrameToEncode)
- {
- // should we encode an I-frame ?
- if( (iTransitionFrame && iFirstTransitionFrame) ||
- (iFrameNumber == iFirstIncludedFrameNumber) ||
- iFirstFrameAfterTransition )
- {
- iTransCoder->SetRandomAccessPoint();
- }
- }
-
- TFrameInformation frameInfo;
- frameInfo.iTranscoderMode = iTranscoderMode;
- frameInfo.iFrameNumber = iFrameNumber;
- frameInfo.iEncodeFrame = iFrameToEncode;
- frameInfo.iKeyFrame = aKeyFrame;
-
- // this timestamp is in ticks for writing the frame
- frameInfo.iTimeStamp = iProcessor->VideoFrameTimeStamp(aFrameNumber) + iTimeStampOffset;
- frameInfo.iTransitionFrame = iTransitionFrame;
- frameInfo.iTransitionPosition = iTransitionPosition;
- frameInfo.iTransitionColor = iTransitionColor;
- frameInfo.iTransitionFrameNumber = iTransitionFrameNumber;
- frameInfo.iModificationApplied = EFalse;
-
- if(iTransitionFrame && iTransitionPosition == EPositionStartOfClip &&
- iStartTransitionColor == EColorTransition)
- {
- TInt duration;
- TInt64 currentTimeStamp = iProcessor->VideoFrameTimeStamp(aFrameNumber);
-
- // get timestamp for 1st frame
- iProcessor->GetNextFrameDuration(duration, frameInfo.iTimeStamp, iTimeStampIndex, iTimeStampOffset);
- iTimeStampIndex++;
-
- if (iFirstTransitionFrame)
- iCutInTimeStamp = currentTimeStamp;
-
- frameInfo.iTimeStamp += iCutInTimeStamp;
-
- // the duration parameter is not used actually, so no need to figure it out
- iProcessor->AppendNextFrameDuration(duration, currentTimeStamp - iCutInTimeStamp);
-
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
- if (iDataFormat == EDataAVC)
- {
-
- TPtr8 ptr(iDataBuffer, iCurrentFrameLength, iBufferLength);
- if (!iDecoderSpecificInfoSent)
- {
- ptr.Set(iDataBuffer + iProcessor->GetDecoderSpecificInfoSize(),
- iCurrentFrameLength - iProcessor->GetDecoderSpecificInfoSize(), iBufferLength);
- }
-
- // Store PPS id
- iAvcEdit->StoreCurrentPPSId( ptr );
-
- if (iNotCodedFrame)
- delete iNotCodedFrame;
- iNotCodedFrame = 0;
- }
-#endif
-
- frameInfo.iRepeatFrame = EFalse;
- iFirstColorTransitionFrame = ETrue; // to indicate that iDataBuffer must not be flushed
- // in MtroReturnCodedBuffer
- }
-
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
- if ( iDataFormat == EDataAVC && iTransitionEffect && iStartTransitionColor == EColorTransition &&
- (iFrameNumber > iFirstIncludedFrameNumber) && iFrameOperation != EDecodeAndWrite)
- {
- TPtr8 ptr(iDataBuffer, iCurrentFrameLength, iBufferLength);
-
- if (!iDecoderSpecificInfoSent)
- {
- ptr.Set(iDataBuffer + iProcessor->GetDecoderSpecificInfoSize(),
- iCurrentFrameLength - iProcessor->GetDecoderSpecificInfoSize(), iBufferLength);
- }
-
- if (!(iAvcEdit->IsNALUnitIDR(ptr)))
- {
- // modify frame number
- iAvcEdit->ModifyFrameNumber(ptr, iModifiedFrameNumber++);
- PRINT((_L("CVideoProcessor::WriteFrameToTranscoderL() modified frame no. => #%d"), iModifiedFrameNumber - 1));
- }
- else
- iModifiedFrameNumber = 1; // this frame is IDR, start numbering from zero
- }
-#endif
-
- // get timestamp in microseconds
- TTimeIntervalMicroSeconds ts =
- (iProcessor->GetVideoTimeInMsFromTicks(frameInfo.iTimeStamp, EFalse)) * 1000;
-
- if (ts <= iPreviousTimeStamp)
- {
- // adjust timestamp so that its bigger than ts of previous frame
- TReal frameRate = iProcessor->GetVideoClipFrameRate();
- VDASSERT(frameRate > 0.0, 106);
- TInt64 durationMs = TInt64( ( 1000.0 / frameRate ) + 0.5 );
- durationMs /= 2; // add half the duration of one frame
-
- ts = TTimeIntervalMicroSeconds( iPreviousTimeStamp.Int64() + durationMs*1000 );
-
- frameInfo.iTimeStamp = iProcessor->GetVideoTimeInTicksFromMs( ts.Int64()/1000, EFalse );
-
- ts = iProcessor->GetVideoTimeInMsFromTicks(frameInfo.iTimeStamp, EFalse) * 1000;
-
- PRINT((_L("CVideoProcessor::WriteFrameToTranscoderL() - adjusted timestamp, prev = %d, new = %d"),
- I64INT( iPreviousTimeStamp.Int64() ) / 1000, I64INT( ts.Int64() ) / 1000));
-
- }
-
- iFrameInfoArray.Append(frameInfo);
-
- iPreviousTimeStamp = ts;
-
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
- if (iDataFormat == EDataAVC)
- {
- TPtr8 ptr(iDataBuffer, iCurrentFrameLength, iBufferLength);
- // This has to be updated when cutting from beginning ??
- iAvcEdit->ProcessAVCBitStreamL((TDes8&)(ptr), (TInt&)(iCurrentFrameLength),
- iProcessor->GetDecoderSpecificInfoSize(), !iDecoderSpecificInfoSent );
- iDataLength = iCurrentFrameLength;
-
- }
-#endif
-
- iMediaBuffer->Set( TPtrC8(iDataBuffer, iBufferLength),
- bt,
- iCurrentFrameLength,
- aKeyFrame,
- ts);
-
- iDecodePending = ETrue;
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
-
-
- PRINT((_L("CVideoProcessor::WriteFrameToTranscoderL() - transcoder mode is %d"), iTranscoderMode));
-
- PRINT((_L("CVideoProcessor::WriteFrameToTranscoderL() - WriteCodedBuffer, frame #%d, timestamp %d ms"),
- iFrameNumber, I64INT( ts.Int64() ) / 1000 ));
-
- PRINT((_L("CVideoProcessor::WriteFrameToTranscoderL() - %d items in queue"), iFrameInfoArray.Count()));
-
- iTransCoder->WriteCodedBufferL(iMediaBuffer);
-
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::InsertDecoderSpecificInfoL
-// Insert AVC dec. config record in the beginning of slice NAL('s)
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::InsertDecoderSpecificInfoL()
-{
-
- if (iDataFormat == EDataMPEG4)
- {
- if ( (iDataLength + iDecoderSpecificInfo->Length()) > iBufferLength )
- {
- // extend buffer size
- TUint newSize = iDataLength + iDecoderSpecificInfo->Length();
- iDataBuffer = (TUint8*) User::ReAllocL(iDataBuffer, newSize);
- iBufferLength = newSize;
- }
- Mem::Copy(iDataBuffer+iDecoderSpecificInfo->Length(), iDataBuffer, iCurrentFrameLength);
- Mem::Copy(iDataBuffer, iDecoderSpecificInfo->Des().Ptr(), iDecoderSpecificInfo->Length());
- iCurrentFrameLength += iDecoderSpecificInfo->Length();
- iDataLength += iDecoderSpecificInfo->Length();
-
- return;
- }
-
- VDASSERT( iDataFormat == EDataAVC, 182 );
-
- // get number of slice NAL's in buffer
- TInt frameLen = 0;
- TInt numSliceNalUnits = 0;
- TUint8* frameLenPtr = iDataBuffer;
-
- while (frameLen < iCurrentFrameLength)
- {
- TInt nalLen = 0;
-
- nalLen = (frameLenPtr[0] << 24) + (frameLenPtr[1] << 16) +
- (frameLenPtr[2] << 8) + frameLenPtr[3] + 4; // +4 for length field
-
- frameLenPtr += nalLen;
- frameLen += nalLen;
- numSliceNalUnits++;
- }
-
- // get no. of SPS & PPS
-
- TUint8* ptr = const_cast<TUint8*>(iDecoderSpecificInfo->Des().Ptr());
-
- TInt index = 4; // Skip version and length information
- ptr[index] |= 0x03; // set no. bytes used for length to 4
-
- index++;
- TInt numSPS = ptr[index] & 0x1f;
-
- index++;
-
- // Loop all SPS units
- for (TInt i = 0; i < numSPS; ++i)
- {
- TInt SPSSize = (ptr[index] << 8) + ptr[index + 1];
- index += 2;
- index += SPSSize;
- }
- TInt numPPS = ptr[index];
-
- // Align at 32-bit boundrary
- TInt payLoadLen = iCurrentFrameLength + iDecoderSpecificInfo->Length();
- TInt alignmentBytes = (payLoadLen % 4 != 0) * ( 4 - (payLoadLen % 4) );
-
- // get needed buffer length
- TInt minBufLen = iCurrentFrameLength + iDecoderSpecificInfo->Length() + alignmentBytes +
- ( (numSliceNalUnits + numSPS + numPPS) * 8 ) + 4;
-
- // ReAllocate buffer
- if (iBufferLength < minBufLen)
- {
- iDataBuffer = (TUint8*) User::ReAllocL(iDataBuffer, minBufLen);
- iBufferLength = minBufLen;
-
- PRINT((_L("CVideoProcessor::XXX() reallocated databuffer, new length = %d"),iBufferLength));
- }
-
- // move slice NAL's the amount of DCR length
- Mem:: Copy(iDataBuffer + iDecoderSpecificInfo->Length(), iDataBuffer, iCurrentFrameLength);
-
- // copy SPS/PPS data in the beginning
- Mem:: Copy(iDataBuffer, iDecoderSpecificInfo->Des().Ptr(), iDecoderSpecificInfo->Length());
-
- iCurrentFrameLength += iDecoderSpecificInfo->Length();
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::GetModeChangeL
-// Determine need to compr. domain transcoding
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TBool CVideoProcessor::GetModeChangeL()
-{
-
- TInt videoClipNumber = iProcessor->GetVideoClipNumber();
-
- // iProcessor->GetModeTranslationMPEG4() returns the overall decision for inserted MPEG4 clips
-
- TVedTranscodeFactor tFact = iProcessor->GetVideoClipTranscodeFactor(videoClipNumber);
-
- TBool fModeChanged = EFalse;
-
- if (iProcessor->GetOutputVideoType() == EVedVideoTypeMPEG4SimpleProfile) //MPEG4
- {
-
- switch (tFact.iStreamType)
- {
- case EVedVideoBitstreamModeUnknown:
- case EVedVideoBitstreamModeMPEG4Regular:
- case EVedVideoBitstreamModeMPEG4Resyn:
- fModeChanged = EFalse; // already the target mode
- break;
- case EVedVideoBitstreamModeH263:
- fModeChanged = ETrue;
- break;
- case EVedVideoBitstreamModeMPEG4ShortHeader:
- default: // other MPEG4 modes
- // if all the MPEG4 (note: it is also considered as MPEG4 type) have the same mode
- // no need to do the mode translation
- fModeChanged = iProcessor->GetModeTranslationMpeg4() ? ETrue: EFalse;
- break;
- }
-
- }
- else if ( (iProcessor->GetOutputVideoType() == EVedVideoTypeH263Profile0Level10) ||
- (iProcessor->GetOutputVideoType() == EVedVideoTypeH263Profile0Level45) )
- {
-
- if (tFact.iStreamType == EVedVideoBitstreamModeH263 ||
- tFact.iStreamType == EVedVideoBitstreamModeMPEG4ShortHeader||
- tFact.iStreamType ==EVedVideoBitstreamModeUnknown)
- {
- fModeChanged = EFalse;
- }
- else
- {
- fModeChanged = ETrue;
- }
- }
-
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
- else if (iProcessor->GetOutputVideoType() == EVedVideoTypeAVCBaselineProfile)
- fModeChanged = EFalse;
-#endif
-
- else // EVedVideoTypeNoVideo
- {
- User::Leave(KErrNotSupported);
- }
-
- return fModeChanged;
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::DecodeFrameL
-// Decode frame in iDataBuffer using vedh263d
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::DecodeFrameL(TInt aOperation, TBool aModeChanged, TInt& aFrameSizeInBytes)
-{
-
- VDASSERT(iDataFormat == EDataH263 || iDataFormat == EDataMPEG4, 136);
-
- // go into the decoder
- TVedColorEffect vedEffect = iProcessor->GetColorEffect();
- CVedH263Dec::TColorEffect effect = (vedEffect == EVedColorEffectNone) ?
- CVedH263Dec::EColorEffectNone : ((vedEffect == EVedColorEffectBlackAndWhite) ? CVedH263Dec::EColorEffectBlackAndWhite : CVedH263Dec::EColorEffectToning);
-
- vdeDecodeParamters_t decodeParams;
-
- // Assign the ColorTone value of the ColorTone
- // U,V value for the color toning
- TInt colorToneU;
- TInt colorToneV;
- iProcessor->GetColorTone((TInt&)colorToneU, (TInt&)colorToneV);
-
- decodeParams.aColorToneU = colorToneU;
- decodeParams.aColorToneV = colorToneV;
- decodeParams.aColorEffect = effect;
- decodeParams.aFrameOperation = aOperation;
- decodeParams.aGetDecodedFrame = EFalse; //getDecodedFrame; // no need to get YUV
- decodeParams.aSMSpeed = iProcessor->GetSlowMotionSpeed();
-
- TInt trD = iProcessor->GetTrPrevOrig();
- TInt trP = iProcessor->GetTrPrevNew();
-
- decodeParams.aTrD = &trD;
- decodeParams.aTrP = &trP;
- decodeParams.aVideoClipNumber = iProcessor->GetVideoClipNumber();
-
- TVedTranscodeFactor tFact = iProcessor->GetVideoClipTranscodeFactor(decodeParams.aVideoClipNumber);
-
- decodeParams.streamMode = tFact.iStreamType;
- decodeParams.iTimeIncrementResolution = tFact.iTRes;
- decodeParams.aGetVideoMode = EFalse;
- decodeParams.aOutputVideoFormat = iProcessor->GetOutputVideoType();
-
- decodeParams.fModeChanged = aModeChanged;
- decodeParams.fHaveDifferentModes = iProcessor->GetModeTranslationMpeg4() ? ETrue: EFalse;
- /* Color Toning */
- decodeParams.aFirstFrameQp = iFirstFrameQp;
-
- // : Optimisation - If the frame is to be encoded, there is no need
- // to process it using vedh263d in all cases, for example when
- // doing end transition. In start transition case it has to be done
- // so that compressed domain transcoding can continue after transition
-
- // before decoding, set the time infomation in the decoder parameters
- decodeParams.aMPEG4TimeStamp = iMPEG4Timer->GetMPEG4TimeStampPtr();
- decodeParams.aMPEG4TargetTimeResolution = iMPEG4Timer->GetMPEG4TimeResolutionPtr();
-
- decodeParams.vosHeaderSize = 0;
-
- // +3 includes the next PSC or EOS in the bit buffer
- TPtrC8 inputPtr(iDataBuffer, iCurrentFrameLength + (iDataFormat==EDataH263 ? KH263StartCodeLength : KMPEG4StartCodeLength));
-
- // check output buffer size & reallocate if its too small
- if ( TReal(iOutVideoFrameBufferLength) < TReal(iCurrentFrameLength) * 1.5 )
- {
- TInt newLen = TInt( TReal(iCurrentFrameLength) * 1.5 );
-
- iOutVideoFrameBuffer = (TUint8*) User::ReAllocL(iOutVideoFrameBuffer, newLen);
- iOutVideoFrameBufferLength = newLen;
-
- PRINT((_L("CVideoProcessor::DecodeFrameL() reallocated output buffer, new size = %d"),
- iOutVideoFrameBufferLength));
- }
-
- TPtr8 outputPtr(iOutVideoFrameBuffer, 0, iOutVideoFrameBufferLength);
-
- TInt frameSize = 0;
- TBool wasFirstFrame = iFirstFrameFlag; // need to save the value since it may be changed inside
- iDecoder->DecodeFrameL(inputPtr, outputPtr, iFirstFrameFlag, frameSize, &decodeParams);
-
- if (frameSize > (TInt)iCurrentFrameLength)
- {
- // decoder used more data than was in the buffer => corrupted bitstream
- PRINT((_L("CVideoProcessor::DecodeFrameL() decoder used more data than was in the buffer => corrupted bitstream")));
- User::Leave( KErrCorrupt );
- }
-
- aFrameSizeInBytes = outputPtr.Length();
-
- /* record first frame QP */
- if ((iFrameNumber==0) && wasFirstFrame)
- {
- iFirstFrameQp = decodeParams.aFirstFrameQp;
-
- if (iProcessor->GetOutputVideoType() == EVedVideoTypeMPEG4SimpleProfile)
- {
- PRINT((_L("CVideoProcessor::DecodeFrameL() save VOS header, size %d"), decodeParams.vosHeaderSize));
- // sync the vol headers
- if ( decodeParams.vosHeaderSize > iOutputVolHeader->Des().MaxLength() )
- {
- delete iOutputVolHeader;
- iOutputVolHeader = NULL;
- iOutputVolHeader = HBufC8::NewL(decodeParams.vosHeaderSize);
- }
- iOutputVolHeader->Des().Copy( outputPtr.Ptr(), decodeParams.vosHeaderSize );
- }
- }
-
- PRINT((_L("CVideoProcessor::DecodeFrameL() out")));
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::CreateAndInitializeTranscoderL
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::CreateAndInitializeTranscoderL(TVedVideoType aInputType, CTRTranscoder::TTROperationalMode aMode)
-{
-
- PRINT((_L("CVideoProcessor::CreateAndInitializeTranscoderL() begin")));
-
- VDASSERT(iTransCoder == 0, 27);
-
- iTransCoder = CTRTranscoder::NewL(*this);
-
- TBufC8<256> inputMime;
-
-// TInt volLength = 0;
- TInt outputBufferSize = 0;
- iInputMPEG4ProfileLevelId = 0;
-
- if (aInputType == EVedVideoTypeMPEG4SimpleProfile)
- {
- // Get the VOL header from the frame data
- CVedVolReader* reader = CVedVolReader::NewL();
- CleanupStack::PushL(reader);
- // Get pointer to the frame data
- TPtrC8 inputPtr(iDecoderSpecificInfo->Des());
- reader->ParseVolHeaderL((TDesC8&) inputPtr);
-
- iInputMPEG4ProfileLevelId = reader->ProfileLevelId();
-
- iInputTimeIncrementResolution = reader->TimeIncrementResolution();
-
- iInputStreamMode = reader->BitstreamMode();
-
- switch (iInputMPEG4ProfileLevelId)
- {
- case 8:
- inputMime = _L8("video/mp4v-es; profile-level-id=8");
- outputBufferSize = KMaxCodedPictureSizeMPEG4QCIF / 2;
- break;
-
- case 9:
- inputMime = _L8("video/mp4v-es; profile-level-id=9");
- outputBufferSize = KMaxCodedPictureSizeMPEG4L0BQCIF / 2;
- break;
-
- case 1:
- inputMime = _L8("video/mp4v-es; profile-level-id=1");
- outputBufferSize = KMaxCodedPictureSizeMPEG4QCIF / 2;
- break;
-
- case 2:
- inputMime = _L8("video/mp4v-es; profile-level-id=2");
- outputBufferSize = KMaxCodedPictureSizeMPEG4CIF / 2;
- break;
-
- case 3:
- inputMime = _L8("video/mp4v-es; profile-level-id=3");
- outputBufferSize = KMaxCodedPictureSizeMPEG4CIF / 2;
- break;
-
- case 4:
- inputMime = _L8("video/mp4v-es; profile-level-id=4");
- outputBufferSize = KMaxCodedPictureSizeVGA / 2;
- break;
-
- default:
- inputMime = _L8("video/mp4v-es; profile-level-id=8");
- outputBufferSize = KMaxCodedPictureSizeMPEG4QCIF / 2;
- break;
- }
-
-// volLength = reader->HeaderSize();
- CleanupStack::PopAndDestroy(reader);
- }
-
- else if (aInputType == EVedVideoTypeH263Profile0Level10)
- {
- inputMime = _L8("video/H263-2000; profile=0; level=10");
- outputBufferSize = KMaxCodedPictureSizeQCIF / 2;
- }
-
- else if (aInputType == EVedVideoTypeH263Profile0Level45)
- {
- inputMime = _L8("video/H263-2000; profile=0; level=45");
- outputBufferSize = KMaxCodedPictureSizeQCIF / 2;
- }
-
- else if (aInputType == EVedVideoTypeAVCBaselineProfile)
- {
- // get input avc level
- VDASSERT( iAvcEdit != 0, 181 );
- VDASSERT( iDecoderSpecificInfo, 181 );
-
- TPtr8 info = iDecoderSpecificInfo->Des();
- User::LeaveIfError( iAvcEdit->GetLevel(info, iInputAVCLevel) );
-
- switch (iInputAVCLevel)
- {
- case 10:
- inputMime = _L8("video/H264; profile-level-id=42800A");
- outputBufferSize = KMaxCodedPictureSizeAVCLevel1 / 2;
- break;
-
- case 101:
- inputMime = _L8("video/H264; profile-level-id=42900B");
- outputBufferSize = KMaxCodedPictureSizeAVCLevel1B / 2;
- break;
-
- case 11:
- inputMime = _L8("video/H264; profile-level-id=42800B");
- outputBufferSize = KMaxCodedPictureSizeAVCLevel1_1 / 2;
- break;
-
- case 12:
- inputMime = _L8("video/H264; profile-level-id=42800C");
- outputBufferSize = KMaxCodedPictureSizeAVCLevel1_2 / 2;
- break;
-
- // NOTE: Levels 1.3 and 2 are enabled for testing purposes,
- // to be removed
- case 13:
- inputMime = _L8("video/H264; profile-level-id=42800D");
- outputBufferSize = KMaxCodedPictureSizeAVCLevel1_3 / 2;
- break;
-
- case 20:
- inputMime = _L8("video/H264; profile-level-id=428014");
- outputBufferSize = KMaxCodedPictureSizeAVCLevel2 / 2;
- break;
-
- //WVGA task
- case 21:
- inputMime = _L8("video/H264; profile-level-id=428015");
- outputBufferSize = KMaxCodedPictureSizeAVCLevel2_1 / 2;
- break;
-
- case 22:
- inputMime = _L8("video/H264; profile-level-id=428016");
- outputBufferSize = KMaxCodedPictureSizeAVCLevel2_2 / 2;
- break;
-
- case 30:
- inputMime = _L8("video/H264; profile-level-id=42801E");
- outputBufferSize = KMaxCodedPictureSizeAVCLevel3 / 2;
- break;
-
- case 31:
- inputMime = _L8("video/H264; profile-level-id=42801F");
- outputBufferSize = KMaxCodedPictureSizeAVCLevel3_1 / 2;
- break;
-
- default:
- User::Leave(KErrNotSupported);
- break;
- }
- }
-
- else
- User::Leave(KErrNotSupported);
-
- if ( !(iTransCoder->SupportsInputVideoFormat(inputMime) ) )
- {
- User::Leave(KErrNotSupported);
- }
-
-
- // default framerate is 15 fps
- TReal frameRate = 15.0;
-
- iOutputBitRate = 64000;
-
- if ( aMode == CTRTranscoder::EFullTranscoding )
- {
- // get output mime type
- SetOutputVideoCodecL(iProcessor->GetOutputVideoMimeType());
-
- if ( !(iTransCoder->SupportsOutputVideoFormat(iOutputMimeType) ) )
- {
- User::Leave(KErrNotSupported);
- }
-
- // check output resolution
- TSize outputResolution = iProcessor->GetMovieResolution();
-
- if ( (outputResolution.iWidth > iMaxOutputResolution.iWidth) || (outputResolution.iHeight > iMaxOutputResolution.iHeight))
- {
- if ( iArbitrarySizeAllowed ) // This is for future-proofness. Currently the checking of standard sizes below overrules this one
- {
- if ( outputResolution.iWidth * outputResolution.iHeight > iMaxOutputResolution.iWidth*iMaxOutputResolution.iHeight )
- {
- PRINT((_L("CVideoProcessor::CreateAndInitializeTranscoderL() too high resolution requested")));
- User::Leave( KErrNotSupported );
- }
- }
- else
- {
- PRINT((_L("CVideoProcessor::CreateAndInitializeTranscoderL() incompatible or too high resolution requested")));
- User::Leave( KErrNotSupported );
- }
- }
-
- // check size. For now only standard sizes are allowed
- if ( (outputResolution != KVedResolutionSubQCIF) &&
- (outputResolution != KVedResolutionQCIF) &&
- (outputResolution != KVedResolutionCIF) &&
- (outputResolution != KVedResolutionQVGA) &&
- (outputResolution != KVedResolutionVGA16By9) &&
- (outputResolution != KVedResolutionVGA) &&
- //WVGA task
- (outputResolution != KVedResolutionWVGA) )
- {
- User::Leave( KErrArgument );
- }
-
- // check output frame rate
- TReal movieFrameRate = iProcessor->GetMovieFrameRate();
-
- if ( movieFrameRate > 0.0 )
- {
- if ( movieFrameRate <= iMaxOutputFrameRate )
- {
- frameRate = TReal32(movieFrameRate);
- }
- else
- {
- frameRate = iMaxOutputFrameRate;
- }
- }
-
- // check output bitrate
- TInt movieBitRate = iProcessor->GetMovieVideoBitrate();
- TInt standardBitRate = iProcessor->GetMovieStandardVideoBitrate();
-
- if ( movieBitRate > 0 )
- {
- if ( movieBitRate <= iMaxOutputBitRate )
- {
- iOutputBitRate = movieBitRate;
- }
- else
- {
- iOutputBitRate = iMaxOutputBitRate;
- }
- }
- else if ( standardBitRate > 0 )
- {
- if ( standardBitRate <= iMaxOutputBitRate )
- {
- iOutputBitRate = standardBitRate;
- }
- else
- {
- iOutputBitRate = iMaxOutputBitRate;
- }
- }
- }
- else
- {
- iOutputMimeType = KNullDesC8;
- }
-
- TTRVideoFormat videoInputFormat;
- TTRVideoFormat videoOutputFormat;
-
- if (!iThumbnailMode)
- {
- videoInputFormat.iSize = iProcessor->GetVideoClipResolution();
- videoOutputFormat.iSize = iProcessor->GetMovieResolution();
- }
- else
- {
- videoInputFormat.iSize = videoOutputFormat.iSize = TSize(iVideoWidth, iVideoHeight);
- }
-
- videoInputFormat.iDataType = CTRTranscoder::ETRDuCodedPicture;
-
- if (aMode == CTRTranscoder::EFullTranscoding)
- videoOutputFormat.iDataType = CTRTranscoder::ETRDuCodedPicture;
- else
- videoOutputFormat.iDataType = CTRTranscoder::ETRYuvRawData420;
-
-
- iTransCoder->OpenL( this,
- aMode,
- inputMime,
- iOutputMimeType,
- videoInputFormat,
- videoOutputFormat,
- EFalse );
-
-
- iTransCoder->SetVideoBitRateL(iOutputBitRate);
-
- if (!iThumbnailMode)
- {
- // check framerate: target framerate cannot be larger than source framerate
- TReal inputFR = iProcessor->GetVideoClipFrameRate();
- if ( inputFR <= 15.0 )
- {
- inputFR = 15.0;
- }
- else
- {
- inputFR = 30.0;
- }
- if (frameRate > inputFR)
- frameRate = inputFR;
- }
-
- iTransCoder->SetFrameRateL(frameRate);
- iTransCoder->SetChannelBitErrorRateL(0.0);
-
- // dummy
- TTRVideoCodingOptions codingOptions;
- codingOptions.iSyncIntervalInPicture = iProcessor->GetSyncIntervalInPicture();
- codingOptions.iMinRandomAccessPeriodInSeconds = (TInt) (1.0 / iProcessor->GetRandomAccessRate());
- codingOptions.iDataPartitioning = EFalse;
- codingOptions.iReversibleVLC = EFalse;
- codingOptions.iHeaderExtension = 0;
-
- iTransCoder->SetVideoCodingOptionsL(codingOptions);
-
- TSize targetSize;
- if (!iThumbnailMode)
- targetSize = iProcessor->GetMovieResolution();
- else
- targetSize = TSize(iVideoWidth, iVideoHeight);
-
- iTransCoder->SetVideoPictureSinkOptionsL(targetSize, this);
-
- iTransCoder->EnableEncoder(EFalse);
- iTransCoder->EnablePictureSink(ETrue);
- iTranscoderMode = EDecodeOnly;
-
- // set init. data
- TPtrC8 initData;
- if (aInputType == EVedVideoTypeMPEG4SimpleProfile ||
- aInputType == EVedVideoTypeAVCBaselineProfile)
- {
- initData.Set(iDecoderSpecificInfo->Des());
- }
- else
- initData.Set(iDataBuffer, iCurrentFrameLength);
-
- iDecoderSpecificInfoSent = EFalse;
-
- iTransCoder->SetDecoderInitDataL( initData );
-
- if (!iThumbnailMode)
- {
- // allocate output bitstream buffer for processing with vedh263d
- VDASSERT( outputBufferSize != 0, 52 );
- iOutVideoFrameBuffer = (TUint8*) User::AllocL(outputBufferSize);
- iOutVideoFrameBufferLength = outputBufferSize;
- }
-
- iTranscoderInitPending = ETrue;
-
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
-
-
- iTransCoder->InitializeL();
-
- // Get processing time estimate from transcoder, divide it by the framerate to get processing time per frame
- // and then multiply it by 2 to get some safety margin and by unit conversion factor 1000000.
- // The delay is used to determine if a frame was skipped, hence there should be some margin.
-#ifdef __WINSCW__
- iMaxEncodingDelay = 5000000; // emulator can be really slow, use 5 seconds timeout
-#else
- iMaxEncodingDelay = (TUint)(2*1000000*iTransCoder->EstimateTranscodeTimeFactorL(videoInputFormat,videoOutputFormat)/frameRate);
-#endif
-
- iMaxItemsInProcessingQueue = iTransCoder->GetMaxFramesInProcessing();
-
- PRINT((_L("CVideoProcessor::CreateAndInitializeTranscoderL() end")));
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::MtroInitializeComplete
-// Called by transcoder to indicate init. completion
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::MtroInitializeComplete(TInt aError)
-{
-
- TInt error = aError;
- TInt outputTimeIncrementResolution = KDefaultTimeIncrementResolution;
-
- PRINT((_L("CVideoProcessor::MtroInitializeComplete() error = %d"), aError));
-
- if ( !iThumbnailMode && (aError == KErrNone) &&
- ( (iProcessor->GetOutputVideoType() == EVedVideoTypeMPEG4SimpleProfile)
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
- || (iProcessor->GetOutputVideoType() == EVedVideoTypeAVCBaselineProfile)
-#endif
- ) )
- {
- PRINT((_L("CVideoProcessor::MtroInitializeComplete() calling GetCodingStandardSpecificInitOutputLC")));
-
- // get & save vol header from encoder
- TRAP(error,
- {
- iOutputVolHeader = iTransCoder->GetCodingStandardSpecificInitOutputLC();
- CleanupStack::Pop();
- });
-
- iOutputVolHeaderWritten = EFalse;
-
- if ( error == KErrNone )
- {
-
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
- if (iProcessor->GetOutputVideoType() == EVedVideoTypeAVCBaselineProfile)
- {
- // Check if we need to use encoder
- // : Are there any other cases where encoder is used _
- if ( iFullTranscoding || iTransitionEffect ||
- iProcessor->GetStartCutTime() != TTimeIntervalMicroSeconds(0) )
- {
- HBufC8* outputAVCHeader = 0;
- // is the max. size of AVCDecoderConfigurationRecord known here ??
- TRAP(error, outputAVCHeader = (HBufC8*) HBufC8::NewL(16384));
-
- if (error == KErrNone)
- {
- TPtr8 ptr = outputAVCHeader->Des();
-
- // parse header & convert it to AVCDecoderConfigurationRecord -format
- TRAP(error, iAvcEdit->ConvertAVCHeaderL(*iOutputVolHeader, ptr));
-
- if (error == KErrNone)
- {
- TRAP(error, iAvcEdit->SaveAVCDecoderConfigurationRecordL(ptr, ETrue));
- }
- }
- if (outputAVCHeader)
- delete outputAVCHeader;
- }
-
- iEncodeUntilIDR = 0;
- if ( iStartOfClipTransition != 0 ||
- iProcessor->GetStartCutTime() != TTimeIntervalMicroSeconds(0) )
- {
- // we need to use encoder at the beginning, now determine
- // if we have to encode frames after cut / transition until
- // input frame is IDR
- iEncodeUntilIDR = iAvcEdit->EncodeUntilIDR();
- }
- }
- else
-#endif
- {
-
- VDASSERT(iOutputVolHeader, 49);
-
- // get time increment resolution using vol reader
- CVedVolReader* reader = NULL;
- TRAP( error, reader = CVedVolReader::NewL() );
-
- if ( error == KErrNone )
- {
- TRAP( error, reader->ParseVolHeaderL( (TDesC8&) *iOutputVolHeader ) );
- if (error == KErrNone)
- {
- outputTimeIncrementResolution = reader->TimeIncrementResolution();
- }
- delete reader;
- }
- }
-
- }
- }
-
- if (error == KErrNone)
- {
- // create MPEG-4 timing instance
- TRAP(error, iMPEG4Timer = CMPEG4Timer::NewL(iProcessor, outputTimeIncrementResolution));
- }
-
- // enable pausing
- if ( ((iFullTranscoding)
- || (iProcessor->GetStartCutTime() > 0))
- && (iStartOfClipTransition == 0)
- && (iEndOfClipTransition == 0) )
- {
- // safe to enable pausing during transcoding:
- // only when doing full transcoding or cutting from the beginning, but not if transitions
- // rules out e.g. thumbnails, and codec-free cases
- iTransCoder->EnablePausing(ETrue);
- }
-
- VDASSERT(iTranscoderInitPending, 28);
- // complete request
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, error);
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::MtroFatalError
-// Called by transcoder to indicate a fatal error
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::MtroFatalError(TInt aError)
-{
- PRINT((_L("CVideoProcessor::MtroFatalError() %d"), aError));
-
- if (iFullTranscoding || iThumbnailMode || iTransitionEffect || (iProcessor->GetStartCutTime() > 0))
- {
- // ok, this is fatal, continue the method
- PRINT((_L("CVideoProcessor::MtroFatalError() transcoder is in use, this is fatal")));
- }
- else
- {
- // transcoder not in use, ignore
- PRINT((_L("CVideoProcessor::MtroFatalError() transcoder not in use, ignore")));
- return;
- }
-
- // stop decoding
- Stop();
-
- if (!iThumbnailMode)
- iMonitor->Error(aError);
- else
- iProcessor->NotifyThumbnailReady(aError);
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::MtroSuspend
-// Suspends processing
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::MtroSuspend()
-{
-
- PRINT((_L("CVideoProcessor::MtroSuspend()")));
-
- if (iProcessingComplete || (!iProcessor->NeedTranscoderAnyMore()))
- {
- PRINT((_L("CVideoProcessor::MtroSuspend(), this clip done or no video at all to process any more, ignore")));
- return;
- }
-
- Cancel();
- iDecoding = EFalse;
- iDecodePending = EFalse;
- iDecodingSuspended = EFalse;
-
- if (iTimer)
- iTimer->CancelTimer();
-
- iProcessor->SuspendProcessing();
-
- // flush input queue
- if (iBlock)
- iQueue->ReturnBlock(iBlock);
- iBlock = iQueue->ReadBlock();
- while (iBlock)
- {
- iQueue->ReturnBlock(iBlock);
- iBlock = iQueue->ReadBlock();
- }
- iBlockPos = 0;
-
- iTranscoderMode = EUndefined; // force to reset the mode when writing the next picture
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::MtroResume
-// Re-starts processing after pause
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::MtroResume()
-{
- PRINT((_L("CVideoProcessor::MtroResume()")));
-
- if (iProcessingComplete)
- {
- PRINT((_L("CVideoProcessor::MtroResume(), processing of this clip completed, continue")));
- // fake RunL with this flag
- iDecoding = ETrue;
- if (!IsActive())
- {
- // Make us active
- PRINT((_L("CVideoProcessor::MtroResume() set active")));
- SetActive();
- iStatus = KRequestPending;
- }
- }
-
- if (!iProcessor->NeedTranscoderAnyMore())
- {
- PRINT((_L("CVideoProcessor::MtroResume(), no video to process any more, ignore")));
- return;
- }
-
- // flush frame info array and cancel timer
- if (iTimer)
- iTimer->CancelTimer();
- iFrameInfoArray.Reset();
-
- Start();
-
- TInt error = iProcessor->ResumeProcessing(iFrameNumber, iLastWrittenFrameNumber);
- if (error != KErrNone)
- iMonitor->Error(error);
-
- iNumberOfFrames = iProcessor->GetClipNumberOfFrames();
- iPreviousTimeStamp = TTimeIntervalMicroSeconds(-1);
-
- iDataLength = iCurrentFrameLength = 0;
- iDataFormat = EDataUnknown;
-
- iStreamEnd = iStreamEndRead = 0;
-
- // reset also delayed buffer; it will need to be anyway re-read
- delete iDelayedBuffer;
- iDelayedBuffer = 0;
- iDelayedWrite = EFalse;
-
- PRINT((_L("CVideoProcessor::MtroResume() - iFrameNumber = %d"), iFrameNumber));
-
- if (!IsActive())
- {
- // Make us active
- PRINT((_L("CVideoProcessor::MtroResume() set active")));
- SetActive();
- iStatus = KRequestPending;
- }
-
- PRINT((_L("CVideoProcessor::MtroResume() out")));
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::MtroReturnCodedBuffer
-// Called by transcoder to return bitstream buffer
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::MtroReturnCodedBuffer(CCMRMediaBuffer* aBuffer)
-{
-
- VDASSERT(aBuffer == iMediaBuffer, 29);
-
- iIsThumbFrameBeingCopied = EFalse;
- iDecoderSpecificInfoSent = ETrue;
-
-#ifdef _DEBUG
- TTimeIntervalMicroSeconds ts = aBuffer->TimeStamp();
-
- PRINT((_L("CVideoProcessor::MtroReturnCodedBuffer() timeStamp = %d ms"),
- I64INT( ts.Int64() ) / 1000 ));
-
-#endif
-
- if (!iFirstColorTransitionFrame)
- {
- // Throw away the data for this frame:
- VDASSERT(iDataLength >= iCurrentFrameLength,4);
- Mem::Copy(iDataBuffer, iDataBuffer + iCurrentFrameLength,
- iDataLength - iCurrentFrameLength);
- iDataLength = iDataLength - iCurrentFrameLength;
- iCurrentFrameLength = 0;
- }
-
- if (!iThumbnailMode)
- {
-
- // check if the next frame in queue is waiting to be encoded
- // and start timer to detect possible frameskip
- if ( IsNextFrameBeingEncoded() )
- {
- if ( !iTimer->IsPending() )
- iTimer->SetTimer( TTimeIntervalMicroSeconds32( iMaxEncodingDelay ) );
- }
-
- if (iFrameInfoArray.Count() >= iMaxItemsInProcessingQueue)
- {
- PRINT((_L("CVideoProcessor::MtroReturnCodedBuffer() - %d items in queue, suspend decoding"),
- iFrameInfoArray.Count() ));
-
- iDecodingSuspended = ETrue;
-
- return;
- }
-
- VDASSERT(IsActive(), 40);
- VDASSERT(iDecodePending, 41);
-
- // complete request
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- }
- else if (iDataFormat == EDataAVC)
- {
-
- VDASSERT(IsActive(), 40);
- VDASSERT(iDecodePending, 41);
-
- // NOTE: it would make sense to call AsyncStopL() here,
- // but at least in WINSCW it didn't have any effect
- //if (iThumbFramesToWrite == 0)
- //{
- //iTransCoder->AsyncStopL();
- //iTranscoderStarted = EFalse;
- //}
-
- if (iStatus == KRequestPending)
- {
- PRINT((_L("CVideoProcessor::MtroReturnCodedBuffer() - completing request")));
- // complete request
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- }
- }
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::MtroSetInputFrameRate
-// Called by transcoder to request inout framerate
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::MtroSetInputFrameRate(TReal& aRate)
-{
- TReal rate = iProcessor->GetVideoClipFrameRate();
-
- if ( rate <= 15.0 )
- {
- rate = 15.0;
- }
- else
- {
- rate = 30.0;
- }
-
- aRate = rate;
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::MtroAsyncStopComplete
-// Called by transcoder after async. stop is complete
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::MtroAsyncStopComplete()
-{
- PRINT((_L("CVideoProcessor::MtroAsyncStopComplete()")));
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::MtroPictureFromTranscoder
-// Called by transcoder to return a decoded picture
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::MtroPictureFromTranscoder(TTRVideoPicture* aPicture)
-{
-
- TTimeIntervalMicroSeconds decodedTs = aPicture->iTimestamp;
-
- PRINT((_L("CVideoProcessor::MtroPictureFromTranscoder(), timestamp %d ms"),
- I64INT( decodedTs.Int64() ) / 1000 ));
-
- if (iThumbnailMode)
- {
- iThumbDecoded = ETrue;
-
- // handle thumbnail
- HandleThumbnailFromTranscoder(aPicture);
-
- return;
- }
-
- // search the decoded frame from list
- TInt index;
- for (index = 0; index < iFrameInfoArray.Count(); )
- {
- PRINT((_L("CVideoProcessor::MtroPictureFromTranscoder(), checking frame with index %d"), index));
-
- TTimeIntervalMicroSeconds ts =
- (iProcessor->GetVideoTimeInMsFromTicks(iFrameInfoArray[index].iTimeStamp, EFalse)) * 1000;
-
- if (ts < decodedTs && ( (iFrameInfoArray[index].iEncodeFrame == EFalse) ||
- (iFrameInfoArray[index].iTranscoderMode == EFullWithIM &&
- iFrameInfoArray[index].iModificationApplied == 0) ) )
- {
- // if there are decode-only or transcoding w/intermediate modification
- // frames in the queue before this one, remove those
- PRINT((_L("CVideoProcessor::MtroPictureFromTranscoder(), removing frame with timestamp %d ms"),
- I64INT( ts.Int64() ) / 1000 ));
-
- iFrameInfoArray.Remove(index);
- // don't increment index
- continue;
- }
-
- if (ts == decodedTs)
- {
- PRINT((_L("CVideoProcessor::MtroPictureFromTranscoder(), found decoded frame at index %d"), index));
- break;
- }
-
- index++;
- }
-
- // If decoded frame is unexpected, i.e. it is not found from book-keeping,
- // or it is not an intermediate modification frame, return frame here
- // and continue
- if ( index >= iFrameInfoArray.Count() ||
- ( iFrameInfoArray[index].iEncodeFrame == 1 &&
- iFrameInfoArray[index].iTranscoderMode != EFullWithIM ) )
- {
- PRINT((_L("CVideoProcessor::MtroPictureFromTranscoder(), unexpected decoded frame, iTranscoderMode %d"), iTranscoderMode));
- // send picture back to transcoder
- TInt error = KErrNone;
- TRAP( error, iTransCoder->SendPictureToTranscoderL(aPicture) );
- if ( error != KErrNone )
- {
- iMonitor->Error(error);
- }
- return;
- }
-
- if (iFrameInfoArray[index].iEncodeFrame == EFalse)
- {
- // handle decode-only frame
- HandleDecodeOnlyFrameFromTranscoder(aPicture, index);
- return;
- }
-
- // check color effect
- TInt colorEffect = TColorEffect2TInt( iProcessor->GetColorEffect() );
- if (colorEffect != 0/*None*/)
- {
- // U,V value for the color toning
- TInt colorToneU;
- TInt colorToneV;
- iProcessor->GetColorTone((TInt&)colorToneU, (TInt&)colorToneV);
- // apply color effect
- ApplySpecialEffect( colorEffect, const_cast<TUint8*>(aPicture->iRawData->Ptr()), colorToneU, colorToneV );
-
- }
-
- if(iFrameInfoArray[index].iTransitionFrame == 1)
- {
- // apply transition to frame
- HandleTransitionFrameFromTranscoder(aPicture, index);
- }
-
- iFrameInfoArray[index].iModificationApplied = ETrue;
-
- // send picture back to transcoder for encoding
- TInt error = KErrNone;
- TRAP( error, iTransCoder->SendPictureToTranscoderL(aPicture) );
- if ( error != KErrNone )
- {
- iMonitor->Error(error);
- return;
- }
-
- // check if the next frame is waiting to be encoded, set timer if so
- if ( IsNextFrameBeingEncoded() )
- {
- if ( !iTimer->IsPending() )
- iTimer->SetTimer( TTimeIntervalMicroSeconds32( iMaxEncodingDelay ) );
- }
-
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::HandleThumbnailFromTranscoder
-// Handle thumbnail frame
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::HandleThumbnailFromTranscoder(TTRVideoPicture* aPicture)
-{
-
- TInt error = KErrNone;
-
- PRINT((_L("CVideoProcessor::HandleThumbnailFromTranscoder() begin")));
-
- if (iProcessingComplete)
- {
- // if requested thumbnail has been done already,
- // just release picture and return
- PRINT((_L("CVideoProcessor::HandleThumbnailFromTranscoder(), thumb already finished, returning")));
-
- TRAP( error, iTransCoder->SendPictureToTranscoderL(aPicture) );
- if ( error != KErrNone )
- {
- iMonitor->Error(error);
- return;
- }
- return;
- }
-
- TInt yuvLength = iVideoWidth*iVideoHeight;
- yuvLength += (yuvLength >> 1);
- // copy to iFrameBuffer
- Mem::Copy(iFrameBuffer, aPicture->iRawData->Ptr(), yuvLength);
-
- // release picture
- TRAP( error, iTransCoder->SendPictureToTranscoderL(aPicture) );
- if ( error != KErrNone )
- {
- iProcessor->NotifyThumbnailReady(error);
- return;
- }
-
- VDASSERT(iDecodePending, 33);
- VDASSERT(IsActive(), 150);
-
- if (iStatus == KRequestPending)
- {
-
- PRINT((_L("CVideoProcessor::HandleThumbnailFromTranscoder(), complete request")));
- // complete request
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- }
-
- PRINT((_L("CVideoProcessor::HandleThumbnailFromTranscoder() end")));
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::HandleDecodeOnlyFrameFromTranscoder
-// Handle decode-only frame
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::HandleDecodeOnlyFrameFromTranscoder(TTRVideoPicture* aPicture, TInt aIndex)
-{
-
- VDASSERT(iFrameInfoArray[aIndex].iTranscoderMode == EDecodeOnly, 43);
-
- if ( iFrameInfoArray[aIndex].iTransitionFrame &&
- iFrameInfoArray[aIndex].iTransitionPosition == EPositionEndOfClip )
- {
- if ( iEndTransitionColor == EColorTransition )
- {
- // Save decoded frame to file
-
- TSize a = iProcessor->GetMovieResolution();
- TInt yuvLength = a.iWidth*a.iHeight;
- yuvLength += (yuvLength>>1);
- TPtr8 ptr(0,0);
- TUint8* tmpBuf=0;
-
- ptr.Set( *aPicture->iRawData );
- tmpBuf = const_cast<TUint8*>(aPicture->iRawData->Ptr());
-
- TInt colorEffect = TColorEffect2TInt( iProcessor->GetColorEffect() );
- if (colorEffect != 0 /*None*/)
- {
- // U,V value for the color toning
- TInt colorToneU;
- TInt colorToneV;
- iProcessor->GetColorTone((TInt&)colorToneU, (TInt&)colorToneV);
- // apply special effect
- ApplySpecialEffect( colorEffect, tmpBuf, colorToneU, colorToneV );
- }
-
- TInt frameDuration = GetFrameDuration(iFrameInfoArray[aIndex].iFrameNumber);
-
- if (frameDuration <= 0)
- {
- TReal frameRate = iProcessor->GetVideoClipFrameRate();
- VDASSERT(frameRate > 0.0, 107);
- TInt timeScale = iProcessor->GetVideoClipTimeScale();
- TInt64 durationMs = TInt64( ( 1000.0 / frameRate ) + 0.5 );
-
- // in ticks
- frameDuration = TInt( ( (TReal)durationMs * (TReal)timeScale / 1000.0 ) + 0.5 );
- }
-
- TInt error = iProcessor->SaveVideoFrameToFile( ptr, frameDuration, iFrameInfoArray[aIndex].iTimeStamp );
- if ( error != KErrNone )
- {
- PRINT((_L("CVideoProcessor::HandleDecodeOnlyFrameFromTranscoder() - SaveVideoFrameToFile failed")));
- iMonitor->Error(error);
- return;
- }
- }
- }
-
- iFrameInfoArray.Remove(aIndex);
-
- PRINT((_L("CVideoProcessor::HandleDecodeOnlyFrameFromTranscoder() - removed decode only pic, %d items in queue"),
- iFrameInfoArray.Count()));
-
- // release picture
- TInt error = KErrNone;
- TRAP( error, iTransCoder->SendPictureToTranscoderL(aPicture) );
- if ( error != KErrNone )
- {
- iMonitor->Error(error);
- return;
- }
-
- if (iStreamEndRead && iFrameInfoArray.Count() == 0 )
- {
- PRINT((_L("CVideoProcessor::HandleDecodeOnlyFrameFromTranscoder() - stream end read, no frames left")));
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
- iTimer->CancelTimer();
- iProcessingComplete = ETrue;
- // activate object to end processing
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- return;
- }
-
- if (iDecodingSuspended && !iStreamEndRead)
- {
- if (iFrameInfoArray.Count() < iMaxItemsInProcessingQueue && !iDelayedWrite)
- {
- PRINT((_L("CVideoProcessor::HandleDecodeOnlyFrameFromTranscoder() - Resume decoding")));
- iDecodingSuspended = EFalse;
- // activate object to start decoding
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- return;
- }
- }
-
- // check if the next frame is waiting to be encoded, set timer if so
- if ( IsNextFrameBeingEncoded() )
- {
- if ( !iTimer->IsPending() )
- iTimer->SetTimer( TTimeIntervalMicroSeconds32( iMaxEncodingDelay ) );
- }
-
- return;
-
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::HandleTransitionFrameFromTranscoder
-// Handle transition frame
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::HandleTransitionFrameFromTranscoder(TTRVideoPicture* aPicture, TInt aIndex)
-{
-
- // apply transition effect in spatial domain (to yuv data in encoder buffer)
- if ( iFrameInfoArray[aIndex].iTransitionPosition == EPositionStartOfClip &&
- iStartTransitionColor == EColorTransition )
- {
- // Do blending transition: wipe / crossfade
-
- TSize a = iProcessor->GetMovieResolution();
- TInt yuvLength = a.iWidth*a.iHeight;
- yuvLength += (yuvLength>>1);
-
- if (iFrameInfoArray[aIndex].iRepeatFrame == 0)
- {
- if( !iColorTransitionBuffer )
- {
- iColorTransitionBuffer = (TUint8*)User::Alloc( yuvLength );
- if (!iColorTransitionBuffer)
- {
- iMonitor->Error(KErrNoMemory);
- return;
- }
- }
-
- if( !iOrigPreviousYUVBuffer )
- {
- iOrigPreviousYUVBuffer = (TUint8*)User::Alloc( yuvLength );
- if (!iOrigPreviousYUVBuffer)
- {
- iMonitor->Error(KErrNoMemory);
- return;
- }
- }
-
- TPtr8 ptr( iColorTransitionBuffer, 0, yuvLength );
-
- if ( iProcessor->GetVideoFrameFromFile( ptr, yuvLength, iFrameDuration, iTimeStamp ) != KErrNone )
- //|| iFrameDuration == 0 || iTimeStamp == 0 )
- {
- // failure in reading frame data from previous clip
- // continue using the current frame data
- Mem::Copy( iColorTransitionBuffer, aPicture->iRawData->Ptr(), yuvLength );
- }
- else
- {
- // buffer frame from previous clip (read from file)
- Mem::Copy( iOrigPreviousYUVBuffer, iColorTransitionBuffer, yuvLength );
- if ( iStartOfClipTransition == (TInt)EVedMiddleTransitionEffectCrossfade )
- {
- // Target frame is the one read from file, iColorTransitionBuffer
- ApplyBlendingTransitionEffect( iColorTransitionBuffer, const_cast<TUint8*>(aPicture->iRawData->Ptr()),
- 0 /* repeatFrame */, iFrameInfoArray[aIndex].iTransitionFrameNumber);
- }
- else
- {
- // Target frame is the one read from file, iColorTransitionBuffer
- ApplySlidingTransitionEffect( iColorTransitionBuffer, const_cast<TUint8*>(aPicture->iRawData->Ptr()), (TVedMiddleTransitionEffect)iStartOfClipTransition,
- 0 /* repeatFrame */, iFrameInfoArray[aIndex].iTransitionFrameNumber);
- }
- // copy frame from edited buffer to transcoder buffer
- Mem::Copy( const_cast<TUint8*>(aPicture->iRawData->Ptr()), iColorTransitionBuffer, yuvLength );
- }
- }
- else
- {
- // repeatFrame
-
- if ( iStartOfClipTransition == (TInt)EVedMiddleTransitionEffectCrossfade )
- {
- ApplyBlendingTransitionEffect( iOrigPreviousYUVBuffer, const_cast<TUint8*>(aPicture->iRawData->Ptr()),
- 1 /* repeatFrame */, iFrameInfoArray[aIndex].iTransitionFrameNumber);
- }
- else
- {
- ApplySlidingTransitionEffect( iOrigPreviousYUVBuffer, const_cast<TUint8*>(aPicture->iRawData->Ptr()), (TVedMiddleTransitionEffect)iStartOfClipTransition,
- 1 /* repeatFrame */, iFrameInfoArray[aIndex].iTransitionFrameNumber );
- }
- // copy frame from edited buffer to transcoder buffer
- Mem::Copy( const_cast<TUint8*>(aPicture->iRawData->Ptr()), iOrigPreviousYUVBuffer, yuvLength );
- }
- }
- else
- {
- // apply transition effect in spatial domain (to yuv data in encoder buffer)
-
- // Do fading transition
- ApplyFadingTransitionEffect(const_cast<TUint8*>(aPicture->iRawData->Ptr()), iFrameInfoArray[aIndex].iTransitionPosition, iFrameInfoArray[aIndex].iTransitionColor,
- iFrameInfoArray[aIndex].iTransitionFrameNumber);
- }
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::ProcessThumb
-// Starts thumbnail generation
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TInt CVideoProcessor::ProcessThumb(MThumbnailObserver* aThumbObserver, TInt aFrameIndex, TInt aStartFrameIndex, TVedTranscodeFactor* aFactor)
-{
- TInt error;
-// TInt goodFrame = 0;
-// TInt frameSkip = 10;
-// TInt frameNumber = aStartFrameIndex;
- TPtrC8 inputPtr;
- TPtr8 outputPtr(0,0);
-
- iThumbObserver = aThumbObserver;
- iThumbFrameIndex = aFrameIndex;
- iThumbFrameNumber = aStartFrameIndex;
- iFramesToSkip = 0;
- iNumThumbFrameSkips = 0;
- iPreviousTimeStamp = TTimeIntervalMicroSeconds(-1);
- iProcessingComplete = EFalse;
-
- iThumbFramesToWrite = iProcessor->GetOutputNumberOfFrames() - iThumbFrameNumber;
-
- // get transcode factor to determine input stream type
- TRAP(error, GetTranscodeFactorL(*aFactor));
- if (error != KErrNone)
- return error;
-
- TVedVideoType inType;
- if (aFactor->iStreamType == EVedVideoBitstreamModeH263)
- inType = EVedVideoTypeH263Profile0Level10;
-
- else if (aFactor->iStreamType == EVedVideoBitstreamModeAVC)
- inType = EVedVideoTypeAVCBaselineProfile;
-
- else
- inType = EVedVideoTypeMPEG4SimpleProfile;
-
- if (aFactor->iStreamType == EVedVideoTypeUnrecognized ||
- aFactor->iStreamType == EVedVideoTypeNoVideo)
- return KErrorCode;
-
- iDecoding = ETrue;
-
- // first frame is now read in iDataBuffer, initialize transcoder
- TRAP(error, CreateAndInitializeTranscoderL(inType, CTRTranscoder::EDecoding))
- if (error != KErrNone)
- return error;
-
- // wait for initialisation to complete => RunL
-
- return KErrNone;
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::ProcessThumb
-// Processes a thumbnail frame internally
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::ProcessThumb(TBool aFirstFrame)
-{
-
- PRINT((_L("CVideoProcessor::ProcessThumb() - begin()")));
-
- iThumbDecoded = EFalse;
-
- if (aFirstFrame)
- {
- // frame read in iDataBuffer, decode
- CCMRMediaBuffer::TBufferType bt =
- (iDataFormat == EDataH263) ? CCMRMediaBuffer::EVideoH263 : CCMRMediaBuffer::EVideoMPEG4;
- TInt index = iThumbFrameNumber - ( iProcessor->GetOutputNumberOfFrames() -
- iProcessor->GetClipNumberOfFrames() );
- TTimeIntervalMicroSeconds ts =
- TTimeIntervalMicroSeconds(iProcessor->GetVideoTimeInMsFromTicks(iProcessor->VideoFrameTimeStamp(index), ETrue) * TInt64(1000) );
-
- // Get the AVC bit stream and add NAL headers
- if(iDataFormat == EDataAVC)
- {
- TInt error = KErrNone;
-
- // insert dec.config. record in the beginning of buffer
- TRAP( error, InsertDecoderSpecificInfoL() );
- if (error != KErrNone)
- {
- iProcessor->NotifyThumbnailReady(error);
- return;
- }
-
- PRINT((_L("CVideoProcessor::ProcessThumb() - ProcessAVCBitStream()")));
-
- TPtr8 ptr(iDataBuffer, iCurrentFrameLength, iBufferLength);
- TRAP( error, iAvcEdit->ProcessAVCBitStreamL((TDes8&)(ptr), (TInt&)(iCurrentFrameLength),
- iProcessor->GetDecoderSpecificInfoSize(), ETrue ) );
-
- if (error != KErrNone)
- {
- iProcessor->NotifyThumbnailReady(error);
- return;
- }
- iDataLength = iCurrentFrameLength;
-
- }
-
- // insert VOL header to beginning of buffer
- if (iDataFormat == EDataMPEG4)
- {
- TRAPD( error, InsertDecoderSpecificInfoL() );
- if (error != KErrNone)
- {
- iProcessor->NotifyThumbnailReady(error);
- return;
- }
- }
-
- iMediaBuffer->Set( TPtrC8(iDataBuffer, iBufferLength),
- bt,
- iCurrentFrameLength,
- ETrue, // keyFrame
- ts
- );
-
- iPreviousTimeStamp = ts;
-
- iIsThumbFrameBeingCopied = ETrue;
- iDecodePending = ETrue;
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
-
- PRINT((_L("CVideoProcessor::ProcessThumb() - WriteCodedBuffer, thumb frame #%d, timestamp %d ms"),
- iThumbFrameNumber, I64INT( ts.Int64() ) / 1000 ));
-
- TRAPD( err, iTransCoder->WriteCodedBufferL(iMediaBuffer) );
- if (err != KErrNone)
- {
- // ready
- FinalizeThumb(err);
- return;
- }
- iThumbFramesToWrite--;
-
- return;
- }
-
- if (iThumbFrameIndex == 0)
- {
- // ready
- FinalizeThumb(KErrNone);
- return;
- }
-
- iThumbFrameNumber++;
-
- if (iDataFormat == EDataAVC)
- {
- // In AVC case, we have to stop decoding before the very last
- // frames are decoded, since for some reason the transcoder/decoder
- // does not decode those frames
-
- // get max number of buffered frames according to spec
- TInt buffered = iAvcEdit->GetMaxAVCFrameBuffering(iInputAVCLevel, TSize(iVideoWidth, iVideoHeight));
-
- if (iThumbFrameNumber > iProcessor->GetOutputNumberOfFrames() - 1 - buffered )
- {
- // ready
- FinalizeThumb(KErrNone);
- return;
- }
- }
-
- if (iThumbFrameIndex < 0)
- {
- if (iFramesToSkip == 0)
- {
- PRINT((_L("CVideoProcessor::ProcessThumb() frameskip done %d times"), iNumThumbFrameSkips));
-
- // limit the number of frame skip cycles to 3, because with
- // near-black or near-white videos we may never find a good thumb.
- // => max. 30 frames are decoded to get the thumb
-
- // check quality & frame skip cycles
- if ( CheckFrameQuality(iFrameBuffer) || iNumThumbFrameSkips >= 3 )
- {
- // quality ok or searched long enough, return
- FinalizeThumb(KErrNone);
- return;
- }
- iFramesToSkip = 10;
- iNumThumbFrameSkips++;
- }
- else
- iFramesToSkip--;
-
- // read new frame & decode
- }
-
- if (iThumbFrameIndex > 0)
- {
- if (iThumbFrameNumber > iThumbFrameIndex)
- {
- // ready
- FinalizeThumb(KErrNone);
- return;
- }
- // read new frame & decode
- }
-
- if (iIsThumbFrameBeingCopied)
- {
- PRINT((_L("CVideoProcessor::ProcessThumb() - thumb being copied, activate")));
- // Re-activate to wait for MtroReturnCodedBuffer
- iDecodePending = ETrue;
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
- }
- else
- {
- PRINT((_L("CVideoProcessor::ProcessThumb() - read and write new")));
- // send new frame for decoding
- ReadAndWriteThumbFrame();
- }
-
- PRINT((_L("CVideoProcessor::ProcessThumb() - end")));
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::ReadAndWriteThumbFrame
-// Reads a new frame to input queue and sends it to transcoder
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::ReadAndWriteThumbFrame()
-{
-
- PRINT((_L("CVideoProcessor::ReadAndWriteThumbFrame() - begin, thumb frames to write %d"),
- iThumbFramesToWrite));
-
- TInt error = KErrNone;
-
- if ( iThumbFramesToWrite )
- {
- // read new frame to input queue
- if(iThumbFrameNumber < (iProcessor->GetOutputNumberOfFrames())) // do not read last frame (already read!)
- {
- CMP4Demux *demux = (CMP4Demux *)iProcessor->GetDemux();
- error = demux->ReadVideoFrames(1);
- if (error != KErrNone)
- {
- FinalizeThumb(error);
- return;
- }
- }
- else
- {
- // no frames left, return
- FinalizeThumb(KErrNone);
- return;
- }
-
- iDataLength = 0;
- iCurrentFrameLength = 0;
- iDataFormat = EDataUnknown;
-
- if (ReadFrame())
- {
- // frame read in iDataBuffer, decode
- CCMRMediaBuffer::TBufferType bt =
- (iDataFormat == EDataH263) ? CCMRMediaBuffer::EVideoH263 : CCMRMediaBuffer::EVideoMPEG4;
-
- TInt index = iThumbFrameNumber - ( iProcessor->GetOutputNumberOfFrames() -
- iProcessor->GetClipNumberOfFrames() );
-
- TTimeIntervalMicroSeconds ts =
- TTimeIntervalMicroSeconds(iProcessor->GetVideoTimeInMsFromTicks(iProcessor->VideoFrameTimeStamp(index), ETrue) * TInt64(1000) );
-
- if (ts <= iPreviousTimeStamp)
- {
- // adjust timestamp so that its bigger than ts of previous frame
- TReal frameRate = iProcessor->GetVideoClipFrameRate();
- VDASSERT(frameRate > 0.0, 108);
- TInt64 durationMs = TInt64( ( 1000.0 / frameRate ) + 0.5 );
- durationMs /= 2; // add half the duration of one frame
-
- ts = TTimeIntervalMicroSeconds( iPreviousTimeStamp.Int64() + durationMs*1000 );
- }
-
- iPreviousTimeStamp = ts;
-
- // Get the AVC bit stream and add NAL headers
- if(iDataFormat == EDataAVC)
- {
- TPtr8 ptr(iDataBuffer, iCurrentFrameLength, iBufferLength);
- TRAPD( error, iAvcEdit->ProcessAVCBitStreamL((TDes8&)(ptr), (TInt&)(iCurrentFrameLength),
- iProcessor->GetDecoderSpecificInfoSize(), EFalse ) );
-
- if (error != KErrNone)
- {
- FinalizeThumb(error);
- return;
- }
- iDataLength = iCurrentFrameLength;
- }
-
- iMediaBuffer->Set( TPtrC8(iDataBuffer, iBufferLength),
- bt,
- iCurrentFrameLength,
- iProcessor->GetVideoFrameType(index),
- ts );
-
- iIsThumbFrameBeingCopied = ETrue;
- iDecodePending = ETrue;
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
-
- PRINT((_L("CVideoProcessor::ProcessThumb() - WriteCodedBuffer, thumb frame #%d, timestamp %d ms"),
- iThumbFrameNumber, I64INT( ts.Int64() ) / 1000 ));
-
- TRAPD( err, iTransCoder->WriteCodedBufferL(iMediaBuffer) );
- if (err != KErrNone)
- {
- FinalizeThumb(err);
- }
- iThumbFramesToWrite--;
- return;
- }
- }
-
- else
- {
- if (iDataFormat == EDataAVC)
- {
- PRINT((_L("CVideoProcessor::ReadAndWriteThumbFrame() - all frames written, wait for output")));
- // all necessary frames written to decoder, now wait for output frames
- iDecodePending = ETrue;
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
- }
- else
- {
- FinalizeThumb(KErrNone);
- }
- }
-
- PRINT((_L("CVideoProcessor::ReadAndWriteThumbFrame() - end")));
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::FinalizeThumb
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::FinalizeThumb(TInt aError)
-{
- iProcessingComplete = ETrue;
- if (iTranscoderStarted)
- {
- TRAPD( err, iTransCoder->StopL() );
- if (err != KErrNone) { }
- iTranscoderStarted = EFalse;
- }
- iProcessor->NotifyThumbnailReady(aError);
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::FetchThumb
-// For getting a pointer to YUV thumbnail frame
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TInt CVideoProcessor::FetchThumb(TUint8** aYUVDataPtr)
-{
- *aYUVDataPtr = iFrameBuffer;
-
- return KErrNone;
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::GetTranscodeFactorL
-// Gets the transcode factor from the current clip
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TInt CVideoProcessor::GetTranscodeFactorL(TVedTranscodeFactor& aFactor)
-{
- // start reading video frames
- CMP4Demux *demux = (CMP4Demux *)iProcessor->GetDemux();
- TInt error = demux->ReadVideoFrames(1);
-
- if (error != KErrNone)
- User::Leave(error);
-
- // seek to and decode first frame
- if (!ReadFrame())
- User::Leave(KErrCorrupt);
-
- // Get pointer to the frame data
- TPtr8 inputPtr(0,0);
- if ( iDataFormat == EDataH263 )
- inputPtr.Set(iDataBuffer, iCurrentFrameLength + KH263StartCodeLength, iCurrentFrameLength + KH263StartCodeLength);
- else
- inputPtr.Set(iDecoderSpecificInfo->Des());
-
- if(iDataFormat == EDataAVC)
- {
- // @@ HARI AVC harcode for now
- // Set transcode factors
- aFactor.iTRes = 30;
- aFactor.iStreamType = EVedVideoBitstreamModeAVC;
- }
- else
- {
- // Get the VOL header from the frame data
- CVedVolReader* reader = CVedVolReader::NewL();
- CleanupStack::PushL(reader);
- reader->ParseVolHeaderL((TDesC8&) inputPtr);
-
- // Set transcode factors
- aFactor.iTRes = reader->TimeIncrementResolution();
- aFactor.iStreamType = reader->BitstreamMode();
-
- CleanupStack::PopAndDestroy(reader);
- }
-
- return KErrNone;
-}
-
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::CheckFrameQuality
-// Checks if a frame has "good" or "legible" quality
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TInt CVideoProcessor::CheckFrameQuality(TUint8* aYUVDataPtr)
-{
- TInt i;
- TInt minValue = 255;
- TInt maxValue = 0;
- TInt goodFrame = 1;
- TInt runningSum=0;
- TInt averageValue=0;
- TInt pixelSkips = 4;
- TInt numberOfSamples=0;
- TInt minMaxDeltaThreshold = 20;
- TInt extremeRegionThreshold = 20;
- TInt ySize = iVideoWidth*iVideoHeight;
-
- // gather image statistics
- for(i=0, numberOfSamples=0; i<ySize; i+=pixelSkips, aYUVDataPtr+=pixelSkips, numberOfSamples++)
- {
- runningSum += *aYUVDataPtr;
- if(*aYUVDataPtr > maxValue)
- maxValue = *aYUVDataPtr;
- if(*aYUVDataPtr < minValue)
- minValue = *aYUVDataPtr;
- }
- VDASSERT(numberOfSamples,10);
- averageValue = runningSum/numberOfSamples;
-
- // make decision based statistics
- if((maxValue - minValue) < minMaxDeltaThreshold)
- goodFrame = 0;
- else
- {
- if(averageValue < (minValue + extremeRegionThreshold) ||
- averageValue > (maxValue - extremeRegionThreshold))
- goodFrame = 0;
- }
- return goodFrame;
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::ReadFrame
-// Reads a frame from input queue to internal buffer
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TInt CVideoProcessor::ReadFrame()
-{
-
- TUint doNow;
-
- if (iProcessor->GetCurrentClipVideoType() == EVedVideoTypeAVCBaselineProfile)
- iDataFormat = EDataAVC;
-
- // Determine data format if needed
- if ( iDataFormat == EDataUnknown )
- {
- // We'll need four bytes of data
- while ( iDataLength < 4 )
- {
- // Get a block (we can't have one as we go here only at the stream
- // start)
- VDASSERT(!iBlock,11);
- while ( (!iBlock) || (iBlock->Length() == 0) )
- {
- if ( iBlock )
- iQueue->ReturnBlock(iBlock);
- if ( (iBlock = iQueue->ReadBlock()) == NULL )
- return EFalse;
- }
- iBlockPos = 0;
-
- // get timestamp for first frame
- if ( iTiming == ETimeStamp )
- {
- VDASSERT( (TUint)iBlock->Length() >= 8,12 );
- iBlockPos += 4;
- }
-
- // Copy data from block to buffer:
- doNow = 4 - iDataLength;
- if ( doNow > (TUint) iBlock->Length() - iBlockPos )
- doNow = iBlock->Length() - iBlockPos;
- Mem::Copy(iDataBuffer+iDataLength, iBlock->Ptr()+iBlockPos, doNow);
- iDataLength += doNow;
- iBlockPos += doNow;
-
- // Return the block if it doesn't have any more data
- if ( ((TInt)iBlockPos == iBlock->Length()) )
- {
- iQueue->ReturnBlock(iBlock);
- iBlock = 0;
- }
- }
-
- // OK, we have 4 bytes of data. Check if the buffer starts with a
- // H.263 PSC:
- if ( (iDataBuffer[0] == 0) && (iDataBuffer[1] == 0) &&
- ((iDataBuffer[2] & 0xfc) == 0x80) )
- {
- // Yes, this is a H.263 stream
- iDataFormat = EDataH263;
- }
-
- // It should be MPEG-4, check if it starts with MPEG 4 Visual
- // Object Sequence start code, Visual Object start code, Video
- // Object start code, or Video Object Layer start code
- else if ( ((iDataBuffer[0] == 0) && (iDataBuffer[1] == 0) && (iDataBuffer[2] == 1) && (iDataBuffer[3] == 0xb0)) ||
- ((iDataBuffer[0] == 0) && (iDataBuffer[1] == 0) && (iDataBuffer[2] == 1) && (iDataBuffer[3] == 0xb6)) ||
- ((iDataBuffer[0] == 0) && (iDataBuffer[1] == 0) && (iDataBuffer[2] == 1) && (iDataBuffer[3] == 0xb3)) ||
- ((iDataBuffer[0] == 0) && (iDataBuffer[1] == 0) && (iDataBuffer[2] == 1) && (iDataBuffer[3] == 0xb5)) ||
- ((iDataBuffer[0] == 0) && (iDataBuffer[1] == 0) && (iDataBuffer[2] == 1) && ((iDataBuffer[3] >> 5) == 0)) ||
- ((iDataBuffer[0] == 0) && (iDataBuffer[1] == 0) && (iDataBuffer[2] == 1) && ((iDataBuffer[3] >> 4) == 2)))
- {
- iDataFormat = EDataMPEG4;
- }
- else
- {
- PRINT((_L("CVideoProcessor::ReadFrame() - no PSC or MPEG-4 start code in the start of the buffer")));
- if (iMonitor)
- iMonitor->Error(KErrCorrupt);
- return EFalse;
- }
- }
-
- // Determine the start code length
- TUint startCodeLength = 0;
- switch (iDataFormat)
- {
- case EDataH263:
- startCodeLength = KH263StartCodeLength;
- break;
- case EDataMPEG4:
- startCodeLength = KMPEG4StartCodeLength ;
- break;
- case EDataAVC:
- break;
-
- default:
- User::Panic(_L("CVideoPlayer"), EInternalAssertionFailure);
- }
-
- // If the stream has ended, we have no blocks and no data for even a
- // picture start code, we can't get a frame
- if( iDataFormat == EDataH263 )
- {
- if ( iStreamEnd && (iQueue->NumDataBlocks() == 0) &&
- (iCurrentFrameLength <= startCodeLength) && (iDataLength <= startCodeLength) )
- return EFalse;
- }
- else
- {
- if ( iStreamEnd && (iQueue->NumDataBlocks() == 0) &&
- (iCurrentFrameLength <= startCodeLength) && (iDataLength < startCodeLength) )
- return EFalse;
- }
-
- switch(iDataFormat)
- {
- case EDataH263:
- return ReadH263Frame();
-// break;
-
- case EDataMPEG4:
- return ReadMPEG4Frame();
-// break;
-
- case EDataAVC:
- return ReadAVCFrame();
-// break;
-
- default:
- User::Panic(_L("CVideoProcessor"), EInternalAssertionFailure);
-
- }
-
- return ETrue;
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::ReadH263Frame
-// Reads a H.263 frame from input queue to internal buffer
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TBool CVideoProcessor::ReadH263Frame()
-{
-
- VDASSERT( iDataFormat == EDataH263, 17 );
-
- TInt offset = 0;
- if ( iTiming == ETimeStamp )
- offset = 4;
-
- // There should be one PSC at the buffer start,
- // and no other PSCs up to iDataLength
- if ( (iDataLength >= KH263StartCodeLength) &&
- ((iDataBuffer[0] != 0) || (iDataBuffer[1] != 0) || ((iDataBuffer[2] & 0xfc) != 0x80)) )
- {
- PRINT((_L("CVideoProcessor::ReadH263Frame() - no PSC in the start of the buffer")))
- if (iMonitor)
- iMonitor->Error(KErrCorrupt);
- return EFalse;
- }
-
- if (iCurrentFrameLength < KH263StartCodeLength )
- iCurrentFrameLength = KH263StartCodeLength;
-
- TBool gotPSC = EFalse;
- while (!gotPSC)
- {
- // If we don't have a block at the moment, get one and check if it
- // has a new PSC
- while (!iBlock)
- {
- if ((iBlock = iQueue->ReadBlock()) == NULL)
- {
- if (!iStreamEnd && !iProcessor->IsThumbnailInProgress())
- return EFalse;
-
- // No more blocks in the stream. If we have more data than
- // just a PSC, use the remaining as the last frame. We'll
- // append an End Of Stream (EOS) codeword to the stream end
- // to keep the decoder happy
- if (iDataLength <= 3)
- return EFalse;
- iCurrentFrameLength = iDataLength;
- if (iBufferLength < (iDataLength+3))
- {
- iBufferLength += 3;
- TUint8* tmp = (TUint8*) User::ReAlloc(iDataBuffer, iBufferLength);
- if ( !tmp )
- {
- if (iMonitor)
- iMonitor->Error(KErrNoMemory);
- return EFalse;
- }
- iDataBuffer = tmp;
- }
- iDataBuffer[iCurrentFrameLength] = 0;
- iDataBuffer[iCurrentFrameLength+1] = 0;
- iDataBuffer[iCurrentFrameLength+2] = 0xfc;
- iDataLength += 3;
- return ETrue;
- }
-
- iBlockPos = 0;
- // Return empty blocks immediately
- if ( iBlock->Length() == 0 )
- {
- iQueue->ReturnBlock(iBlock);
- iBlock = 0;
- }
- }
-
- // If we are at the start of a block, check if it begins with a PSC
- if ( iBlockPos == 0 )
- {
- if ( (iBlock->Length() > 2 + offset) &&
- ( ((*iBlock)[0+offset] == 0) && ((*iBlock)[1+offset] == 0) && (((*iBlock)[2+offset] & 0xfc) == 0x80) ) )
- {
- gotPSC = ETrue;
- iCurrentFrameLength = iDataLength; // timestamps not copied to buffer
-
- if (iTiming == ETimeStamp)
- {
- iBlockPos += offset;
- }
- }
- else
- {
- PRINT((_L("CVideoProcessor::ReadH263Frame() - no PSC in the start of the buffer")))
- if (iMonitor)
- iMonitor->Error( KErrCorrupt );
- return EFalse;
- }
- }
-
- // If we still have data in our current block, copy it to the buffer
- // Make sure we have enough space
- TUint copyBytes = iBlock->Length() - iBlockPos;
- if (copyBytes)
- {
- while (iBufferLength < (iDataLength + copyBytes))
- {
- // New size is 3/2ths of the old size, rounded up to the next
- // full kilobyte
- TUint newSize = (3 * iBufferLength) / 2;
- newSize = (newSize + 1023) & (~1023);
-
- TUint8* tmp = (TUint8*) User::ReAlloc(iDataBuffer, newSize);
- if (!tmp)
- {
- if (iMonitor)
- iMonitor->Error(KErrNoMemory);
- return EFalse;
- }
- iDataBuffer = tmp;
- iBufferLength = newSize;
- }
- Mem::Copy(&iDataBuffer[iDataLength], iBlock->Ptr() + iBlockPos,
- copyBytes);
- iBlockPos += copyBytes;
- iDataLength += copyBytes;
- }
-
- // OK, block used, throw it away
- VDASSERT(iBlock->Length() == (TInt)iBlockPos,16);
- iQueue->ReturnBlock(iBlock);
- iBlock = 0;
- }
-
- return ETrue;
-}
-
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::ReadMPEG4Frame
-// Reads a MPEG-4 frame from input queue to internal buffer
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TBool CVideoProcessor::ReadMPEG4Frame()
-{
-
- VDASSERT( (iDataFormat == EDataMPEG4 && iTiming == ETimeStamp), 17 );
-
- // The following code assumes that there is one complete video frame
- // in each input block. This is true for 3GP input streams.
-
- // get a new block if we don't have one
- while (!iBlock)
- {
- if ((iBlock = iQueue->ReadBlock()) == NULL)
- return EFalse;
-
- iBlockPos = 0;
- // Return empty blocks immediately
- if (iBlock->Length() == 0)
- {
- iQueue->ReturnBlock(iBlock);
- iBlock = 0;
- }
- }
-
- // If we are at the start of a block, save timestamp
- if (iBlockPos == 0)
- {
- //TUint* p = (TUint*)iBlock->Ptr();
- //AI: iRenderFrameTime = TInt64( (TUint)((*p)*1000) );
- iBlockPos += 4; // skip timestamp
- }
-
- if (iFirstRead)
- {
- // allocate buffer for header
- VDASSERT(!iDecoderSpecificInfo, 160);
- iDecoderSpecificInfo = (HBufC8*) HBufC8::New(iProcessor->GetDecoderSpecificInfoSize());
- if (!iDecoderSpecificInfo)
- {
- iMonitor->Error(KErrNoMemory);
- return EFalse;
- }
-
- TPtr8 ptr(iDecoderSpecificInfo->Des());
-
- // first copy already read bytes from iDataBuffer
- ptr.Copy(iDataBuffer, iDataLength);
-
- TInt copyNow = iProcessor->GetDecoderSpecificInfoSize() - iDataLength;
- iDataLength = 0;
-
- // then copy the rest from input buffer
- ptr.Append(iBlock->Ptr() + iBlockPos, copyNow);
- iBlockPos += copyNow;
- iDecoderSpecificInfoSent = EFalse;
-
- iFirstRead = EFalse;
-
- }
-
- TUint copyBytes = iBlock->Length() - iBlockPos;
- if (copyBytes)
- {
- // Make sure we have enough space
- // +4 is for inserting a start code at the end of the frame
- while (iBufferLength < (iDataLength + copyBytes + 4))
- {
- // New size is 3/2ths of the old size, rounded up to the next
- // full kilobyte
- TUint newSize = (3 * iBufferLength) / 2;
- newSize = (newSize + 1023) & (~1023);
- TUint8* tmp = (TUint8*) User::ReAlloc(iDataBuffer, newSize);
- if (!tmp)
- {
- if (iMonitor)
- iMonitor->Error(KErrNoMemory);
- return EFalse;
- }
- iDataBuffer = tmp;
- iBufferLength = newSize;
- }
- Mem::Copy(&iDataBuffer[iDataLength], iBlock->Ptr() + iBlockPos,
- copyBytes);
- iBlockPos += copyBytes;
- iDataLength += copyBytes;
- }
-
- // OK, block used, throw it away
- VDASSERT((iBlock->Length() == (TInt)iBlockPos),18);
- iQueue->ReturnBlock(iBlock);
- iBlock = 0;
-
- // check for VOS end code
- if ( (iDataBuffer[0] == 0 ) && (iDataBuffer[1] == 0 ) &&
- (iDataBuffer[2] == 0x01) && (iDataBuffer[3] == 0xb1) )
- return EFalse;
-
- // insert VOP start code at the end, the decoder needs it
- iDataBuffer[iDataLength++] = 0;
- iDataBuffer[iDataLength++] = 0;
- iDataBuffer[iDataLength++] = 0x01;
- iDataBuffer[iDataLength++] = 0xb6;
- iCurrentFrameLength = iDataLength;
-
- // we have a complete frame
- return ETrue;
-
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::ReadAVCFrame
-// Reads an AVC frame from input queue to internal buffer
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TBool CVideoProcessor::ReadAVCFrame()
-{
-
- VDASSERT( iDataFormat == EDataAVC, 17 );
-
- // get a new block if we don't have one
- while (!iBlock)
- {
- if ((iBlock = iQueue->ReadBlock()) == NULL)
- return EFalse;
-
- iBlockPos = 0;
- // Return empty blocks immediately
- if (iBlock->Length() == 0)
- {
- iQueue->ReturnBlock(iBlock);
- iBlock = 0;
- }
- }
-
- // skip 4 bytes for the timestamp
- TInt skip = 4;
-// TInt numSPS = 0;
-// TInt numPPS = 0;
-
- // set this to point to the start of frame length field
- TUint8* frameLenPtr = const_cast<TUint8*>(iBlock->Ptr()) + skip;
- // how much space needed for frame data
- TInt frameLen = 0;
-
- TInt totalFrameLen = iBlock->Length() - skip;
-
- if (iFirstRead)
- {
- TInt index = skip + 4; // Skip timestamp + version etc.
- TUint8* temp = const_cast<TUint8*>(iBlock->Ptr());
-
- // get no. bytes used for length
- iFrameLengthBytes = ( temp[index] & 0x3 ) + 1;
-
- // save DCR
- VDASSERT(!iDecoderSpecificInfo, 160);
-
- iDecoderSpecificInfo = (HBufC8*) HBufC8::New(iProcessor->GetDecoderSpecificInfoSize());
- if (!iDecoderSpecificInfo)
- {
- iMonitor->Error(KErrNoMemory);
- return EFalse;
- }
-
- TPtr8 ptr(iDecoderSpecificInfo->Des());
- ptr.Copy(iBlock->Ptr() + skip, iProcessor->GetDecoderSpecificInfoSize());
- iDecoderSpecificInfoSent = EFalse;
-
- // advance pointer over info to point to length field
- frameLenPtr += iProcessor->GetDecoderSpecificInfoSize();
-
- // add to frame len. since it is used to calculate the minimum buffer size
- //frameLen += iProcessor->GetDecoderSpecificInfoSize();
-
- totalFrameLen -= iProcessor->GetDecoderSpecificInfoSize();
- skip += iProcessor->GetDecoderSpecificInfoSize();
-
- iFirstRead = EFalse;
- }
-
-
-
- TInt numSliceNalUnits = 0;
- while (frameLen < totalFrameLen)
- {
- TInt nalLen = 0;
- switch (iFrameLengthBytes)
- {
- case 1:
- nalLen = frameLenPtr[0] + 1; // +1 for length field
- break;
-
- case 2:
- nalLen = (frameLenPtr[0] << 8) + frameLenPtr[1] + 2; // +2 for length field
- break;
-
- case 3:
- nalLen = (frameLenPtr[0] << 16) + (frameLenPtr[1] << 8) +
- frameLenPtr[2] + 3; // +3 for length field
- break;
-
- case 4:
- nalLen = (frameLenPtr[0] << 24) + (frameLenPtr[1] << 16) +
- (frameLenPtr[2] << 8) + frameLenPtr[3] + 4; // +4 for length field
- break;
-
- default:
- if (iMonitor)
- iMonitor->Error(KErrCorrupt);
- return EFalse;
- }
- frameLenPtr += nalLen;
- frameLen += nalLen;
- numSliceNalUnits++;
- }
-
- if ( iFrameLengthBytes != 4 )
- frameLen += numSliceNalUnits * ( (iFrameLengthBytes == 1) ? 3 : 2 );
-
- // reserve space for alignment
- TInt addBytes = (frameLen % 4 != 0) * ( 4 - (frameLen % 4) );
-
- // reserve space for slice NAL unit offset and size fields
- addBytes += (numSliceNalUnits * 8);
-
- // reserve space for number of NAL units (4)
- addBytes += 4;
-
- // Make sure we have enough space
- while (iBufferLength < (iDataLength + frameLen + addBytes))
- {
- // New size is 3/2ths of the old size, rounded up to the next
- // full kilobyte
- TUint newSize = (3 * iBufferLength) / 2;
- newSize = (newSize + 1023) & (~1023);
- TUint8* tmp = (TUint8*) User::ReAlloc(iDataBuffer, newSize);
- if (!tmp)
- {
- iMonitor->Error(KErrNoMemory);
- return EFalse;
- }
-
- iDataBuffer = tmp;
- iBufferLength = newSize;
- }
-
- iBlockPos += skip;
-
- if (iFrameLengthBytes == 4)
- {
- // just copy directly, no need to change length field
- Mem::Copy(&iDataBuffer[iDataLength], iBlock->Ptr() + skip, frameLen);
- iDataLength += frameLen;
- iBlockPos += frameLen;
- }
- else
- {
- // have to change length field for each NAL
- TUint8* srcPtr = const_cast<TUint8*>(iBlock->Ptr()) + skip;
- while (numSliceNalUnits--)
- {
- // read length
- TInt nalLen = 0;
- switch (iFrameLengthBytes)
- {
- case 1:
- nalLen = srcPtr[0];
- srcPtr += 1; // skip length field
- iBlockPos += 1;
- break;
-
- case 2:
- nalLen = (srcPtr[0] << 8) + srcPtr[1];
- srcPtr += 2; // skip length field
- iBlockPos += 2;
- break;
-
- case 3:
- nalLen = (srcPtr[0] << 16) + (srcPtr[1] << 8) + srcPtr[2];
- srcPtr += 3; // skip length field
- iBlockPos += 3;
- break;
-
- default:
- if (iMonitor)
- iMonitor->Error(KErrCorrupt);
- return EFalse;
- }
-
- // code length with 4 bytes
- iDataBuffer[iDataLength] = TUint8((nalLen >> 24) & 0xff);
- iDataBuffer[iDataLength + 1] = TUint8((nalLen >> 16) & 0xff);
- iDataBuffer[iDataLength + 2] = TUint8((nalLen >> 8) & 0xff);
- iDataBuffer[iDataLength + 3] = TUint8(nalLen & 0xff);
- iDataLength += 4;
- // copy NAL data
- Mem::Copy(&iDataBuffer[iDataLength], srcPtr, nalLen);
- iDataLength += nalLen;
- srcPtr += nalLen;
- iBlockPos += nalLen;
- }
- }
-
- // OK, block used, throw it away
- VDASSERT((iBlock->Length() == (TInt)iBlockPos),18);
- iQueue->ReturnBlock(iBlock);
- iBlock = 0;
-
- iCurrentFrameLength = iDataLength;
-
- // we have a complete frame
- return ETrue;
-
-}
-
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::DetermineClipTransitionParameters
-// Sets transition frame parameters
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TInt CVideoProcessor::DetermineClipTransitionParameters(TInt& aTransitionEffect,
- TInt& aStartOfClipTransition,
- TInt& aEndOfClipTransition,
- TTransitionColor& aStartTransitionColor,
- TTransitionColor& aEndTransitionColor)
-{
- TInt error=KErrNone;
- // find if transition effect is to be applied
- TInt numberOfVideoClips = iProcessor->GetNumberOfVideoClips();
- TInt videoClipNumber = iProcessor->GetVideoClipNumber();
- TVedStartTransitionEffect startTransitionEffect = iProcessor->GetStartTransitionEffect();
- TVedEndTransitionEffect endTransitionEffect = iProcessor->GetEndTransitionEffect();
- TVedMiddleTransitionEffect middleTransitionEffect = iProcessor->GetMiddleTransitionEffect();
- TVedMiddleTransitionEffect previousMiddleTransitionEffect = iProcessor->GetPreviousMiddleTransitionEffect();
-
- // is transition effect to be applied anywhere in the movie?
- if(startTransitionEffect==EVedStartTransitionEffectNone &&
- middleTransitionEffect==EVedMiddleTransitionEffectNone &&
- endTransitionEffect==EVedEndTransitionEffectNone &&
- previousMiddleTransitionEffect==EVedMiddleTransitionEffectNone)
- aTransitionEffect=0;
- else
- aTransitionEffect=1;
- // where is the transition effect to be applied - beginning, end or both?
- if(aTransitionEffect)
- {
- // if first video clip
- if(videoClipNumber==0)
- {
- switch(startTransitionEffect)
- {
- default:
- case EVedStartTransitionEffectNone:
- case EVedStartTransitionEffectLast:
- aStartOfClipTransition=0;
- aStartTransitionColor = EColorNone;
- break;
- case EVedStartTransitionEffectFadeFromBlack:
- aStartOfClipTransition=1;
- aStartTransitionColor = EColorBlack;
- break;
- case EVedStartTransitionEffectFadeFromWhite:
- aStartOfClipTransition=1;
- aStartTransitionColor = EColorWhite;
- break;
- }
- // do we need transition at the end of this clip?
- if(videoClipNumber==numberOfVideoClips-1) // last clip?
- {
- switch(endTransitionEffect)
- {
- default:
- case EVedEndTransitionEffectNone:
- case EVedEndTransitionEffectLast:
- aEndOfClipTransition=0;
- aEndTransitionColor = EColorNone;
- break;
- case EVedEndTransitionEffectFadeToBlack:
- aEndOfClipTransition=1;
- aEndTransitionColor = EColorBlack;
- break;
- case EVedEndTransitionEffectFadeToWhite:
- aEndOfClipTransition=1;
- aEndTransitionColor = EColorWhite;
- break;
- }
- }
- else // middle clip
- {
- switch(middleTransitionEffect)
- {
- default:
- case EVedMiddleTransitionEffectNone:
- case EVedMiddleTransitionEffectLast:
- aEndOfClipTransition=0;
- aEndTransitionColor = EColorNone;
- break;
- case EVedMiddleTransitionEffectDipToBlack:
- aEndOfClipTransition=1;
- aEndTransitionColor = EColorBlack;
- break;
- case EVedMiddleTransitionEffectDipToWhite:
- aEndOfClipTransition=1;
- aEndTransitionColor = EColorWhite;
- break;
- //change
- case EVedMiddleTransitionEffectCrossfade:
- aEndOfClipTransition=TInt(EVedMiddleTransitionEffectCrossfade);
- aEndTransitionColor = EColorTransition;
- break;
- case EVedMiddleTransitionEffectWipeLeftToRight:
- aEndOfClipTransition=TInt(EVedMiddleTransitionEffectWipeLeftToRight);
- aEndTransitionColor = EColorTransition;
- break;
- case EVedMiddleTransitionEffectWipeRightToLeft:
- aEndOfClipTransition=TInt(EVedMiddleTransitionEffectWipeRightToLeft);
- aEndTransitionColor = EColorTransition;
- break;
- case EVedMiddleTransitionEffectWipeTopToBottom:
- aEndOfClipTransition=TInt(EVedMiddleTransitionEffectWipeTopToBottom);
- aEndTransitionColor = EColorTransition;
- break;
- case EVedMiddleTransitionEffectWipeBottomToTop:
- aEndOfClipTransition=TInt(EVedMiddleTransitionEffectWipeBottomToTop);
- aEndTransitionColor = EColorTransition;
- break;
- }
- }
- }
- // else its the middle or last clip
- else
- {
- // do we need transition at the beginning of this clip?
- switch(previousMiddleTransitionEffect)
- {
- default:
- case EVedMiddleTransitionEffectNone:
- case EVedMiddleTransitionEffectLast:
- aStartOfClipTransition=0;
- aStartTransitionColor = EColorNone;
- break;
- case EVedMiddleTransitionEffectDipToBlack:
- aStartOfClipTransition=1;
- aStartTransitionColor = EColorBlack;
- break;
- case EVedMiddleTransitionEffectDipToWhite:
- aStartOfClipTransition=1;
- aStartTransitionColor = EColorWhite;
- break;
-
- case EVedMiddleTransitionEffectCrossfade:
- aStartOfClipTransition=TInt(EVedMiddleTransitionEffectCrossfade);
- aStartTransitionColor = EColorTransition;
- break;
- case EVedMiddleTransitionEffectWipeLeftToRight:
- aStartOfClipTransition=TInt(EVedMiddleTransitionEffectWipeLeftToRight);
- aStartTransitionColor = EColorTransition;
- break;
- case EVedMiddleTransitionEffectWipeRightToLeft:
- aStartOfClipTransition=TInt(EVedMiddleTransitionEffectWipeRightToLeft);
- aStartTransitionColor = EColorTransition;
- break;
- case EVedMiddleTransitionEffectWipeTopToBottom:
- aStartOfClipTransition=TInt(EVedMiddleTransitionEffectWipeTopToBottom);
- aStartTransitionColor = EColorTransition;
- break;
- case EVedMiddleTransitionEffectWipeBottomToTop:
- aStartOfClipTransition=TInt(EVedMiddleTransitionEffectWipeBottomToTop);
- aStartTransitionColor = EColorTransition;
- break;
- }
- // do we need transition at the end of this clip?
- if(videoClipNumber==numberOfVideoClips-1) // last clip?
- {
- switch(endTransitionEffect)
- {
- default:
- case EVedEndTransitionEffectNone:
- case EVedEndTransitionEffectLast:
- aEndOfClipTransition=0;
- aEndTransitionColor = EColorNone;
- break;
- case EVedEndTransitionEffectFadeToBlack:
- aEndOfClipTransition=1;
- aEndTransitionColor = EColorBlack;
- break;
- case EVedEndTransitionEffectFadeToWhite:
- aEndOfClipTransition=1;
- aEndTransitionColor = EColorWhite;
- break;
- }
- }
- else // middle clip
- {
- switch(middleTransitionEffect)
- {
- default:
- case EVedMiddleTransitionEffectNone:
- case EVedMiddleTransitionEffectLast:
- aEndOfClipTransition=0;
- aEndTransitionColor = EColorNone;
- break;
- case EVedMiddleTransitionEffectDipToBlack:
- aEndOfClipTransition=1;
- aEndTransitionColor = EColorBlack;
- break;
- case EVedMiddleTransitionEffectDipToWhite:
- aEndOfClipTransition=1;
- aEndTransitionColor = EColorWhite;
- break;
- //change
- case EVedMiddleTransitionEffectCrossfade:
- aEndOfClipTransition=TInt(EVedMiddleTransitionEffectCrossfade);
- aEndTransitionColor = EColorTransition;
- break;
- case EVedMiddleTransitionEffectWipeLeftToRight:
- aEndOfClipTransition=TInt(EVedMiddleTransitionEffectWipeLeftToRight);
- aEndTransitionColor = EColorTransition;
- break;
- case EVedMiddleTransitionEffectWipeRightToLeft:
- aEndOfClipTransition=TInt(EVedMiddleTransitionEffectWipeRightToLeft);
- aEndTransitionColor = EColorTransition;
- break;
- case EVedMiddleTransitionEffectWipeTopToBottom:
- aEndOfClipTransition=TInt(EVedMiddleTransitionEffectWipeTopToBottom);
- aEndTransitionColor = EColorTransition;
- break;
- case EVedMiddleTransitionEffectWipeBottomToTop:
- aEndOfClipTransition=TInt(EVedMiddleTransitionEffectWipeBottomToTop);
- aEndTransitionColor = EColorTransition;
- break;
- }
- }
- }
- }
- return error;
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::GetNumberOfTransitionFrames
-// Calculate the number of transition frames
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::GetNumberOfTransitionFrames(TTimeIntervalMicroSeconds aStartCutTime,
- TTimeIntervalMicroSeconds aEndCutTime)
-{
-
- TInt startFrameIndex = iProcessor->GetVideoFrameIndex(aStartCutTime);
- // the following is because binary search gives us frame with timestamp < startCutTime
- // this frame would be out of range for movie
- if(startFrameIndex > 0 && startFrameIndex < iNumberOfFrames-1)
- startFrameIndex++;
- TInt endFrameIndex = iProcessor->GetVideoFrameIndex(aEndCutTime);
- // adjust frame indices for cut video clip
- startFrameIndex -= iProcessor->GetStartFrameIndex();
- endFrameIndex -= iProcessor->GetStartFrameIndex();
- if(startFrameIndex < 0)
- startFrameIndex = 0;
- if(endFrameIndex < 0)
- endFrameIndex = 0;
- if(endFrameIndex<startFrameIndex)
- endFrameIndex = startFrameIndex;
-
- // determine the total number of included frames in the clip
- iNumberOfIncludedFrames = endFrameIndex-startFrameIndex+1;
-
- // make sure there are enough frames to apply transition
- // for transition at both ends
- if(iStartOfClipTransition && iEndOfClipTransition)
- {
-
- if ( iStartTransitionColor == EColorTransition &&
- iEndTransitionColor == EColorTransition )
- {
- iStartNumberOfTransitionFrames >>= 1;
-
- // if there are not enough frames saved from previous
- // clip, the transition must be shortened accordingly
- if (iProcessor->GetNumberOfSavedFrames() < iStartNumberOfTransitionFrames)
- iStartNumberOfTransitionFrames = iProcessor->GetNumberOfSavedFrames();
-
- iEndNumberOfTransitionFrames >>= 1;
- if ( iNumberOfIncludedFrames < (iStartNumberOfTransitionFrames + iEndNumberOfTransitionFrames) )
- {
- iStartNumberOfTransitionFrames = iNumberOfIncludedFrames >> 1;
- iEndNumberOfTransitionFrames = iNumberOfIncludedFrames - iStartNumberOfTransitionFrames;
- }
- }
- else
- {
- if ( iStartTransitionColor == EColorTransition )
- {
- iStartNumberOfTransitionFrames >>= 1;
-
- // if there are not enough frames saved from previous
- // clip, the transition must be shortened accordingly
- if (iProcessor->GetNumberOfSavedFrames() < iStartNumberOfTransitionFrames)
- iStartNumberOfTransitionFrames = iProcessor->GetNumberOfSavedFrames();
- }
-
- if ( iEndTransitionColor == EColorTransition )
- iEndNumberOfTransitionFrames >>= 1;
-
- if ( iNumberOfIncludedFrames < (iStartNumberOfTransitionFrames + iEndNumberOfTransitionFrames) )
- {
- if ( iStartTransitionColor == EColorTransition )
- {
- if ( ( iNumberOfIncludedFrames >> 1 ) > iStartNumberOfTransitionFrames )
- {
- iEndNumberOfTransitionFrames = iNumberOfIncludedFrames - iStartNumberOfTransitionFrames;
- }
- else
- {
- iStartNumberOfTransitionFrames = iNumberOfIncludedFrames >> 1;
- iEndNumberOfTransitionFrames = iNumberOfIncludedFrames - iStartNumberOfTransitionFrames;
- }
- }
- else if ( iEndTransitionColor == EColorTransition )
- {
- if ( ( iNumberOfIncludedFrames >> 1 ) > iEndNumberOfTransitionFrames )
- {
- iStartNumberOfTransitionFrames = iNumberOfIncludedFrames - iEndNumberOfTransitionFrames;
- }
- else
- {
- iStartNumberOfTransitionFrames = iNumberOfIncludedFrames >> 1;
- iEndNumberOfTransitionFrames = iNumberOfIncludedFrames - iStartNumberOfTransitionFrames;
- }
- }
- else
- {
- iStartNumberOfTransitionFrames = iNumberOfIncludedFrames >> 1;
- iEndNumberOfTransitionFrames = iNumberOfIncludedFrames - iStartNumberOfTransitionFrames;
- }
- }
- }
- }
- // if transition is at one end only
- else
- {
- if ( iStartOfClipTransition )
- {
- iEndNumberOfTransitionFrames = 0;
- if ( iStartTransitionColor == EColorTransition )
- {
- iStartNumberOfTransitionFrames >>= 1;
-
- // if there are not enough frames saved from previous
- // clip, the transition must be shortened accordingly
- if (iProcessor->GetNumberOfSavedFrames() < iStartNumberOfTransitionFrames)
- iStartNumberOfTransitionFrames = iProcessor->GetNumberOfSavedFrames();
- }
-
- if ( iNumberOfIncludedFrames < iStartNumberOfTransitionFrames )
- {
- iStartNumberOfTransitionFrames = iNumberOfIncludedFrames;
- }
- }
- else
- {
- iStartNumberOfTransitionFrames = 0;
- if ( iEndTransitionColor == EColorTransition )
- {
- iEndNumberOfTransitionFrames >>= 1;
- }
- if ( iNumberOfIncludedFrames < iEndNumberOfTransitionFrames )
- {
- iEndNumberOfTransitionFrames = iNumberOfIncludedFrames;
- }
- }
- }
- // fetch the last Intra before transition begins.
- // should be done after the cutting as well.
-
- iLastIntraFrameBeforeTransition=0;
- if(iNumberOfIncludedFrames > 2) //so that we could loop to find the last intra.
- {
- TInt i;
- TInt j=iProcessor->GetStartFrameIndex(); // processor needs frame index from beginning of clip
- for(i=endFrameIndex-iEndNumberOfTransitionFrames; i>=startFrameIndex;i--)
- {
- if(iProcessor->GetVideoFrameType(i+j) == 1) // absolute index needed here!
- {
- iLastIntraFrameBeforeTransition=i;
- break;
- }
- }
- }
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::SetTransitionFrameParams
-// Set parameters for a transition frame
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::SetTransitionFrameParams(TInt aIncludedFrameNumber, TBool& aDecodeFrame)
-{
-
- // if transition is to be applied at the beginning of the clip
- if(iStartOfClipTransition)
- {
- iFirstFrameAfterTransition = EFalse;
- // this is for start-of-clip transition
- if(aIncludedFrameNumber < iStartNumberOfTransitionFrames)
- {
- // if its first transition frame
- if(aIncludedFrameNumber == 0)
- {
- iFirstTransitionFrame = 1;
- iTransitionFrameNumber = 0;
- }
- else
- {
- iTransitionFrameNumber++;
- }
-
- if ( iStartTransitionColor == EColorTransition )
- {
- // ignore this transition if the previous clip has less transition frames
- // than this clip's transition frames
- if ( iTransitionFrameNumber < ( iProcessor->NumberOfTransition() - iTransitionFrameNumber ) )
- {
- iTransitionFrame = 1;
- iTransitionPosition = EPositionStartOfClip;
- aDecodeFrame = ETrue;
- iTransitionColor = iStartTransitionColor;
- }
- else
- {
- iPreviousFrameIncluded = EFalse;
- }
- }
- else
- {
- iTransitionFrame = 1;
- iTransitionPosition = EPositionStartOfClip;
- aDecodeFrame = EFalse;
- iTransitionColor = iStartTransitionColor;
- }
-
- }
- else
- {
- // if this is first frame after transition, we need to encode it as intra
- // treat/simulate it as if its the start of the cut point.
- if(aIncludedFrameNumber == iStartNumberOfTransitionFrames)
- {
- iFirstFrameAfterTransition = ETrue;
- iPreviousFrameIncluded = EFalse;
- }
- }
- }
-
- // if transition is to be applied at the end of the clip
- if(iEndOfClipTransition && iTransitionFrame == 0)
- {
- // this is for end-of-clip transition
- if(aIncludedFrameNumber >= iNumberOfIncludedFrames - iEndNumberOfTransitionFrames)
- {
- // if its first transition frame
- if(aIncludedFrameNumber == iNumberOfIncludedFrames - iEndNumberOfTransitionFrames)
- {
- iFirstTransitionFrame = 1;
- iTransitionFrameNumber = 0;
- }
- else
- {
- iTransitionFrameNumber++;
- }
-
- if ( iEndTransitionColor == EColorTransition )
- {
- // get the next clip's start transition information
- GetNextClipTransitionInfo();
- // if next clip's start transition number is less than current clip's
- // end transition number, then DO NOT treat current frame as the
- // the transition frame
- if ( ( iEndNumberOfTransitionFrames - iTransitionFrameNumber ) <= iNextTransitionNumber )
- {
- iTransitionFrame = 1;
- iTransitionPosition = EPositionEndOfClip;
- aDecodeFrame = ETrue;
- iTransitionColor = iEndTransitionColor;
- }
- }
- else
- {
- iTransitionFrame = 1;
- iTransitionPosition = EPositionEndOfClip;
- aDecodeFrame = EFalse;
- iTransitionColor = iEndTransitionColor;
- }
- }
- else
- {
- // if this is first frame, we need to start decoding from here
- // treat/simulate it as if its the nearest preceding intra frame.
- if(iFrameNumber >= iLastIntraFrameBeforeTransition)
- aDecodeFrame = ETrue;
-
- // In AVC case, if there is also starting transition, decode
- // all frames after that since frame numbering must be consistent
- // for AVC decoding to work
- if (iDataFormat == EDataAVC && iStartOfClipTransition)
- aDecodeFrame = ETrue;
-
- } // end-of-clip transition
- }
-
-}
-
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::ApplyFadingTransitionEffect
-// Applies fading transition effect for a YUV frame
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-
-void CVideoProcessor::ApplyFadingTransitionEffect(TUint8* aYUVPtr,
- TTransitionPosition aTransitionPosition,
- TTransitionColor aTransitionColor,
- TInt aTransitionFramenumber)
-{
- TInt i;
-
- TSize movieSize = iProcessor->GetMovieResolution();
- TInt yLength = movieSize.iWidth * movieSize.iHeight;
-
- TInt uLength = yLength>>2;
- TUint8* yFrame = (TUint8*)aYUVPtr;
- TUint8* uFrame = (TUint8*)(yFrame+yLength);
- TUint8* vFrame = (TUint8*)(uFrame+uLength);
- TInt position;
- TChar chr;
- TInt value;
- TPtr8 ptr(0,0);
-
- // look-up tables to avoid floating point operations due to fractional weighting
- // corresponding to 0.1, 26 values quantized to 8
- const TUint8 quantTable1[8] = {
- 4, 7, 10, 13, 16, 19, 22, 24 };
- // corresponding to 0.2, 52 values quantized to 16
- const TUint8 quantTable2[16] = {
- 4, 8, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 50 };
- // corresponding to 0.3, 77 values quantized to 16
- const TUint8 quantTable3[16] = {
- 5, 10, 15, 20, 24, 29, 33, 38, 42, 47, 51, 56, 61, 66, 71, 75 };
- // corresponding to 0.4, 103 values quantized to 32
- const TUint8 quantTable4[32] = {
- 5, 10, 14, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54,
- 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 101 };
- // corresponding to 0.5, 128 values quantized to 32
- const TUint8 quantTable5[32] = {
- 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63,
- 67, 71, 75, 79, 83, 87, 91, 95, 99, 103, 107, 111, 115, 119, 123, 126 };
- // corresponding to 0.6, 154 values quantized to 32
- const TUint8 quantTable6[32] = {
- 5, 13, 20, 27, 32, 36, 41, 45, 50, 54, 59, 63, 68, 72, 77, 81,
- 86, 90, 95, 99, 103, 108, 112, 117, 121, 126, 130, 135, 139, 144, 148, 152 };
- // corresponding to 0.7, 179 values quantized to 64
- const TUint8 quantTable7[64] = {
- 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50,
- 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98,
- 101, 104, 107, 110, 113, 116, 119, 122, 125, 128, 131, 134, 137, 140, 143, 146,
- 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 178 };
- // corresponding to 0.8, 204 values quantized to 64
- const TUint8 quantTable8[64] = {
- 5, 10, 15, 20, 25, 29, 33, 36, 40, 42, 45, 48, 51, 54, 57, 60,
- 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108,
- 111, 114, 117, 120, 123, 126, 129, 132, 135, 138, 141, 144, 147, 150, 153, 156,
- 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, 192, 195, 198, 201, 203 };
- // corresponding to 0.9, 230 values quantized to 64
- const TUint8 quantTable9[64] = {
- 5, 10, 15, 19, 23, 26, 30, 33, 37, 40, 44, 47, 51, 54, 58, 61,
- 65, 68, 72, 75, 79, 82, 86, 89, 93, 96, 100, 103, 107, 110, 114, 117,
- 121, 124, 128, 131, 135, 138, 142, 145, 149, 152, 156, 159, 163, 166, 170, 173,
- 177, 180, 184, 187, 191, 194, 198, 201, 205, 208, 212, 215, 219, 222, 226, 228 };
- const TUint8 indexTable[10]={1,2,3,4,5,6,7,8,9,10};
-
- // figure out if the transition is at the beginning or end of the clip
- TInt index;
- switch(aTransitionPosition)
- {
- case EPositionStartOfClip: // start-of-clip transition
- if( (index = iStartNumberOfTransitionFrames - aTransitionFramenumber-1) < 0 ) index = 0;
- break;
- case EPositionEndOfClip: // end-of-clip transition
- if( (index = aTransitionFramenumber) >= iEndNumberOfTransitionFrames ) index = iEndNumberOfTransitionFrames - 1;
- break;
- default:
- index = 0;
- break;
- }
- position = indexTable[index];
-
- if(aTransitionColor==EColorWhite)
- {
- switch(position) // white
- {
- case 10: // 0% frame1, 100% frame2
- // Y
- value = 254; chr = value;
- ptr.Set(yFrame, yLength, yLength);
- ptr.Fill(chr);
- // U,V
- value = 128; chr = value;
- ptr.Set(uFrame, uLength<<1, uLength<<1);
- ptr.Fill(chr);
- break;
- case 9: // 10% frame1, 90% frame2
- value = quantTable9[63]; // 90% of 254 (white)
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable1[(*yFrame)>>5] + value);
- value = 113; // 90% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable1[(*uFrame)>>5] + value);
- *vFrame = (TUint8)(quantTable1[(*vFrame)>>5] + value);
- }
- break;
- case 8: // 20% frame1, 80% frame2
- value = quantTable8[63]; // 80% of 254 (white)
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable2[(*yFrame)>>4] + value);
- value = 98; // 80% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable2[(*uFrame)>>4] + value);
- *vFrame = (TUint8)(quantTable2[(*vFrame)>>4] + value);
- }
- break;
- case 7: // 30% frame1, 70% frame2
- value = quantTable7[63]; // 70% of 254 (white)
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable3[(*yFrame)>>4] + value);
- value = 86; // 70% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable3[(*uFrame)>>4] + value);
- *vFrame = (TUint8)(quantTable3[(*vFrame)>>4] + value);
- }
- break;
- case 6: // 40% frame1, 60% frame2
- value = quantTable6[31]; // 60% of 254 (white)
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable4[(*yFrame)>>3] + value);
- value = 72; //77; // 60% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable4[(*uFrame)>>3] + value);
- *vFrame = (TUint8)(quantTable4[(*vFrame)>>3] + value);
- }
- break;
- case 5: // 50% frame1, 50% frame2
- value = quantTable5[31]; // 50% of 254 (white)
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable5[(*yFrame)>>3] + value);
- value = 62; // 50% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable5[(*uFrame)>>3] + value);
- *vFrame = (TUint8)(quantTable5[(*vFrame)>>3] + value);
- }
- break;
- case 4: // 60% frame1, 40% frame2
- value = quantTable4[31]; // 40% of 254 (white)
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable6[(*yFrame)>>3] + value);
- value = 44; //51; // 40% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable6[(*uFrame)>>3] + value);
- *vFrame = (TUint8)(quantTable6[(*vFrame)>>3] + value);
- }
- break;
- case 3: // 70% frame1, 30% frame2
- value = quantTable3[15]; // 30% of 254 (white)
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable7[(*yFrame)>>2] + value);
- value = 28; //38; // 30% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable7[(*uFrame)>>2] + value);
- *vFrame = (TUint8)(quantTable7[(*vFrame)>>2] + value);
- }
- break;
- case 2: // 80% frame1, 20% frame2
- value = quantTable2[15]; // 20% of 254 (white)
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable8[(*yFrame)>>2] + value);
- value = 18; //25; // 20% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable8[(*uFrame)>>2] + value);
- *vFrame = (TUint8)(quantTable8[(*vFrame)>>2] + value);
- }
- break;
- case 1: // 90% frame1, 10% frame2
- value = quantTable1[7]; // 10% of 254 (white)
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable9[(*yFrame)>>2] + value);
- value = 8; //13; // 10% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable9[(*uFrame)>>2] + value);
- *vFrame = (TUint8)(quantTable9[(*vFrame)>>2] + value);
- }
- break;
- default: // e.g., 100% frame1, 0% frame2
- break;
- }
- }
- else if(aTransitionColor==EColorBlack) // black
- {
- switch(position)
- {
- case 10: // 0% frame1, 100% frame2
- // Y
- value = 4; chr = value;
- ptr.Set(yFrame, yLength, yLength);
- ptr.Fill(chr);
- // U,V
- value = 128; chr = value;
- ptr.Set(uFrame, uLength<<1, uLength<<1);
- ptr.Fill(chr);
- break;
- case 9: // 10% frame1, 90% frame2
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable1[(*yFrame)>>5]);
- value = 113; // 90% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable1[(*uFrame)>>5] + value);
- *vFrame = (TUint8)(quantTable1[(*vFrame)>>5] + value);
- }
- break;
- case 8: // 20% frame1, 80% frame2
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable2[(*yFrame)>>4]);
- value = 98; // 80% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable2[(*uFrame)>>4] + value);
- *vFrame = (TUint8)(quantTable2[(*vFrame)>>4] + value);
- }
- break;
- case 7: // 30% frame1, 70% frame2
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable3[(*yFrame)>>4]);
- value = 86; // 70% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable3[(*uFrame)>>4] + value);
- *vFrame = (TUint8)(quantTable3[(*vFrame)>>4] + value);
- }
- break;
- case 6: // 40% frame1, 60% frame2
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable4[(*yFrame)>>3]);
- value = 72; //77; // 60% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable4[(*uFrame)>>3] + value);
- *vFrame = (TUint8)(quantTable4[(*vFrame)>>3] + value);
- }
- break;
- case 5: // 50% frame1, 50% frame2
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable5[(*yFrame)>>3]);
- value = 62; // 50% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable5[(*uFrame)>>3] + value);
- *vFrame = (TUint8)(quantTable5[(*vFrame)>>3] + value);
- }
- break;
- case 4: // 60% frame1, 40% frame2
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable6[(*yFrame)>>3]);
- value = 44; //51; // 40% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable6[(*uFrame)>>3] + value);
- *vFrame = (TUint8)(quantTable6[(*vFrame)>>3] + value);
- }
- break;
- case 3: // 70% frame1, 30% frame2
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable7[(*yFrame)>>2]);
- value = 28; //38; // 30% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable7[(*uFrame)>>2] + value);
- *vFrame = (TUint8)(quantTable7[(*vFrame)>>2] + value);
- }
- break;
- case 2: // 80% frame1, 20% frame2
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable8[(*yFrame)>>2]);
- value = 18; //25; // 20% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable8[(*uFrame)>>2] + value);
- *vFrame = (TUint8)(quantTable8[(*vFrame)>>2] + value);
- }
- break;
- case 1: // 90% frame1, 10% frame2
- for(i=0; i<yLength; i++, yFrame++) // Y
- *yFrame = (TUint8)(quantTable9[(*yFrame)>>2]);
- value = 8; //13; // 10% of 128
- for(i=0; i<uLength; i++, uFrame++,vFrame++) // U
- {
- *uFrame = (TUint8)(quantTable9[(*uFrame)>>2] + value);
- *vFrame = (TUint8)(quantTable9[(*vFrame)>>2] + value);
- }
- break;
- default: // e.g., 100% frame1, 0% frame2
- break;
- }
- }
- return;
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::ApplyBlendingTransitionEffect
-// Applies blending transition effect between two YUV frames
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::ApplyBlendingTransitionEffect(TUint8* aYUVPtr1,
- TUint8* aYUVPtr2,
- TInt aRepeatFrame,
- TInt aTransitionFramenumber)
-{
- TInt i;
- TSize tempSize = iProcessor->GetMovieResolution();
-
- TInt yLength = tempSize.iWidth*tempSize.iHeight;
- TInt uLength = yLength>>2;
- TInt yuvLength = yLength + (yLength>>1);
- TUint8* yFrame1 = (TUint8*)aYUVPtr1;
- TUint8* uFrame1 = (TUint8*)(yFrame1+yLength);
- TUint8* vFrame1 = (TUint8*)(uFrame1+uLength);
- TUint8* yFrame2 = (TUint8*)aYUVPtr2;
- TUint8* uFrame2 = (TUint8*)(yFrame2+yLength);
- TUint8* vFrame2 = (TUint8*)(uFrame2+uLength);
- TInt position;
- TPtr8 ptr(0,0);
- const TInt numberOfTables = 10;
-
- // corresponding to 0.1, 26 values quantized to 8
- const TUint8 quantTable1[8] = {
- 4, 7, 10, 13, 16, 19, 22, 24 };
- // corresponding to 0.2, 52 values quantized to 16
- const TUint8 quantTable2[16] = {
- 4, 8, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 50 };
- // corresponding to 0.3, 77 values quantized to 16
- const TUint8 quantTable3[16] = {
- 5, 10, 15, 20, 24, 29, 33, 38, 42, 47, 51, 56, 61, 66, 71, 75 };
- // corresponding to 0.4, 103 values quantized to 32
- const TUint8 quantTable4[32] = {
- 5, 10, 14, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54,
- 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 101 };
- // corresponding to 0.5, 128 values quantized to 32
- const TUint8 quantTable5[32] = {
- 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63,
- 67, 71, 75, 79, 83, 87, 91, 95, 99, 103, 107, 111, 115, 119, 123, 126 };
- // corresponding to 0.6, 154 values quantized to 32
- const TUint8 quantTable6[32] = {
- 5, 13, 20, 27, 32, 36, 41, 45, 50, 54, 59, 63, 68, 72, 77, 81,
- 86, 90, 95, 99, 103, 108, 112, 117, 121, 126, 130, 135, 139, 144, 148, 152 };
- // corresponding to 0.7, 179 values quantized to 64
- const TUint8 quantTable7[64] = {
- 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50,
- 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98,
- 101, 104, 107, 110, 113, 116, 119, 122, 125, 128, 131, 134, 137, 140, 143, 146,
- 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 178 };
- // corresponding to 0.8, 204 values quantized to 64
- const TUint8 quantTable8[64] = {
- 5, 10, 15, 20, 25, 29, 33, 36, 40, 42, 45, 48, 51, 54, 57, 60,
- 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108,
- 111, 114, 117, 120, 123, 126, 129, 132, 135, 138, 141, 144, 147, 150, 153, 156,
- 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, 192, 195, 198, 201, 203 };
- // corresponding to 0.9, 230 values quantized to 64
- const TUint8 quantTable9[64] = {
- 5, 10, 15, 19, 23, 26, 30, 33, 37, 40, 44, 47, 51, 54, 58, 61,
- 65, 68, 72, 75, 79, 82, 86, 89, 93, 96, 100, 103, 107, 110, 114, 117,
- 121, 124, 128, 131, 135, 138, 142, 145, 149, 152, 156, 159, 163, 166, 170, 173,
- 177, 180, 184, 187, 191, 194, 198, 201, 205, 208, 212, 215, 219, 222, 226, 228 };
-
- const TUint8 indexTable[10]={1,2,3,4,5,6,7,8,9,10};
-
- // figure out the position of the index (determines which table to use)
- TInt frameNumber = aTransitionFramenumber;
- if(frameNumber>=iStartNumberOfTransitionFrames) frameNumber=iStartNumberOfTransitionFrames-1;
- TInt index = (frameNumber<<1) + aRepeatFrame;
- if(index>=numberOfTables) index=numberOfTables-1;
- position = indexTable[index];
-
- // calculate new values
- switch(position)
- {
- case 10: // 0% frame1, 100% frame2
- ptr.Set(yFrame1,yuvLength,yuvLength);
- ptr.Copy(yFrame2,yuvLength);
- break;
- case 9: // 10% frame1, 90% frame2
- for(i=0; i<yLength; i++, yFrame1++,yFrame2++) // Y
- *yFrame1 = (TUint8)(quantTable1[(*yFrame1)>>5] + quantTable9[(*yFrame2)>>2]);
- for(i=0; i<uLength; i++, uFrame1++,uFrame2++,vFrame1++,vFrame2++) // U
- {
- *uFrame1 = (TUint8)(quantTable1[(*uFrame1)>>5] + quantTable9[(*uFrame2)>>2] - 10);
- *vFrame1 = (TUint8)(quantTable1[(*vFrame1)>>5] + quantTable9[(*vFrame2)>>2] - 10);
- }
- break;
- case 8: // 20% frame1, 80% frame2
- for(i=0; i<yLength; i++, yFrame1++,yFrame2++) // Y
- *yFrame1 = (TUint8)(quantTable2[(*yFrame1)>>4] + quantTable8[(*yFrame2)>>2]);
- for(i=0; i<uLength; i++, uFrame1++,uFrame2++,vFrame1++,vFrame2++) // U
- {
- *uFrame1 = (TUint8)(quantTable2[(*uFrame1)>>4] + quantTable8[(*uFrame2)>>2] - 15);
- *vFrame1 = (TUint8)(quantTable2[(*vFrame1)>>4] + quantTable8[(*vFrame2)>>2] - 15);
- }
- break;
- case 7: // 30% frame1, 70% frame2
- for(i=0; i<yLength; i++, yFrame1++,yFrame2++) // Y
- *yFrame1 = (TUint8)(quantTable3[(*yFrame1)>>4] + quantTable7[(*yFrame2)>>2]);
- for(i=0; i<uLength; i++, uFrame1++,uFrame2++,vFrame1++,vFrame2++) // U
- {
- *uFrame1 = (TUint8)(quantTable3[(*uFrame1)>>4] + quantTable7[(*uFrame2)>>2] - 15);
- *vFrame1 = (TUint8)(quantTable3[(*vFrame1)>>4] + quantTable7[(*vFrame2)>>2] - 15);
- }
- break;
- case 6: // 40% frame1, 60% frame2
- for(i=0; i<yLength; i++, yFrame1++,yFrame2++) // Y
- *yFrame1 = (TUint8)(quantTable4[(*yFrame1)>>3] + quantTable6[(*yFrame2)>>3]);
- for(i=0; i<uLength; i++, uFrame1++,uFrame2++,vFrame1++,vFrame2++) // U
- {
- *uFrame1 = (TUint8)(quantTable4[(*uFrame1)>>3] + quantTable6[(*uFrame2)>>3] - 10);
- *vFrame1 = (TUint8)(quantTable4[(*vFrame1)>>3] + quantTable6[(*vFrame2)>>3] - 10);
- }
- break;
- case 5: // 50% frame1, 50% frame2
- for(i=0; i<yLength; i++, yFrame1++,yFrame2++) // Y
- *yFrame1 = (TUint8)(quantTable5[(*yFrame1)>>3] + quantTable5[(*yFrame2)>>3]);
- for(i=0; i<uLength; i++, uFrame1++,uFrame2++,vFrame1++,vFrame2++) // U
- {
- *uFrame1 = (TUint8)(quantTable5[(*uFrame1)>>3] + quantTable5[(*uFrame2)>>3] - 5);
- *vFrame1 = (TUint8)(quantTable5[(*vFrame1)>>3] + quantTable5[(*vFrame2)>>3] - 5);
- }
- break;
- case 4: // 60% frame1, 40% frame2
- for(i=0; i<yLength; i++, yFrame1++,yFrame2++) // Y
- *yFrame1 = (TUint8)(quantTable6[(*yFrame1)>>3] + quantTable4[(*yFrame2)>>3]);
- for(i=0; i<uLength; i++, uFrame1++,uFrame2++,vFrame1++,vFrame2++) // U
- {
- *uFrame1 = (TUint8)(quantTable6[(*uFrame1)>>3] + quantTable4[(*uFrame2)>>3] - 10);
- *vFrame1 = (TUint8)(quantTable6[(*vFrame1)>>3] + quantTable4[(*vFrame2)>>3] - 10);
- }
- break;
- case 3: // 70% frame1, 30% frame2
- for(i=0; i<yLength; i++, yFrame1++,yFrame2++) // Y
- *yFrame1 = (TUint8)(quantTable7[(*yFrame1)>>2] + quantTable3[(*yFrame2)>>4]);
- for(i=0; i<uLength; i++, uFrame1++,uFrame2++,vFrame1++,vFrame2++) // U
- {
- *uFrame1 = (TUint8)(quantTable7[(*uFrame1)>>2] + quantTable3[(*uFrame2)>>4] - 8);
- *vFrame1 = (TUint8)(quantTable7[(*vFrame1)>>2] + quantTable3[(*vFrame2)>>4] - 8);
- }
- break;
- case 2: // 80% frame1, 20% frame2
- for(i=0; i<yLength; i++, yFrame1++,yFrame2++) // Y
- *yFrame1 = (TUint8)(quantTable8[(*yFrame1)>>2] + quantTable2[(*yFrame2)>>4]);
- for(i=0; i<uLength; i++, uFrame1++,uFrame2++,vFrame1++,vFrame2++) // U
- {
- *uFrame1 = (TUint8)(quantTable8[(*uFrame1)>>2] + quantTable2[(*uFrame2)>>4] - 8);
- *vFrame1 = (TUint8)(quantTable8[(*vFrame1)>>2] + quantTable2[(*vFrame2)>>4] - 8);
- }
- break;
- case 1: // 90% frame1, 10% frame2
- for(i=0; i<yLength; i++, yFrame1++,yFrame2++) // Y
- *yFrame1 = (TUint8)(quantTable9[(*yFrame1)>>2] + quantTable1[(*yFrame2)>>5]);
- for(i=0; i<uLength; i++, uFrame1++,uFrame2++,vFrame1++,vFrame2++) // U
- {
- *uFrame1 = (TUint8)(quantTable9[(*uFrame1)>>2] + quantTable1[(*uFrame2)>>5] - 5);
- *vFrame1 = (TUint8)(quantTable9[(*vFrame1)>>2] + quantTable1[(*vFrame2)>>5] - 5);
- }
- break;
- default: // e.g., 100% frame1, 0% frame2
- break;
- }
- return;
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::ApplySlidingTransitionEffect
-// Applies sliding transition effect between two YUV frames
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::ApplySlidingTransitionEffect(TUint8* aYUVPtr1,
- TUint8* aYUVPtr2,
- TVedMiddleTransitionEffect aVedMiddleTransitionEffect,
- TInt aRepeatFrame,
- TInt aTransitionFramenumber)
-{
- TInt i;
- TSize tempSize = iProcessor->GetMovieResolution();
- TInt yLength = tempSize.iWidth*tempSize.iHeight;
- TInt uLength = yLength>>2;
- TInt yWidth = tempSize.iWidth;
- TInt uWidth = tempSize.iWidth>>1;
- TInt yHeight = tempSize.iHeight;
- TInt uHeight = tempSize.iHeight>>1;
- TUint8* yFrame1 = (TUint8*)aYUVPtr1;
- TUint8* uFrame1 = (TUint8*)(yFrame1+yLength);
- TUint8* vFrame1 = (TUint8*)(uFrame1+uLength);
- TUint8* yFrame2 = (TUint8*)aYUVPtr2;
- TUint8* uFrame2 = (TUint8*)(yFrame2+yLength);
- TUint8* vFrame2 = (TUint8*)(uFrame2+uLength);
- TPtr8 ptr(0,0);
- TInt offset = 0;
- TInt ySliceWidth = 0;
- TInt uSliceWidth = 0;
- TInt sliceSize = 0;
- TInt frameNumber = (aTransitionFramenumber<<1) + aRepeatFrame;
-
- switch(aVedMiddleTransitionEffect)
- {
- case EVedMiddleTransitionEffectWipeLeftToRight:
- // figure out the amount of data to change
- VDASSERT(iStartNumberOfTransitionFrames,19);
- ySliceWidth = (TInt)((TReal)yWidth * (TReal)(frameNumber+1)/(TReal)(iStartNumberOfTransitionFrames<<1) + 0.5);
- if(ySliceWidth>yWidth) ySliceWidth = yWidth;
- uSliceWidth = ySliceWidth>>1;
- // copy the relevant portions of the image from frame2 to frame1
- // y
- for(i=0; i<yHeight; i++, yFrame1+=yWidth,yFrame2+=yWidth)
- {
- ptr.Set(yFrame1,ySliceWidth,ySliceWidth);
- ptr.Copy(yFrame2,ySliceWidth);
- }
- // u,v
- for(i=0; i<uHeight; i++, uFrame1+=uWidth,uFrame2+=uWidth,vFrame1+=uWidth,vFrame2+=uWidth)
- {
- ptr.Set(uFrame1,uSliceWidth,uSliceWidth);
- ptr.Copy(uFrame2,uSliceWidth);
- ptr.Set(vFrame1,uSliceWidth,uSliceWidth);
- ptr.Copy(vFrame2,uSliceWidth);
- }
- break;
- case EVedMiddleTransitionEffectWipeRightToLeft:
- // figure out the amount of data to change
- VDASSERT(iStartNumberOfTransitionFrames,20);
- ySliceWidth = (TInt)((TReal)yWidth * (TReal)(frameNumber+1)/(TReal)(iStartNumberOfTransitionFrames<<1) + 0.5);
- if(ySliceWidth>yWidth) ySliceWidth = yWidth;
- uSliceWidth = ySliceWidth>>1;
- // evaluate the yuv offsets and new positions to point to in the buffer
- offset = yWidth-ySliceWidth;
- yFrame1+=offset;
- yFrame2+=offset;
- offset = uWidth-uSliceWidth;
- uFrame1+=offset;
- uFrame2+=offset;
- vFrame1+=offset;
- vFrame2+=offset;
- // copy the relevant portions of the image from frame2 to frame1
- // y
- for(i=0; i<yHeight; i++, yFrame1+=yWidth,yFrame2+=yWidth)
- {
- ptr.Set(yFrame1,ySliceWidth,ySliceWidth);
- ptr.Copy(yFrame2,ySliceWidth);
- }
- // u,v
- for(i=0; i<uHeight; i++, uFrame1+=uWidth,uFrame2+=uWidth,vFrame1+=uWidth,vFrame2+=uWidth)
- {
- ptr.Set(uFrame1,uSliceWidth,uSliceWidth);
- ptr.Copy(uFrame2,uSliceWidth);
- ptr.Set(vFrame1,uSliceWidth,uSliceWidth);
- ptr.Copy(vFrame2,uSliceWidth);
- }
- break;
- case EVedMiddleTransitionEffectWipeTopToBottom:
- // figure out the amount of data to change
- VDASSERT(iStartNumberOfTransitionFrames,21);
- ySliceWidth = (TInt)((TReal)yHeight * (TReal)(frameNumber+1)/(TReal)(iStartNumberOfTransitionFrames<<1) + 0.5);
- if(ySliceWidth>yHeight) ySliceWidth = yHeight;
- uSliceWidth = ySliceWidth>>1;
- // copy the relevant portions of the image from frame2 to frame1
- // y
- sliceSize = ySliceWidth * yWidth;
- ptr.Set(yFrame1,sliceSize,sliceSize);
- ptr.Copy(yFrame2,sliceSize);
- // u,v
- sliceSize = uSliceWidth * uWidth;
- ptr.Set(uFrame1,sliceSize,sliceSize);
- ptr.Copy(uFrame2,sliceSize);
- ptr.Set(vFrame1,sliceSize,sliceSize);
- ptr.Copy(vFrame2,sliceSize);
- break;
- case EVedMiddleTransitionEffectWipeBottomToTop:
- // figure out the amount of data to change
- VDASSERT(iStartNumberOfTransitionFrames,22);
- ySliceWidth = (TInt)((TReal)yHeight * (TReal)(frameNumber+1)/(TReal)(iStartNumberOfTransitionFrames<<1) + 0.5);
- if(ySliceWidth>yHeight) ySliceWidth = yHeight;
- uSliceWidth = ySliceWidth>>1;
- // evaluate the yuv offsets and new positions to point to in the buffer
- offset = (yHeight-ySliceWidth) * yWidth;
- yFrame1+=offset;
- yFrame2+=offset;
- offset = (uHeight-uSliceWidth) * uWidth;
- uFrame1+=offset;
- uFrame2+=offset;
- vFrame1+=offset;
- vFrame2+=offset;
- // copy the relevant portions of the image from frame2 to frame1
- // y
- sliceSize = ySliceWidth * yWidth;
- ptr.Set(yFrame1,sliceSize,sliceSize);
- ptr.Copy(yFrame2,sliceSize);
- // u,v
- sliceSize = uSliceWidth * uWidth;
- ptr.Set(uFrame1,sliceSize,sliceSize);
- ptr.Copy(uFrame2,sliceSize);
- ptr.Set(vFrame1,sliceSize,sliceSize);
- ptr.Copy(vFrame2,sliceSize);
- break;
- case EVedMiddleTransitionEffectNone:
- case EVedMiddleTransitionEffectDipToBlack:
- case EVedMiddleTransitionEffectDipToWhite:
- case EVedMiddleTransitionEffectCrossfade:
- case EVedMiddleTransitionEffectLast:
- default:
- break;
- }
- return;
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::ApplySpecialEffect
-// Applies color effect for a YUV frame
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::ApplySpecialEffect(TInt aColorEffect, TUint8* aYUVDataPtr,
- TInt aColorToneU, TInt aColorToneV)
-{
- VDASSERT(aYUVDataPtr,23);
- VDASSERT(iVideoWidth,24);
- VDASSERT(iVideoHeight,25);
- TChar chr;
- TInt value;
- TInt offset;
- TInt length;
- // Values for the U & V Fill parameters
- TInt uFillValue, vFillValue;
- TPtr8 ptr(0,0);
- TSize tempSize = iProcessor->GetMovieResolution();
-
- // asad - check if mpeg4, then change pixel range from (-128,127) to (0,255)
- if (iProcessor->GetOutputVideoType() == EVedVideoTypeMPEG4SimpleProfile)
- {
- // U
- aColorToneU += 128;
- if (aColorToneU<0) aColorToneU = 0;
- if (aColorToneU>255) aColorToneU = 255;
- // V
- aColorToneV += 128;
- if (aColorToneV<0) aColorToneV = 0;
- if (aColorToneV>255) aColorToneV = 255;
- }
- TChar uChr, vChr;
- switch(aColorEffect)
- {
- case 0/*None*/:
- return;
- case 1/*BW*/:
- value = 128;
- chr = value;
- offset = tempSize.iWidth*tempSize.iHeight;
- length = offset>>1; // u,v data length (2*L/2*W/2)
- ptr.Set((TUint8*)(aYUVDataPtr+offset), length, length);
- ptr.Fill((TChar)chr);
- break;
- case 2:
- offset = tempSize.iWidth*tempSize.iHeight;
- length = offset>>2;
- uFillValue = aColorToneU;
- uChr = uFillValue;
- vFillValue = aColorToneV;
- vChr = vFillValue;
-
- ptr.Set((TUint8*)(aYUVDataPtr + offset), length, length);
- ptr.Fill((TChar)uChr);
-
- offset = 1.25 * offset; // For filling the v-value
- ptr.Set((TUint8*)(aYUVDataPtr + offset), length, length);
- ptr.Fill((TChar)vChr);
- break;
- default:
- return;
- }
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::TFrameOperation2TInt
-// Converts frame operation enumeration to int
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TInt CVideoProcessor::TFrameOperation2TInt(TDecoderFrameOperation aFrameOperation)
-{
- switch(aFrameOperation)
- {
- case EDecodeAndWrite:
- return 1;
- case EDecodeNoWrite:
- return 2;
- case EWriteNoDecode:
- return 3;
- case ENoDecodeNoWrite:
- return 4;
- default:
- return KErrGeneral;
- }
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::TColorEffect2TInt
-// Converts color effect enumeration to int
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TInt CVideoProcessor::TColorEffect2TInt(TVedColorEffect aColorEffect)
-{
- switch(aColorEffect)
- {
- case EVedColorEffectNone:
- return 0;
- case EVedColorEffectBlackAndWhite:
- return 1;
- case EVedColorEffectToning:
- return 2;
- default:
- return KErrGeneral;
- }
-}
-
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::InputDataAvailable
-// Overridden CDataProcessor::InputDataAvailable() method
-// Called when new input blocks are available
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::InputDataAvailable(TAny* /*aUserPointer*/)
-{
- PRINT((_L("CVideoProcessor::InputDataAvailable()")));
- // Signal ourselves if we are decoding and a request is not
- // pending:
- if ( iDecoding && !iTranscoderInitPending && !iDecodePending &&
- (iStatus == KRequestPending) )
- {
- PRINT((_L("CVideoProcessor::InputDataAvailable() - complete request")));
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- }
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::StreamEndReached
-// Overridden CDataProcessor::StreamEndReached() method
-// Called when input stream has ended
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-
-void CVideoProcessor::StreamEndReached(TAny* /*aUserPointer*/)
-{
- PRINT((_L("CVideoProcessor::StreamEndReached()")));
- iStreamEnd = ETrue;
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::DoCancel
-// Cancels any asynchronous requests pending.
-//
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::DoCancel()
-{
-
- // Cancel our internal request
- if ( iStatus == KRequestPending )
- {
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrCancel);
- }
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::GetNextClipTransitionInfo
-// Get the start transition info of the next clip.
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-void CVideoProcessor::GetNextClipTransitionInfo()
-{
- if ( iNextTransitionNumber == -1 )
- {
- iNextTransitionNumber = iProcessor->NextClipStartTransitionNumber();
- }
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::DetermineResolutionChange
-// This function checks if the video clip is needed to be resampled
-// (other items were commented in a header).
-// ---------------------------------------------------------
-// Resolution Transcoder, check if this video clip need to be resample
-
-TBool CVideoProcessor::DetermineResolutionChange()
-{
- TSize VideoClipResolution = iProcessor->GetVideoClipResolution();
- TSize MovieResolution = iProcessor->GetMovieResolution();
- if (VideoClipResolution != MovieResolution)
- return ETrue;
- else
- return EFalse;
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::DetermineFrameRateChange
-// This function checks if the frame rate must be changed
-// => clip re-encoded
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TBool CVideoProcessor::DetermineFrameRateChange()
- {
-
- TReal clipFrameRate = iProcessor->GetVideoClipFrameRate();
- TReal movieFrameRate = iProcessor->GetMovieFrameRate();
-
- // Do re-encoding only when reducing frame rate,
- // otherwise we would have to come up with new frames
- if ( movieFrameRate > 0 && clipFrameRate > movieFrameRate )
- return ETrue;
-
- return EFalse;
-
- }
-
-// ---------------------------------------------------------
-// CVideoProcessor::DetermineFrameRateChange
-// This function checks if the bitrate must be changed
-// => clip re-encoded
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TBool CVideoProcessor::DetermineBitRateChange()
- {
-
- // : AVC bitrate transcoding from a higher level
- // to lower if resolution transcoding is not needed
-
- if ( iProcessor->GetMovieVideoBitrate() > 0 ) // movie has bitrate restriction => need to transcode
- return ETrue;
-
- if ( iProcessor->GetOutputVideoType() == EVedVideoTypeH263Profile0Level10 )
- {
- if (iDataFormat == EDataH263)
- {
- if ( (iProcessor->GetCurrentClipVideoType() != EVedVideoTypeH263Profile0Level10) &&
- (iProcessor->GetCurrentClipVideoType() != EVedVideoTypeUnrecognized) )
- return ETrue;
- }
-
- else if (iDataFormat == EDataMPEG4)
- {
- // level 0 and level 1 max bitrate is 64 kb/s
- // others need to be transcoded
- if (iInputMPEG4ProfileLevelId != 8 && iInputMPEG4ProfileLevelId != 1)
- return ETrue;
- }
- }
-
- return EFalse;
-
- }
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::GetFrameDuration
-// Calculates the duration of current frame
-// (other items were commented in a header).
-// ---------------------------------------------------------
-//
-TInt CVideoProcessor::GetFrameDuration(TInt aFrameNumber)
-{
- // calculate frame duration in ticks
- TInt startFrame = iProcessor->GetOutputNumberOfFrames() - iNumberOfFrames;
- TInt absFrameNumber = startFrame + aFrameNumber;
- TInt cur = absFrameNumber;
- TInt next = cur+1;
-
- // frameDuration is in ticks, with timescale of the current input clip
- if(next >= iProcessor->GetOutputNumberOfFrames())
- {
- return I64INT(iProcessor->GetVideoClipDuration() - iProcessor->VideoFrameTimeStamp(cur) );
- }
- else
- {
- return I64INT( iProcessor->VideoFrameTimeStamp(next) - iProcessor->VideoFrameTimeStamp(cur) );
- }
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::CheckVosHeaderL
-// Checks whether the resynch bit is set if set then resets to zero
-// (other items were commented in a header).
-// @return TBool
-// ---------------------------------------------------------
-//
-
-TBool CVideoProcessor::CheckVosHeaderL(TPtrC8& aBuf)
-{
- return iDecoder->CheckVOSHeaderL((TPtrC8&)aBuf);
-}
-
-
-// ---------------------------------------------------------
-// CVideoProcessor::RenderFrame
-// The H.263 decoder calls this function when a decoded
-// frame is available for retrieving
-// @return TInt
-// ---------------------------------------------------------
-//
-TInt CVideoProcessor::RenderFrame(TAny* aFrame)
-{
- iDecoder->FrameRendered(aFrame);
- return KErrNone;
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::MtoTimerElapsed
-// Called when timer has elapsed
-// ---------------------------------------------------------
-//
-void CVideoProcessor::MtoTimerElapsed(TInt aError)
-{
-
- PRINT((_L("CVideoProcessor::MtoTimerElapsed() begin")));
-
- if (aError != KErrNone)
- {
- iMonitor->Error(aError);
- return;
- }
-
- VDASSERT(iFrameInfoArray[0].iEncodeFrame == 1, 110);
-
- // if next frame in encode queue is an intermediate modification frame
- // and modification has not yet been applied, start waiting timer again
- if ( ( (iFrameInfoArray[0].iTransitionFrame == 1) ||
- (iProcessor->GetColorEffect() != EVedColorEffectNone) ) &&
- iFrameInfoArray[0].iModificationApplied == 0 )
- {
- PRINT((_L("CVideoProcessor::MtoTimerElapsed() - modification not done yet, set timer")));
-
- iTimer->SetTimer( TTimeIntervalMicroSeconds32( GetEncodingDelay() ) );
- return;
- }
-
- PRINT((_L("CVideoProcessor::MtoTimerElapsed() - removing pic with ts %d ms"),
- I64INT(iProcessor->GetVideoTimeInMsFromTicks(iFrameInfoArray[0].iTimeStamp, EFalse)) ))
-
- // save frame number to be able to recover in case the frame
- // gets encoded regardless of the delay
- iSkippedFrameNumber = iFrameInfoArray[0].iFrameNumber;
-
- // remove skipped frame from queue
- iFrameInfoArray.Remove(0);
-
- PRINT((_L("CVideoProcessor::MtoTimerElapsed() - %d items in queue"), iFrameInfoArray.Count()));
-
- if (iDecodingSuspended && !iStreamEndRead)
- {
- if (iFrameInfoArray.Count() < iMaxItemsInProcessingQueue && !iDelayedWrite)
- {
- PRINT((_L("CVideoProcessor::MtoTimerElapsed() - Resume decoding")));
- iDecodingSuspended = EFalse;
- // activate object to start decoding
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- return;
- }
- }
-
- if ( !IsEncodeQueueEmpty() )
- {
- // if there are still frames to be encoded, and next one is waiting,
- // set timer again
- if ( IsNextFrameBeingEncoded() )
- {
- if ( !iTimer->IsPending() )
- {
- PRINT((_L("CVideoProcessor::MtoTimerElapsed(), set timer again")));
- iTimer->SetTimer( TTimeIntervalMicroSeconds32( iMaxEncodingDelay ) );
- }
- }
- return;
- }
-
- if (iDelayedWrite)
- {
- PRINT((_L("CVideoProcessor::MtoTimerElapsed(), writing delayed frame")));
- // write delayed frame
- TRAPD( error, WriteDelayedFrameL() );
- if (error != KErrNone)
- {
- iMonitor->Error(aError);
- return;
- }
- }
-
- if ( iStreamEndRead )
- {
- if ( iFrameInfoArray.Count() != 0 )
- {
- // return now if we have read stream end, but there are still frames waiting
- // to be decoded => processing will be completed in MtroPictureFromTranscoder
- PRINT((_L("CVideoProcessor::MtoTimerElapsed(), end read but frames in progress, return")));
- return;
- }
-
- else
- {
- // activate to stop processing
- PRINT((_L("CVideoProcessor::MtoTimerElapsed(), end read and all frames processed, stopping")));
- iProcessingComplete = ETrue;
- }
- }
-
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
- // activate object to continue/end processing
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- PRINT((_L("CVideoProcessor::MtoTimerElapsed() end")));
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::WriteBufferL
-// Called by transcoder to pass an encoded buffer
-// ---------------------------------------------------------
-//
-void CVideoProcessor::WriteBufferL(CCMRMediaBuffer* aBuffer)
-{
- if ( iFrameInfoArray.Count() == 0 )
- {
- PRINT((_L("CVideoProcessor::WriteBufferL() not ready to receive buffer, return")));
- return;
- }
-
- if ( ((iFrameInfoArray[0].iTranscoderMode != EFullWithIM) &&
- (iFrameInfoArray[0].iTranscoderMode != EFull)) ||
- (iFrameInfoArray[0].iEncodeFrame != 1) )
- {
- PRINT((_L("CVideoProcessor::WriteBufferL() encoded picture received but not expected, ignore & return")));
- return;
- }
-
-
- // cancel timer
- iTimer->CancelTimer();
-
- if (aBuffer->Type() == CCMRMediaBuffer::EVideoMPEG4DecSpecInfo)
- {
- // should not happen
- return;
- }
-
- TTimeIntervalMicroSeconds encodedTs = aBuffer->TimeStamp();
-
- PRINT((_L("CVideoProcessor::WriteBufferL(), timestamp %d ms, keyFrame = %d"),
- I64INT( encodedTs.Int64() ) / 1000, aBuffer->RandomAccessPoint() ));
-
- TBool removeItem = ETrue;
- TInt64 timeStamp = 0;
- TInt frameNumber = 0;
-
- while (iFrameInfoArray.Count())
- {
- TTimeIntervalMicroSeconds ts = (iProcessor->GetVideoTimeInMsFromTicks(iFrameInfoArray[0].iTimeStamp, EFalse)) * 1000;
-
- if (ts < encodedTs)
- {
- // a frame has been skipped
- iFrameInfoArray.Remove(0);
- PRINT((_L("CVideoProcessor::WriteBufferL() frame skipped - number of items in queue: %d"), iFrameInfoArray.Count()));
- }
- else if (ts > encodedTs)
- {
- // this frame has most likely been treated as skipped using timer,
- // but it was encoded regardless
- removeItem = EFalse;
- frameNumber = iSkippedFrameNumber;
- timeStamp = iProcessor->GetVideoTimeInTicksFromMs( encodedTs.Int64() / 1000, EFalse );
-
- PRINT((_L("CVideoProcessor::WriteBufferL() frame skipped falsely, ts in ticks = %d"), I64INT(timeStamp)));
- break;
- }
- else
- {
- // normal case, encoded frame timestamp is as expected
- timeStamp = iFrameInfoArray[0].iTimeStamp;
- frameNumber = iFrameInfoArray[0].iFrameNumber;
- break;
- }
- }
-
- VDASSERT(iFrameInfoArray.Count(), 50);
-
- // set descriptor for writing the frame
- TPtr8 writeDes(0,0);
- writeDes.Set(const_cast<TUint8*>(aBuffer->Data().Ptr()),
- aBuffer->Data().Length(), aBuffer->Data().Length());
-
- HBufC8* tempBuffer = 0;
- TInt error;
-
- if ( (iProcessor->GetOutputVideoType() == EVedVideoTypeMPEG4SimpleProfile) &&
- (!iOutputVolHeaderWritten) && (frameNumber >= iFirstIncludedFrameNumber) )
- {
- VDASSERT(iOutputVolHeader, 51);
-
- // MPEG-4 output:
- // Encoded frame is the first one of the clip, insert VOL header at the beginning
- // Allocate a temp buffer to include vol header and the encoded frame
- TInt length = iOutputVolHeader->Length() + aBuffer->Data().Length();
- TRAP(error, tempBuffer = (HBufC8*) HBufC8::NewL(length) );
-
- if (error != KErrNone)
- {
- iMonitor->Error(error);
- return;
- }
-
- TPtr8 ptr( tempBuffer->Des() );
- ptr.Copy(iOutputVolHeader->Des());
- ptr.Append(aBuffer->Data());
-
- writeDes.Set(tempBuffer->Des());
- iOutputVolHeaderWritten = ETrue;
- }
-
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
- if (iProcessor->GetOutputVideoType() == EVedVideoTypeAVCBaselineProfile)
- {
-
- // get number of NAL units
- TUint8* tmp = const_cast<TUint8*>(aBuffer->Data().Ptr() + aBuffer->Data().Length());
-
- tmp -= 4;
- TInt numNalUnits = TInt(tmp[0]) + (TInt(tmp[1])<<8) + (TInt(tmp[2])<<16) + (TInt(tmp[3])<<24);
-
- TInt totalLength = 0;
-
- // get nal_unit_type of first NAL
- TUint8* type = const_cast<TUint8*>(aBuffer->Data().Ptr());
- TInt nalType = *type & 0x1F;
-
- PRINT((_L("CVideoProcessor::WriteBufferL() - # of NAL units = %d, frame # = %d, nal_unit_type = %d"),
- numNalUnits, frameNumber, nalType));
-
- if (nalType != 1 && nalType != 5)
- {
- // there are extra SPS/PPS units in the beginning
- // of the buffer, skip those
- numNalUnits--;
-
- if (numNalUnits == 0)
- {
- PRINT((_L("CVideoProcessor::WriteBufferL() No NAL units left, return")));
- return;
- }
-
- // point to first length field
- tmp = const_cast<TUint8*>(aBuffer->Data().Ptr() + aBuffer->Data().Length());
- tmp -= 4; // #
- tmp -= numNalUnits * 8; // offset & length for each NAL
- tmp += 4; // skip offset
-
- // get NAL length
- TInt len = TInt(tmp[0]) + (TInt(tmp[1])<<8) + (TInt(tmp[2])<<16) + (TInt(tmp[3])<<24);
- type += len;
- nalType = *type & 0x1F;
-
- while (nalType != 1 && nalType != 5 && numNalUnits)
- {
- numNalUnits--;
- tmp += 8;
- len = TInt(tmp[0]) + (TInt(tmp[1])<<8) + (TInt(tmp[2])<<16) + (TInt(tmp[3])<<24);
- type += len;
- nalType = *type & 0x1F;
- }
- tmp = const_cast<TUint8*>(aBuffer->Data().Ptr() + aBuffer->Data().Length()) - 4;
- }
-
- if (numNalUnits == 0)
- {
- PRINT((_L("CVideoProcessor::WriteBufferL() No NAL units left, return")));
- return;
- }
-
- // rewind to last length field
- tmp -= 4;
-
- // get total length of slices
- for (TInt x = numNalUnits; x > 0; x--)
- {
- totalLength += TInt(tmp[0]) + (TInt(tmp[1])<<8) + (TInt(tmp[2])<<16) + (TInt(tmp[3])<<24);
- tmp -= 8;
- }
-
- TInt tempLength = totalLength + numNalUnits*4;
-
- // allocate output buffer
- TRAP(error, tempBuffer = (HBufC8*) HBufC8::NewL(tempLength) );
- if (error != KErrNone)
- {
- iMonitor->Error(error);
- return;
- }
-
- TUint8* dst = const_cast<TUint8*>(tempBuffer->Des().Ptr());
- TUint8* src = const_cast<TUint8*>(aBuffer->Data().Ptr());
-
- // point to first offset field
- tmp += 4;
-
- for (TInt x = numNalUnits; x > 0; x--)
- {
- // get length
- tmp += 4;
- TInt length = TInt(tmp[0]) + (TInt(tmp[1])<<8) + (TInt(tmp[2])<<16) + (TInt(tmp[3])<<24);
-
- // set length
- dst[0] = TUint8((length >> 24) & 0xff);
- dst[1] = TUint8((length >> 16) & 0xff);
- dst[2] = TUint8((length >> 8) & 0xff);
- dst[3] = TUint8(length & 0xff);
- dst += 4;
-
- // copy data
- TPtr8 ptr(dst, length);
- ptr.Copy(src, length);
-
- dst += length;
- src += length;
-
- // point to next offset field
- tmp +=4;
- }
-
- writeDes.Set(tempBuffer->Des());
- writeDes.SetLength(tempLength);
-
- }
-#endif
-
- // Figure out are we writing frames from the first
- // or second clip in color transition
-
- TBool colorTransitionFlag = ETrue;
- TInt index = KNumTransitionFrames / 4;
-
- if ( iFrameInfoArray[0].iTransitionFrame == 1 &&
- iFrameInfoArray[0].iTransitionPosition == EPositionStartOfClip &&
- iStartTransitionColor == EColorTransition )
- {
- if ( ( (iFrameInfoArray[0].iTransitionFrameNumber == index) &&
- (iFrameInfoArray[0].iRepeatFrame == 0) ) ||
- iFrameInfoArray[0].iTransitionFrameNumber < index )
- {
- colorTransitionFlag = EFalse;
- }
- }
-
- // write frame
- error = iProcessor->WriteVideoFrameToFile((TDesC8&)writeDes,
- timeStamp, 0 /*dummy*/,
- aBuffer->RandomAccessPoint(), EFalse, colorTransitionFlag, ETrue );
-
- if (tempBuffer)
- delete tempBuffer;
-
- if (error == KErrCompletion)
- {
- PRINT((_L("CVideoProcessor::WriteBufferL() - processing complete")));
- // stop processing
- iProcessingComplete = ETrue;
- iFrameInfoArray.Reset();
- VDASSERT(iTranscoderStarted, 51);
- iTransCoder->StopL();
- iTranscoderStarted = EFalse;
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
-
- // activate object to end processing
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- return;
- }
-
- else if (error != KErrNone)
- {
- iMonitor->Error(error);
- return;
- }
-
- TInt startFrame = iProcessor->GetOutputNumberOfFrames() - iNumberOfFrames;
- TInt absFrameNumber = startFrame + frameNumber;
-
- // save frame number
- iLastWrittenFrameNumber = frameNumber;
-
- iProcessor->SetFrameType(absFrameNumber, aBuffer->RandomAccessPoint());
-
- if (removeItem)
- {
- iFrameInfoArray.Remove(0);
-
- PRINT((_L("CVideoProcessor::WriteBufferL() - removed encoded pic, %d items in queue"), iFrameInfoArray.Count()));
- }
- else
- PRINT((_L("CVideoProcessor::WriteBufferL() - did not remove encoded pic, %d items in queue"), iFrameInfoArray.Count()));
-
-
- if (iDecodingSuspended && !iStreamEndRead)
- {
- if (iFrameInfoArray.Count() < iMaxItemsInProcessingQueue && !iDelayedWrite)
- {
- PRINT((_L("CVideoProcessor::WriteBufferL() - Resume decoding")));
- iDecodingSuspended = EFalse;
- // activate object to start decoding
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- return;
- }
- }
-
- // if there are still frames to be encoded, start timer again
- if ( !IsEncodeQueueEmpty() )
- {
- // check if the next frame in queue is waiting to be encoded, set timer if so
- if ( IsNextFrameBeingEncoded() )
- {
- if ( !iTimer->IsPending() )
- {
- PRINT((_L("CVideoProcessor::WriteBufferL(), set timer")));
- iTimer->SetTimer( TTimeIntervalMicroSeconds32( iMaxEncodingDelay ) );
- }
- }
- return;
- }
-
- if (iStreamEndRead && !iDelayedWrite)
- {
-
- PRINT((_L("CVideoProcessor::WriteBufferL() - stream end read & !iDelayedWrite")));
-
- // stream end has been read
- if (iFrameInfoArray.Count() == 0)
- {
- PRINT((_L("CVideoProcessor::WriteBufferL() - stream end read, no frames left")));
- // end
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
- iProcessingComplete = ETrue;
- // activate object to end processing
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- }
- // else there are frames to be decoded, processing will be completed
- // MtroPictureFromTranscoder
- return;
- }
-
- if (iDelayedWrite)
- {
- if ( IsEncodeQueueEmpty() )
- {
- PRINT((_L("CVideoProcessor::WriteBufferL() writing delayed frame")));
-
- TRAP(error, WriteDelayedFrameL());
- if (error != KErrNone)
- {
- iMonitor->Error(error);
- return;
- }
-
- if ( iStreamEndRead )
- {
- if ( iFrameInfoArray.Count() != 0 )
- {
- // return now if we have read stream end, but there are still frames waiting
- // to be decoded => processing will be completed in MtroPictureFromTranscoder
- PRINT((_L("CVideoProcessor::WriteBufferL(), end read but frames in progress, return")));
- return;
- }
- else
- {
- // activate to stop processing
- PRINT((_L("CVideoProcessor::WriteBufferL(), end read and all frames processed, stopping")));
- iProcessingComplete = ETrue;
- }
- }
-
- if (!IsActive())
- {
- SetActive();
- iStatus = KRequestPending;
- }
- // activate object to continue/end processing
- TRequestStatus *status = &iStatus;
- User::RequestComplete(status, KErrNone);
- return;
- }
- else
- {
- // check if the next frame in queue is waiting to be encoded, set timer if so
- if ( IsNextFrameBeingEncoded() )
- {
- if ( !iTimer->IsPending() )
- {
- PRINT((_L("CVideoProcessor::WriteBufferL() - iDelayedWrite, set timer")));
- iTimer->SetTimer( TTimeIntervalMicroSeconds32( iMaxEncodingDelay ) );
- }
- return;
- }
- }
- }
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::IsEncodeQueueEmpty
-// (other items were commented in a header)
-// ---------------------------------------------------------
-//
-TBool CVideoProcessor::IsEncodeQueueEmpty()
-{
-
- // check if there are still frames waiting to be encoded
- for (TInt i = 0; i < iFrameInfoArray.Count(); i++)
- {
- if (iFrameInfoArray[i].iEncodeFrame == 1)
- {
- return EFalse;
- }
- }
- return ETrue;
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::IsNextFrameBeingEncoded
-// (other items were commented in a header)
-// ---------------------------------------------------------
-//
-TBool CVideoProcessor::IsNextFrameBeingEncoded()
-{
-
- // check if the next frame in queue is waiting to be encoded
- if ( iFrameInfoArray.Count() && (iFrameInfoArray[0].iEncodeFrame == 1) )
- {
-
- VDASSERT( ( iFrameInfoArray[0].iTranscoderMode == EFull ||
- iFrameInfoArray[0].iTranscoderMode == EFullWithIM ), 120 );
-
- if ( (iFrameInfoArray[0].iTranscoderMode == EFull) ||
- (iFrameInfoArray[0].iModificationApplied == 1) )
- {
- return ETrue;
- }
- }
-
- return EFalse;
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::GetEncodingDelay
-// (other items were commented in a header)
-// ---------------------------------------------------------
-//
-TInt CVideoProcessor::GetEncodingDelay()
-{
-
- // number of decode only -frames in queue before first encode frame
- TInt numDecodeFrames = 0;
-
- TInt i;
- for (i = 0; i < iFrameInfoArray.Count(); i++)
- {
- // get index of next encode frame in queue
- if (iFrameInfoArray[i].iEncodeFrame == 1)
- break;
- else
- numDecodeFrames++;
- }
-
- VDASSERT(i < iFrameInfoArray.Count(), 112);
-
- TInt delay = iMaxEncodingDelay;
-
- // If the next frame in encoding queue is an intermediate modification frame
- // (either transition frame or color effect has to be applied)
- // and modification has not been applied to it, double the default delay
- if ( ( (iFrameInfoArray[0].iTransitionFrame == 1) ||
- (iProcessor->GetColorEffect() != EVedColorEffectNone) ) &&
- iFrameInfoArray[0].iModificationApplied == 0 )
- {
- PRINT((_L("CVideoProcessor::GetEncodingDelay() - double the delay")));
- delay <<= 1;
- }
-
- // add time to process decode-only frames to delay
- delay += numDecodeFrames * (iMaxEncodingDelay / 2);
-
- PRINT((_L("CVideoProcessor::GetEncodingDelay() - encoding delay = %d ms, num decode frames %d"), delay/1000, numDecodeFrames));
-
- return delay;
-
-
-
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::WriteDelayedFrameL
-// (other items were commented in a header)
-// ---------------------------------------------------------
-//
-void CVideoProcessor::WriteDelayedFrameL()
-{
-
- PRINT((_L("CVideoProcessor::WriteDelayedFrameL() begin")));
-
- // write the delayed frame
- TPtr8 ptr(iDelayedBuffer->Des());
-
- TInt error = iProcessor->WriteVideoFrameToFile(ptr,
- iDelayedTimeStamp, 0 /*dummy*/,
- iDelayedKeyframe, EFalse, EFalse, EFalse );
-
- if (error == KErrCompletion)
- {
- PRINT((_L("CVideoProcessor::WriteDelayedFrameL() write delayed frame, processing complete")));
- VDASSERT(iTranscoderStarted, 51);
- iTransCoder->StopL();
- iTranscoderStarted = EFalse;
- iFrameInfoArray.Reset();
- iTimer->CancelTimer();
- iProcessingComplete = ETrue;
- }
- else if (error != KErrNone)
- {
- User::Leave(error);
- }
-
- // save frame number
- iLastWrittenFrameNumber = iDelayedFrameNumber;
-
- delete iDelayedBuffer;
- iDelayedBuffer = 0;
- iDelayedWrite = EFalse;
-
- PRINT((_L("CVideoProcessor::WriteDelayedFrameL() end")));
-
-}
-
-TInt CVideoProcessor::SetVideoFrameSize(TSize /*aSize*/)
-{
-
- PRINT((_L("CVideoProcessor::SetVideoFrameSize()")))
-
- return KErrNone;
-}
-
-TInt CVideoProcessor::SetAverageVideoBitRate(TInt /*aBitRate*/)
-{
-
- PRINT((_L("CVideoProcessor::SetAverageVideoBitRate()")))
-
- return KErrNone;
-}
-
-
-TInt CVideoProcessor::SetMaxVideoBitRate(TInt /*aBitRate*/)
-{
- PRINT((_L("CVideoProcessor::SetMaxVideoBitRate()")))
-
- return KErrNone;
-}
-
-TInt CVideoProcessor::SetAverageAudioBitRate(TInt /*aBitRate*/)
-{
- PRINT((_L("CVideoProcessor::SetAverageAudioBitRate()")))
-
- return KErrNone;
-}
-
-// ---------------------------------------------------------
-// CVideoProcessor::SetVideoCodecL()
-// Interpret and store video mime type
-// ---------------------------------------------------------
-//
-void CVideoProcessor::SetOutputVideoCodecL(const TPtrC8& aMimeType)
- {
- TBuf8<256> string;
- TBuf8<256> newMimeType;
- string = KVedMimeTypeH263;
- string += _L8( "*" );
-
- iMaxOutputFrameRate = 15.0;
- iArbitrarySizeAllowed = EFalse;
-
- if ( aMimeType.MatchF( (const TDesC8& )string ) != KErrNotFound )
- {
- // H.263
-
- newMimeType = KVedMimeTypeH263;
-
- if ( aMimeType.MatchF( _L8("*profile*") ) != KErrNotFound )
- {
- // profile given, check if we support it
- if ( aMimeType.MatchF( _L8("*profile=0*")) != KErrNotFound )
- {
- // profile 0 requested
- newMimeType += _L8( "; profile=0" );
- }
- else
- {
- // no other profiles supported
- PRINT((_L("CVideoEncoder::SetVideoCodecL() unsupported profile")));
- User::Leave(KErrNotSupported);
- }
- }
- else
- {
- // no profile is given => assume 0
- newMimeType += _L8( "; profile=0" );
- }
-
- if ( aMimeType.MatchF( _L8("*level=10*") ) != KErrNotFound )
- {
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateH263Level10;
- iMaxOutputResolution = KVedResolutionQCIF;
- //dataBufferSize = KMaxCodedPictureSizeQCIF;
- newMimeType += _L8( "; level=10" );
- }
- else if ( aMimeType.MatchF( _L8("*level=45*") ) != KErrNotFound )
- {
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateH263Level45;
- iMaxOutputResolution = KVedResolutionQCIF;
- //dataBufferSize = KMaxCodedPictureSizeQCIF;
- newMimeType += _L8( "; level=45" );
- }
- else if ( aMimeType.MatchF( _L8("*level*") ) != KErrNotFound )
- {
- // no other levels supported
- PRINT((_L("CVideoEncoder::SetVideoCodecL() unsupported level")));
- User::Leave(KErrNotSupported);
- }
- else
- {
- // if no level is given assume 10
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateH263Level10;
- iMaxOutputResolution = KVedResolutionQCIF;
- //dataBufferSize = KMaxCodedPictureSizeQCIF;
- newMimeType += _L8( "; level=10" );
- }
- }
- else
- {
- string = KVedMimeTypeMPEG4Visual;
- string += _L8( "*" );
-
- if ( aMimeType.MatchF( string ) != KErrNotFound )
- {
- // MPEG-4 Visual
- newMimeType = KVedMimeTypeMPEG4Visual;
- if ( aMimeType.MatchF( _L8("*profile-level-id=8*") ) != KErrNotFound )
- {
- // simple profile level 0
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateMPEG4Level0;
- iMaxOutputResolution = KVedResolutionQCIF;
- // define max size 10K
- //dataBufferSize = KMaxCodedPictureSizeMPEG4QCIF;
- newMimeType += _L8("; profile-level-id=8");
- }
- else if ( aMimeType.MatchF( _L8("*profile-level-id=9*") ) != KErrNotFound )
- {
- // simple profile level 0b
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateMPEG4Level0;
- iMaxOutputResolution = KVedResolutionQCIF;
- // define max size 10K
- //dataBufferSize = KMaxCodedPictureSizeMPEG4QCIF;
- newMimeType += _L8("; profile-level-id=9");
- }
- else if ( aMimeType.MatchF( _L8("*profile-level-id=1*") ) != KErrNotFound )
- {
- // simple profile level 1
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateMPEG4Level0;
- iMaxOutputResolution = KVedResolutionQCIF;
- // define max size 10K
- //dataBufferSize = KMaxCodedPictureSizeMPEG4QCIF;
- iArbitrarySizeAllowed = ETrue;
- newMimeType += _L8("; profile-level-id=1");
- }
- else if ( aMimeType.MatchF( _L8("*profile-level-id=2*") ) != KErrNotFound )
- {
- // simple profile level 2
- //dataBufferSize = KMaxCodedPictureSizeMPEG4CIF;
- iMaxOutputResolution = KVedResolutionCIF;
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateMPEG4Level2;
- iArbitrarySizeAllowed = ETrue;
- newMimeType += _L8("; profile-level-id=2");
- }
- else if ( aMimeType.MatchF( _L8("*profile-level-id=3*") ) != KErrNotFound )
- {
- // simple profile level 3
- //dataBufferSize = KMaxCodedPictureSizeMPEG4CIF;
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateMPEG4Level2;
- iMaxOutputResolution = KVedResolutionCIF;
- iMaxOutputFrameRate = 30.0;
- iArbitrarySizeAllowed = ETrue;
- newMimeType += _L8("; profile-level-id=3");
- }
- else if ( aMimeType.MatchF( _L8("*profile-level-id=4*") ) != KErrNotFound )
- {
- // simple profile level 4a
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateMPEG4Level4A;
- //dataBufferSize = KMaxCodedPictureSizeVGA;
- iMaxOutputResolution = KVedResolutionVGA;
- iMaxOutputFrameRate = 30.0;
- iArbitrarySizeAllowed = ETrue;
- newMimeType += _L8("; profile-level-id=4");
- }
- else if ( aMimeType.MatchF( _L8("*profile-level-id=*") ) != KErrNotFound )
- {
- // no other profile-level ids supported
- PRINT((_L("CVideoEncoder::SetVideoCodecL() unsupported MPEG-4 profile-level")));
- User::Leave(KErrNotSupported);
- }
- else
- {
- // Default is level 0 in our case (normally probably level 1)
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateMPEG4Level0;
- iMaxOutputResolution = KVedResolutionQCIF;
- // define max size 10K
- //dataBufferSize = KMaxCodedPictureSizeMPEG4QCIF;
- newMimeType += _L8("; profile-level-id=8");
- }
- }
-
- else
- {
-
-#ifdef VIDEOEDITORENGINE_AVC_EDITING
- string = KVedMimeTypeAVC;
- string += _L8( "*" );
-
- if ( aMimeType.MatchF( string ) != KErrNotFound )
- {
- // AVC
- newMimeType = KVedMimeTypeAVC;
- if ( aMimeType.MatchF( _L8("*profile-level-id=42800A*") ) != KErrNotFound )
- {
- // baseline profile level 1
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateAVCLevel1;
- iMaxOutputResolution = KVedResolutionQCIF;
- newMimeType += _L8("; profile-level-id=42800A");
- }
- else if ( aMimeType.MatchF( _L8("*profile-level-id=42900B*") ) != KErrNotFound )
- {
- // baseline profile level 1b
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateAVCLevel1b;
- iMaxOutputResolution = KVedResolutionQCIF;
- newMimeType += _L8("; profile-level-id=42900B");
- }
- else if ( aMimeType.MatchF( _L8("*profile-level-id=42800B*") ) != KErrNotFound )
- {
- // baseline profile level 1.1
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateAVCLevel1_1;
- iMaxOutputResolution = KVedResolutionCIF;
- newMimeType += _L8("; profile-level-id=42800B");
- }
- else if ( aMimeType.MatchF( _L8("*profile-level-id=42800C*") ) != KErrNotFound )
- {
- // baseline profile level 1.2
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateAVCLevel1_2;
- iMaxOutputResolution = KVedResolutionCIF;
- newMimeType += _L8("; profile-level-id=42800C");
- }
- //WVGA task
- else if ( aMimeType.MatchF( _L8("*profile-level-id=42801E*") ) != KErrNotFound )
- {
- // baseline profile level 3.0
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateAVCLevel3;
- iMaxOutputResolution = KVedResolutionWVGA;
- newMimeType += _L8("; profile-level-id=42801E");
- }
-
- else if ( aMimeType.MatchF( _L8("*profile-level-id=42801F*") ) != KErrNotFound )
- {
- // baseline profile level 3.1
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateAVCLevel3_1;
- iMaxOutputResolution = KVedResolutionWVGA;
- newMimeType += _L8("; profile-level-id=42801F");
- }
- else if ( aMimeType.MatchF( _L8("*profile-level-id=*") ) != KErrNotFound )
- {
- // no other profile-level ids supported
- PRINT((_L("CVideoEncoder::SetVideoCodecL() unsupported AVC profile-level")));
- User::Leave(KErrNotSupported);
- }
- else
- {
- // Default is level 1 (?)
- iMaxOutputBitRate = iOutputBitRate = KVedBitRateAVCLevel1;
- iMaxOutputResolution = KVedResolutionQCIF;
- newMimeType += _L8("; profile-level-id=42800A");
- }
- }
-
- else
- {
- // unknown mimetype
- User::Leave( KErrNotSupported );
- }
-#else
-
- // unknown mimetype
- User::Leave( KErrNotSupported );
-
-#endif
- }
- }
-
- // successfully interpreted the input mime type
- iOutputMimeType = newMimeType;
-
- /*if ( iDataBuffer )
- {
- delete iDataBuffer;
- iDataBuffer = NULL;
- }
- iDataBuffer = (HBufC8*) HBufC8::NewL(dataBufferSize); */
-
- }
-
-// ---------------------------------------------------------
-// CVideoProcessor::GetVosHeaderSize()
-// Gets the size of MPEG-4 VOS header (from encoder)
-// ---------------------------------------------------------
-//
-TInt CVideoProcessor::GetVosHeaderSize()
-{
- VDASSERT(iOutputVolHeader, 190);
-
- return iOutputVolHeader->Length();
-}
-
-// ---------------------------------------------------------
-// CCallbackTimer::NewL()
-// Two-phased constructor
-// ---------------------------------------------------------
-//
-CCallbackTimer* CCallbackTimer::NewL(MTimerObserver& aObserver)
-{
-
- CCallbackTimer* self = new (ELeave) CCallbackTimer(aObserver);
- CleanupStack::PushL(self);
- self->ConstructL();
- CleanupStack::Pop();
-
- return self;
-}
-
-// ---------------------------------------------------------
-// CCallbackTimer::CCallbackTimer()
-// C++ default constructor.
-// ---------------------------------------------------------
-//
-CCallbackTimer::CCallbackTimer(MTimerObserver& aObserver) :
- CActive(EPriorityStandard), iObserver(aObserver)
-
-{
-}
-
-// ---------------------------------------------------------
-// CCallbackTimer::~CCallbackTimer()
-// Destructor
-// ---------------------------------------------------------
-//
-CCallbackTimer::~CCallbackTimer()
-{
- Cancel();
-
- if ( iTimerCreated )
- {
- iTimer.Close();
- iTimerCreated = EFalse;
- }
-}
-
-// ---------------------------------------------------------
-// CCallbackTimer::ConstructL()
-// Symbian 2nd phase constructor
-// ---------------------------------------------------------
-//
-void CCallbackTimer::ConstructL()
-{
- // Create a timer
- User::LeaveIfError(iTimer.CreateLocal());
- iTimerCreated = ETrue;
-
- // Add us to active scheduler
- CActiveScheduler::Add(this);
-}
-
-// ---------------------------------------------------------
-// CCallbackTimer::SetTimer()
-// Set timer
-// ---------------------------------------------------------
-//
-void CCallbackTimer::SetTimer(TTimeIntervalMicroSeconds32 aDuration)
-{
-
-// __ASSERT_DEBUG(!iTimerRequestPending != 0, -5000); //CSI: #174-D: expression has no effect, just an assert debug no effect intended
-// __ASSERT_DEBUG(iTimerCreated, -5001);
-
- PRINT((_L("CCallbackTimer::SetTimer()")))
-
- // activate timer to wait for encoding
- SetActive();
- iStatus = KRequestPending;
- iTimer.After(iStatus, aDuration);
- iTimerRequestPending = ETrue;
-
-}
-
-// ---------------------------------------------------------
-// CCallbackTimer::CancelTimer()
-// Cancel timer
-// ---------------------------------------------------------
-//
-void CCallbackTimer::CancelTimer()
-{
- PRINT((_L("CCallbackTimer::CancelTimer()")))
- Cancel();
-}
-
-// ---------------------------------------------------------
-// CCallbackTimer::RunL()
-// AO running method
-// ---------------------------------------------------------
-//
-void CCallbackTimer::RunL()
-{
- if ( iTimerRequestPending )
- {
- iTimerRequestPending = EFalse;
-
- // call observer
- iObserver.MtoTimerElapsed(KErrNone);
- }
-}
-
-// ---------------------------------------------------------
-// CCallbackTimer::DoCancel()
-// AO cancelling method
-// ---------------------------------------------------------
-//
-void CCallbackTimer::DoCancel()
-{
-
- // Cancel our timer request if we have one
- if ( iTimerRequestPending )
- {
- iTimer.Cancel();
- iTimerRequestPending = EFalse;
- return;
- }
-
-}
-
-// ---------------------------------------------------------
-// CCallbackTimer::RunError()
-// AO RunL error method
-// ---------------------------------------------------------
-//
-TInt CCallbackTimer::RunError(TInt aError)
-{
- Cancel();
-
- // call observer
- iObserver.MtoTimerElapsed(aError);
-
- return KErrNone;
-}
-
-
-// End of File
-