diff -r 951a5db380a0 -r e0b5df5c0969 videoeditorengine/vedtranscoder/src/Ctrscaler.cpp --- a/videoeditorengine/vedtranscoder/src/Ctrscaler.cpp Fri Jan 29 14:08:33 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,791 +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: -* Resampling framework for YUV 4.2.0. -* -*/ - - - -// INCLUDES -#include "ctrscaler.h" -#include "ctrsettings.h" -#include "ctrhwsettings.h" -#include - - -// Debug print macro -#ifdef _DEBUG - #include - #define PRINT(x) RDebug::Print x; -#else - #define PRINT(x) -#endif - - -// An assertion macro wrapper to clean up the code a bit -#define VPASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CTRScaler"), KErrAbort)) - - -// Macros for fixed point math -#define FP_BITS 15 // Number of bits to use for FP decimals -#define FP_FP(x) (static_cast((x) * 32768.0)) -#define FP_ONE (1 << FP_BITS) -#define FP_MUL(x,y) (((x) * (y)) >> FP_BITS) -#define FP_FRAC(x) ((x) & (FP_ONE - 1)) -#define FP_INT(x) ((x) >> FP_BITS) - - -// ============================ MEMBER FUNCTIONS =============================== - -// ----------------------------------------------------------------------------- -// CTRScaler::NewL -// Two-phased constructor. -// ----------------------------------------------------------------------------- -// -CTRScaler* CTRScaler::NewL() - { - // Standard two phase construction - CTRScaler* self = new (ELeave) CTRScaler(); - CleanupStack::PushL(self); - self->ConstructL(); - CleanupStack::Pop(); - - return self; - } - - -// ----------------------------------------------------------------------------- -// CTRScaler::ConstructL -// Symbian 2nd phase constructor can leave. -// ----------------------------------------------------------------------------- -// -void CTRScaler::ConstructL() - { - } - - -// ----------------------------------------------------------------------------- -// CTRScaler::CTRScaler -// C++ default constructor can NOT contain any code, that -// might leave. -// ----------------------------------------------------------------------------- -CTRScaler::CTRScaler() - { - // Scaler does not perform any operation before initializing - iOperation = EOperationNone; - iTrgBuffer = NULL; - } - - -// --------------------------------------------------------- -// CTRScaler::~CTRScaler() -// Destructor -// --------------------------------------------------------- -// -CTRScaler::~CTRScaler() - { - } - -// --------------------------------------------------------- -// CTRScaler::IsWideAspectRatio() -// Checks if aspect ratio is wide -// --------------------------------------------------------- -// -TBool CTRScaler::IsWideAspectRatio(TSize aSize) - { - return ( TReal(aSize.iWidth) / TReal(aSize.iHeight) ) > KTRWideThreshold; - } - -// ----------------------------------------------------------------------------- -// CTRScaler::SetupScalerL -// Sets the scaler options (src buffer, dest buffer (could be the same as a src), src resolution, trg resolution) -// (other items were commented in a header). -// ----------------------------------------------------------------------------- -// -void CTRScaler::SetScalerOptionsL(TPtr8& aSrc, TPtr8& aTrg, TSize& aSrcSize, TSize& aTrgSize ) - { - - - PRINT((_L("CTRScaler::SetScalerOptionsL, src = (%d, %d), trg = (%d, %d)"), - aSrcSize.iWidth, aSrcSize.iHeight, aTrgSize.iWidth, aTrgSize.iHeight)); - - // Check settings - if ( ( !aSrc.Ptr() ) || ( !aTrg.Ptr() ) || - ( aSrcSize.iWidth == 0) || ( aSrcSize.iHeight == 0 ) || - ( aTrgSize.iWidth == 0) || ( aTrgSize.iHeight == 0 ) || - ( aSrc.MaxLength() < ( aSrcSize.iWidth * aSrcSize.iHeight * 3 / 2 ) ) || - ( aTrg.MaxLength() < ( aTrgSize.iWidth * aTrgSize.iHeight * 3 / 2 ) ) - ) - { - PRINT((_L("CTRScaler::SetupScalerL(), Given options are not supported"))) - User::Leave(KErrNotSupported); - } - else - { - TReal remainder = 0.0; - iTrgBuffer = NULL; - - // We don't support non-multiple output yet - Math::Mod( remainder, static_cast(aTrgSize.iWidth), 4.0 ); - - if ( remainder == 0.0 ) - { - Math::Mod( remainder, static_cast(aTrgSize.iHeight), 4.0 ); - } - - if ( remainder != 0.0 ) - { - PRINT((_L("CTRScaler::SetupScalerL(), Scaler does not support output resolution that is not multiple by 4"))) - User::Leave(KErrNotSupported); - } - - TSize targetSize = aTrgSize; - // check if black boxing is needed - TBool srcWide = IsWideAspectRatio(aSrcSize); - TBool dstWide = IsWideAspectRatio(aTrgSize); - - iBlackBoxing = TSize(0,0); - - TBool doScaling = ETrue; - if (srcWide != dstWide) - { - TSize resolution(0,0); - - doScaling = GetIntermediateResolution(aSrcSize, aTrgSize, resolution, iBlackBoxing); - - // Set the whole image to black - TUint yLength = aTrgSize.iWidth * aTrgSize.iHeight; - TUint uvLength = yLength >> 1; - - // Y - TInt data = 0; - TPtr8 tempPtr(0,0); - tempPtr.Set(const_cast(aTrg.Ptr()), yLength, yLength); - tempPtr.Fill((TChar)data, yLength); - - // U,V - data = 127; - tempPtr.Set(const_cast(aTrg.Ptr()) + yLength, uvLength, uvLength); - tempPtr.Fill((TChar)data, uvLength); - - aTrgSize = resolution; - PRINT((_L("CTRScaler::SetScalerOptionsL, blackboxing width = %d, height = %d"), iBlackBoxing.iWidth, iBlackBoxing.iHeight)); - } - - if ( !doScaling ) - { - // No need to perform resampling operation, copy data with black boxing - iOperation = EOperationCopyWithBB; - } - - else if ( (aTrgSize.iWidth == aSrcSize.iWidth) && (aTrgSize.iHeight == aSrcSize.iHeight) ) - { - // No need to perform resampling operation, just copy data - iOperation = EOperationCopy; - } - else if ( (aTrgSize.iWidth == aSrcSize.iWidth * 2) && (aTrgSize.iHeight == aSrcSize.iHeight * 2) ) - { - // Resolution is doubled - iOperation = EDoubleSize; - } - else if ( (aTrgSize.iWidth * 2 == aSrcSize.iWidth) && (aTrgSize.iHeight * 2 == aSrcSize.iHeight) ) - { - // Resolution is halved - iOperation = EHalveSize; - } - else if ( (aTrgSize.iWidth > aSrcSize.iWidth) && (aTrgSize.iHeight > aSrcSize.iHeight) ) - { - // Resolution is increased - iOperation = EUpSampling; - } - else if ( (aTrgSize.iWidth < aSrcSize.iWidth) && (aTrgSize.iHeight < aSrcSize.iHeight) ) - { - // Resolution is decreased - iOperation = EDownSampling; - } - else - { - // The image is streched ie. vertical resolution increases and horizontal decreases or vice versa - iOperation = EUpDownSampling; - } - - // Set given settings - iSrc = const_cast( aSrc.Ptr() ); - iTrg = const_cast( aTrg.Ptr() ); - iSrcSize = aSrcSize; - iTrgSize = aTrgSize; - iSrcInit = iSrc; - iTrgInit = iTrg; - aTrgSize = targetSize; // recover target size since it's a reference - iTrgDataSize = aTrgSize.iWidth * aTrgSize.iHeight * 3 / 2; - iTrgBuffer = &aTrg; - } - } - -// --------------------------------------------------------- -// CTRScaler::GetIntermediateResolution() -// Calculates intermediate resolution for use with black boxing -// --------------------------------------------------------- -// -TBool CTRScaler::GetIntermediateResolution(TSize aSrcSize, TSize aTrgSize, - TSize& aTargetResolution, TSize& aBlackBoxing) - { - - TSize resolution; - TBool doScaling = ETrue; - - TBool srcWide = IsWideAspectRatio(aSrcSize); - TBool dstWide = IsWideAspectRatio(aTrgSize); - - VPASSERT(srcWide != dstWide); - - if (dstWide) - { - // Pillarboxing - - // scale height to destination - TReal factor = TReal(aTrgSize.iHeight) / TReal(aSrcSize.iHeight); - - resolution.iWidth = TInt( aSrcSize.iWidth * factor ); - - if (resolution.iWidth & 0x1 > 0) - resolution.iWidth++; - - resolution.iHeight = aTrgSize.iHeight; - - while ( (aTrgSize.iWidth - resolution.iWidth) % 4 != 0 ) - { - resolution.iWidth += 2; - } - - aBlackBoxing.iWidth = (aTrgSize.iWidth - resolution.iWidth) / 2; - - if ( factor == 1.0 ) - { - // source and destination heights are the same, - // meaning source width is smaller and we don't - // have to scale, just do pillarboxing - doScaling = EFalse; - - // set target width - resolution.iWidth = aTrgSize.iWidth; - } - - } - else - { - // Letterboxing - - // scale width to destination - TReal factor = TReal(aTrgSize.iWidth) / TReal(aSrcSize.iWidth); - - resolution.iHeight = TInt( aSrcSize.iHeight * factor ); - - if (resolution.iHeight & 0x1 > 0) - resolution.iHeight++; - - resolution.iWidth = aTrgSize.iWidth; - - while ( (aTrgSize.iHeight - resolution.iHeight) % 4 != 0 ) - { - resolution.iHeight += 2; - } - - aBlackBoxing.iHeight = (aTrgSize.iHeight - resolution.iHeight) / 2; - - if ( factor == 1.0 ) - { - // source and destination widths are the same, - // meaning source height is smaller and we don't - // have to scale, just do letterboxing - doScaling = EFalse; - - // set target height - resolution.iHeight = aTrgSize.iHeight; - } - } - - PRINT((_L("CTRScaler::GetIntermediateResolution, resolution = (%d, %d), bb = (%d, %d)"), - resolution.iWidth, resolution.iHeight, aBlackBoxing.iWidth, aBlackBoxing.iHeight)); - - aTargetResolution = resolution; - - return doScaling; - - -} - - -// ----------------------------------------------------------------------------- -// CTRScaler::Scale() -// Scale the image -// (other items were commented in a header). -// ----------------------------------------------------------------------------- -// -void CTRScaler::Scale() - { - TSize srcSizeUV = TSize( iSrcSize.iWidth / 2, iSrcSize.iHeight / 2 ); - TSize trgSizeUV = TSize( iTrgSize.iWidth / 2, iTrgSize.iHeight / 2 ); - TSize blackBoxingUV = TSize( iBlackBoxing.iWidth / 2, iBlackBoxing.iHeight / 2 ); - - switch( iOperation ) - { - case EOperationCopy: - { - // Src / Trg resolutions are the same, no needs to perform resampling - if ( iSrc != iTrg ) - { - // Copy data, if different memory areas are specified - Mem::Copy( iTrg, iSrc, iTrgDataSize ); - } - else - { - // The same memory fragment is specified for the output; Keep it without changes; - } - } - break; - - case EOperationCopyWithBB: - { - // Copy with black boxing - CopyWithBlackBoxing(iSrcSize, iTrgSize, iBlackBoxing); - CopyWithBlackBoxing(srcSizeUV, trgSizeUV, blackBoxingUV); - CopyWithBlackBoxing(srcSizeUV, trgSizeUV, blackBoxingUV); - } - break; - - case EDownSampling: - { - TInt error = KErrNoMemory; - - // If scaling to less than 50% of the source size - if ( (iTrgSize.iWidth * 2 < iSrcSize.iWidth) && (iTrgSize.iHeight * 2 < iSrcSize.iHeight) ) - { - // Try to do the scaling in two steps - TRAP( error, DoHalveAndBilinearResampleL() ); - } - - // If the above failed or scaling to 51% or higher - if ( error != KErrNone ) - { - // Resample the Y, U & V components - ResampleBilinear(iSrcSize, iTrgSize, iBlackBoxing); - ResampleBilinear(srcSizeUV, trgSizeUV, blackBoxingUV); - ResampleBilinear(srcSizeUV, trgSizeUV, blackBoxingUV); - } - } - break; - - case EUpSampling: - case EUpDownSampling: - { - // Resample the Y, U & V components - ResampleBilinear(iSrcSize, iTrgSize, iBlackBoxing); - ResampleBilinear(srcSizeUV, trgSizeUV, blackBoxingUV); - ResampleBilinear(srcSizeUV, trgSizeUV, blackBoxingUV); - } - break; - - case EDoubleSize: - { - // Resample the Y, U & V components to double size - ResampleDouble(iSrcSize, iTrgSize); - ResampleDouble(srcSizeUV, trgSizeUV); - ResampleDouble(srcSizeUV, trgSizeUV); - } - break; - - case EHalveSize: - { - // Resample the Y, U & V components to half size - ResampleHalve(iSrcSize, iTrgSize, iBlackBoxing); - ResampleHalve(srcSizeUV, trgSizeUV, blackBoxingUV); - ResampleHalve(srcSizeUV, trgSizeUV, blackBoxingUV); - } - break; - - case EOperationNone: - { - PRINT((_L("CTRScaler::Scale(), Scaler was not initialized yet to perform any operation"))) - return; - } -// break; - - default: - { - } - } - - // Recover source and target data pointers - iSrc = iSrcInit; - iTrg = iTrgInit; - - // Set Dsc length - if (iTrgBuffer) - { - iTrgBuffer->SetLength(iTrgDataSize); - } - } - -// ----------------------------------------------------------------------------- -// CTRScaler::CopyWithBlackBoxing() -// Copies frame to target buffer applying black borders -// ----------------------------------------------------------------------------- -// -void CTRScaler::CopyWithBlackBoxing(TSize& aSrcSize, TSize& aTrgSize, TSize& aBlackBoxing) -{ - - if (aBlackBoxing.iHeight != 0) - { - - TInt copyLength = aSrcSize.iWidth * aSrcSize.iHeight; - - iTrg += aBlackBoxing.iHeight * aTrgSize.iWidth; - Mem::Copy(iTrg, iSrc, copyLength); - - iTrg += copyLength; - iTrg += aBlackBoxing.iHeight * aTrgSize.iWidth; - iSrc += copyLength; - - } - - else if (aBlackBoxing.iWidth != 0) - { - - TInt i; - iTrg += aBlackBoxing.iWidth; - - for (i = 0; i < iTrgSize.iHeight; i++) - { - // copy one row - Mem::Copy(iTrg, iSrc, aSrcSize.iWidth); - iSrc += aSrcSize.iWidth; - iTrg += aSrcSize.iWidth; - iTrg += aBlackBoxing.iWidth * 2; - } - - // subtract the width of one pillar - iTrg -= aBlackBoxing.iWidth; - - } -} - - -// ----------------------------------------------------------------------------- -// CTRScaler::DoHalveAndBilinearResampleL() -// First resamples an image to half size and then uses bilinear resample to -// scale it to requested size. -// ----------------------------------------------------------------------------- -// -void CTRScaler::DoHalveAndBilinearResampleL() - { - // Make sure the scale factor is correct - VPASSERT( (iTrgSize.iWidth * 2 < iSrcSize.iWidth) && - (iTrgSize.iHeight * 2 < iSrcSize.iHeight) ); - - TSize srcSizeUV = TSize( iSrcSize.iWidth / 2, iSrcSize.iHeight / 2 ); - TSize trgSizeUV = TSize( iTrgSize.iWidth / 2, iTrgSize.iHeight / 2 ); - TSize blackBoxingUV = TSize( iBlackBoxing.iWidth / 2, iBlackBoxing.iHeight / 2 ); - - // Calculate the size for the temporary image where we store the intermediate result - TSize tempSize = TSize( iSrcSize.iWidth / 2, iSrcSize.iHeight / 2 ); - TSize tempSizeUV = TSize( tempSize.iWidth / 2, tempSize.iHeight / 2 ); - - // Allocate memory for the temporary image - TUint8* tempBuffer = (TUint8*) User::AllocLC(tempSize.iWidth * tempSize.iHeight * 3 / 2); - - // Set the temporary image as the target - iTrg = tempBuffer; - - TSize zeroBlackBox = TSize(0,0); - // Resample the Y, U & V components to half size - ResampleHalve(iSrcSize, tempSize, zeroBlackBox); - ResampleHalve(srcSizeUV, tempSizeUV, zeroBlackBox); - ResampleHalve(srcSizeUV, tempSizeUV, zeroBlackBox); - - // Set the temporary image as the source and recover the original target - iSrc = tempBuffer; - iTrg = iTrgInit; - - // Resample the Y, U & V components - ResampleBilinear(tempSize, iTrgSize, iBlackBoxing); - ResampleBilinear(tempSizeUV, trgSizeUV, blackBoxingUV); - ResampleBilinear(tempSizeUV, trgSizeUV, blackBoxingUV); - - // Release the temporary buffer - CleanupStack::PopAndDestroy(tempBuffer); - } - -// ----------------------------------------------------------------------------- -// CTRScaler::ResampleBilinear() -// Resamples an image with bilinear filtering. The target pixel is generated by -// linearly interpolating the four nearest source pixels in x- and y-directions. -// ----------------------------------------------------------------------------- -// -void CTRScaler::ResampleBilinear(TSize& aSrcSize, TSize& aTrgSize, TSize& aBlackBoxing) - { - TInt i = 0, j = 0; - TInt x = 0, y = 0; - TInt fx = 0, fy = 0; - TInt weightFactor = 0; - - // Pointers to the source memory - TUint8* srcRowPosition = 0; - TUint8* srcPixelPosition = 0; - - // Calculate the scale factor using the max indices of the source and target images - TReal scaleX = TReal(aSrcSize.iWidth - 1) / TReal(aTrgSize.iWidth - 1); - TReal scaleY = TReal(aSrcSize.iHeight - 1) / TReal(aTrgSize.iHeight - 1); - - // Convert the scale factor to fixed point - iScaleXInt = FP_FP(scaleX) - 1; // subtract 1 so we don't go outside the source image - iScaleYInt = FP_FP(scaleY) - 1; - - if ( aBlackBoxing.iWidth != 0 ) - { - // increment target pointer over first 'pillar' - iTrg += aBlackBoxing.iWidth; - } - else if ( aBlackBoxing.iHeight != 0 ) - { - // increment target pointer over top letterboxed area - iTrg += aTrgSize.iWidth * aBlackBoxing.iHeight; - } - - // Loop target rows - for( i = 0, y = 0; i < aTrgSize.iHeight; i++ ) - { - // Calculate the row position of the source - srcRowPosition = iSrc + FP_INT(y) * aSrcSize.iWidth; - - fy = FP_FRAC(y); // Fractational part of the row position - - // Loop target columns - for( j = 0, x = 0; j < aTrgSize.iWidth; j++ ) - { - // Calculate the pixel position in the source - srcPixelPosition = srcRowPosition + FP_INT(x); - - // Calculate the weight factor for blending - fx = FP_FRAC(x); - weightFactor = FP_MUL(fx, fy); - - // Blend using the four nearest pixels - *(iTrg) = FP_INT( - *(srcPixelPosition) * (weightFactor + FP_ONE - fx - fy) + - *(srcPixelPosition + 1) * (fx - weightFactor) + - *(srcPixelPosition + aSrcSize.iWidth) * (fy - weightFactor) + - *(srcPixelPosition + 1 + aSrcSize.iWidth) * weightFactor ); - - iTrg++; // Move on to the next target pixel - x += iScaleXInt; // Calculate the column for the next source pixel - } - - y += iScaleYInt; // Calculate the row for the next source pixels - - if ( aBlackBoxing.iWidth != 0 ) - { - // increment target pointer over two pillars, one at the end of this row, - // other one at the beginning of the next row - iTrg += aBlackBoxing.iWidth * 2; - } - } - - // Update pointers - iSrc += aSrcSize.iWidth * aSrcSize.iHeight; - - if ( aBlackBoxing.iWidth != 0 ) - { - // subtract the width of one pillar - iTrg -= aBlackBoxing.iWidth; - } - else if ( aBlackBoxing.iHeight != 0 ) - { - // increment over bottom letterboxed area - iTrg += aBlackBoxing.iHeight * aTrgSize.iWidth; - } - - } - -// ----------------------------------------------------------------------------- -// CTRScaler::ResampleHalve() -// Resamples an image to half size. For each target pixel a 2x2 pixel area is -// read from the source and blended together to produce the target color. -// ----------------------------------------------------------------------------- -// -void CTRScaler::ResampleHalve(TSize& aSrcSize, TSize& aTrgSize, TSize& aBlackBoxing) - { - TInt i = 0, j = 0; - - // Make sure the scale factor is correct - VPASSERT( (aTrgSize.iWidth * 2 == aSrcSize.iWidth) && - (aTrgSize.iHeight * 2 == aSrcSize.iHeight) ); - - if ( aBlackBoxing.iHeight != 0 ) - { - // increment target pointer over top letterboxed area - iTrg += aTrgSize.iWidth * aBlackBoxing.iHeight; - } - - // Loop target rows - for( i = 0; i < aTrgSize.iHeight; i++ ) - { - // Loop target columns - for( j = 0; j < aTrgSize.iWidth; j++ ) - { - // Calculate the target pixel by blending the 4 nearest source pixels - *(iTrg) = ( - *(iSrc) + - *(iSrc + 1) + - *(iSrc + aSrcSize.iWidth) + - *(iSrc + 1 + aSrcSize.iWidth) - ) >> 2; // divide by 4 - - iTrg++; // Move on to the next target pixel - iSrc += 2; // Sample every second column from the source - } - - iSrc += aSrcSize.iWidth; // Sample every second row from the source - } - - if ( aBlackBoxing.iHeight != 0 ) - { - // increment over bottom letterboxed area - iTrg += aBlackBoxing.iHeight * aTrgSize.iWidth; - } - } - -// ----------------------------------------------------------------------------- -// CTRScaler::ResampleDouble() -// Resamples an image to double size. A 2x2 pixel area is generated using -// the four nearest pixels from the source and written to the target image. -// ----------------------------------------------------------------------------- -// -void CTRScaler::ResampleDouble(TSize& aSrcSize, TSize& aTrgSize) - { - TInt i = 0, j = 0; - - // Make sure the scale factor is correct - VPASSERT( (aTrgSize.iWidth == aSrcSize.iWidth * 2) && - (aTrgSize.iHeight == aSrcSize.iHeight * 2) ); - - // Generate 2x2 target pixels in each loop - - // Loop every second target row - for( i = 0; i < aTrgSize.iHeight - 2; i += 2 ) - { - // Loop every second target column - for( j = 0; j < aTrgSize.iWidth - 2; j += 2 ) - { - // Top-left pixel: Copy as it is - *(iTrg) = *(iSrc); - - // Top-right pixel: Blend the pixels on the left and right - *(iTrg + 1) = (*(iSrc) + *(iSrc + 1)) >> 1; - - // Bottom-left pixel: Blend the above and below pixels - *(iTrg + aTrgSize.iWidth) = (*(iSrc) + *(iSrc + aSrcSize.iWidth)) >> 1; - - // Bottom-right pixel: Blend the four nearest pixels - *(iTrg + 1 + aTrgSize.iWidth) = ( - *(iSrc) + - *(iSrc + 1) + - *(iSrc + aSrcSize.iWidth) + - *(iSrc + 1 + aSrcSize.iWidth) - ) >> 2; - - iTrg += 2; // Move on to the next 2x2 group of pixels - iSrc++; // Sample the next pixel from source - } - - // The last 2x2 pixels on this row need to be handled separately - - // Top-left and top-right pixels: Copy as it is - *(iTrg) = *(iTrg + 1) = *(iSrc); - - // Bottom-left and bottom-right pixels: Blend the above and below pixels - *(iTrg + aTrgSize.iWidth) = *(iTrg + 1 + aTrgSize.iWidth) = ( - *(iSrc) + - *(iSrc + aSrcSize.iWidth) - ) >> 1; - - iTrg += 2 + aTrgSize.iWidth; // Move on to the beginning of the next row - iSrc++; // Sample the next pixel from source - } - - // Handle the last row - for( j = 0; j < aTrgSize.iWidth - 2; j += 2 ) - { - // Top-left and bottom-left pixels: Copy as it is - *(iTrg) = *(iTrg + aTrgSize.iWidth) = *(iSrc); - - // Top-right and bottom-right pixels: Blend the pixels on the left and right - *(iTrg + 1) = *(iTrg + 1 + aTrgSize.iWidth) = ( - *(iSrc) + - *(iSrc + 1) - ) >> 1; - - iTrg += 2; // Move on to the next 2x2 group of pixels - iSrc++; // Sample the next pixel from source - } - - // Handle the last 2x2 group of pixels - - // Copy all four pixels - *(iTrg) = *(iTrg + 1) = *(iTrg + aTrgSize.iWidth) = *(iTrg + 1 + aTrgSize.iWidth) = *(iSrc); - - // Update pointers to the beginning of the next image - iTrg += 2 + aTrgSize.iWidth; - iSrc++; - } - -// ----------------------------------------------------------------------------- -// CTRScaler::EstimateResampleFrameTime -// Returns a time estimate of how long it takes to resample a frame -// (other items were commented in a header). -// ----------------------------------------------------------------------------- -// -TReal CTRScaler::EstimateResampleFrameTime(const TTRVideoFormat& aInput, const TTRVideoFormat& aOutput) - { - // Assume bilinear filtering is used by default - TReal time = KTRResampleTimeFactorBilinear; - - if ( (aOutput.iSize.iWidth == aInput.iSize.iWidth) && (aOutput.iSize.iHeight == aInput.iSize.iHeight) ) - { - // No need for resampling - return 0.0; - } - else if ( (aOutput.iSize.iWidth == aInput.iSize.iWidth * 2) && (aOutput.iSize.iHeight == aInput.iSize.iHeight * 2) ) - { - // Resolution is doubled - time = KTRResampleTimeFactorDouble; - } - else if ( (aOutput.iSize.iWidth * 2 == aInput.iSize.iWidth) && (aOutput.iSize.iHeight * 2 == aInput.iSize.iHeight) ) - { - // Resolution is halved - time = KTRResampleTimeFactorHalve; - } - - // Multiply the time by the resolution of the output frame - time *= static_cast(aOutput.iSize.iWidth + aOutput.iSize.iHeight) * KTRTimeFactorScale; - - PRINT((_L("CTRScaler::EstimateResampleFrameTime(), resample frame time: %.2f"), time)) - - return time; - } - - -// End of file