diff -r 000000000000 -r 40261b775718 mmlibs/mmfw/src/Client/Video/mediaclientvideodisplaybody.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmlibs/mmfw/src/Client/Video/mediaclientvideodisplaybody.cpp Tue Feb 02 01:56:55 2010 +0200 @@ -0,0 +1,958 @@ +// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include "mediaclientvideodisplaybody.h" +#include "mediaclientvideotrace.h" +#include + +CMediaClientVideoDisplayBody* CMediaClientVideoDisplayBody::NewL(TInt aDisplayId) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::NewL +++")); + CMediaClientVideoDisplayBody* self = new (ELeave) CMediaClientVideoDisplayBody(aDisplayId); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::NewL ---")); + return self; + } + +CMediaClientVideoDisplayBody* CMediaClientVideoDisplayBody::NewL(TInt aDisplayId, const TSurfaceId& aSurfaceId, + const TRect& aCropRect, TVideoAspectRatio aAspectRatio) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::NewL +++")); + if(aSurfaceId.IsNull()) + { + User::Leave(KErrArgument); + } + CMediaClientVideoDisplayBody* self = new(ELeave) CMediaClientVideoDisplayBody(aDisplayId, aSurfaceId, aCropRect, aAspectRatio); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::NewL ---")); + return self; + } + +void CMediaClientVideoDisplayBody::ConstructL() + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::ConstructL +++")); + + iExtDisplaySwitchingSupported = CExtDisplayConnectionProviderInterface::ExternalDisplaySupportedL(); + + // Try and enable display switching by default. If this leaves then do so quietly. + // Either the client has no scheduler installed or the device does not support external + // switching (i.e. no plugin was found) + TRAPD(err, SetExternalDisplaySwitchingL(ETrue)); + err = err; // remove compile warning + DEBUG_PRINT2(_L("CMediaClientVideoDisplayBody::ConstructL SetExternalDisplaySwitchingL returned with %d"), err); + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::ConstructL ---")); + } + +CMediaClientVideoDisplayBody::CMediaClientVideoDisplayBody(TInt aDisplayId, const TSurfaceId& aSurfaceId, + const TRect& aCropRect, TVideoAspectRatio aAspectRatio) : + iDisplayId(aDisplayId), + iSurfaceId(aSurfaceId), + iCropRect(aCropRect), + iAspectRatio(aAspectRatio) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CMediaClientVideoDisplayBody +++")); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CMediaClientVideoDisplayBody ---")); + } + +CMediaClientVideoDisplayBody::CMediaClientVideoDisplayBody(TInt aDisplayId) : + iDisplayId(aDisplayId) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CMediaClientVideoDisplayBody +++")); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CMediaClientVideoDisplayBody ---")); + } + +CMediaClientVideoDisplayBody::~CMediaClientVideoDisplayBody() + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::~CMediaClientVideoDisplayBody +++")); + + RemoveBackgroundSurface(ETrue); + + iWindows.Close(); + delete iExtDisplayConnectionProvider; + REComSession::FinalClose(); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::~CMediaClientVideoDisplayBody ---")); + } + +void CMediaClientVideoDisplayBody::AddDisplayL(MMMFSurfaceEventHandler& aEventHandler) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::AddDisplayL +++")); + if (iEventHandler != NULL) + { + User::Leave(KErrInUse); + } + + iEventHandler = &aEventHandler; + + if (IsSurfaceCreated()) + { + iEventHandler->MmsehSurfaceCreated(iDisplayId, iSurfaceId, iCropRect, iAspectRatio); + } + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::AddDisplayL ---")); + } + +void CMediaClientVideoDisplayBody::AddDisplayWindowL(const RWindowBase* aWindow, const TRect& aClipRect, const TRect& aCropRegion, const TRect& aVideoExtent, + TReal32 aScaleWidth, TReal32 aScaleHeight, TVideoRotation aRotation, + TAutoScaleType aAutoScaleType, TInt aHorizPos, TInt aVertPos, RWindow* aWindow2) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::AddDisplayWindowL +++")); + TInt pos = iWindows.Find(aWindow->WsHandle(), TWindowData::CompareByWsHandle); + + if (pos != KErrNotFound) + { + User::Leave(KErrInUse); + } + + TWindowData winData(aWindow, aClipRect, aVideoExtent, aScaleWidth, aScaleHeight, aRotation, aAutoScaleType, aHorizPos, aVertPos, aWindow2); + iWindows.AppendL(winData); + + iCropRegion = aCropRegion; + + if (IsSurfaceCreated()) + { + if(iExtDisplaySwitchingSupported && iClientRequestedExtDisplaySwitching) + { + CreateExtDisplayConnProvAndRemoveSurfaceL(EFalse); + } + + if(!iExtDisplayConnected) + { + User::LeaveIfError(SetBackgroundSurface(winData, aCropRegion)); + } + } + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::AddDisplayWindowL ---")); + } + +void CMediaClientVideoDisplayBody::RemoveDisplay() + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveDisplay +++")); + iEventHandler = NULL; + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveDisplay ---")); + } + +TInt CMediaClientVideoDisplayBody::RemoveDisplayWindow(const RWindowBase& aWindow) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveDisplayWindow +++")); + TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle); + + if (pos >= 0) + { + if (IsSurfaceCreated()) + { + iWindows[pos].iWindow->RemoveBackgroundSurface(ETrue); + + // Make sure all window rendering has completed before proceeding + RWsSession* ws = iWindows[pos].iWindow->Session(); + if (ws) + { + ws->Finish(); + } + } + iWindows.Remove(pos); + + if(iWindows.Count() == 0) + { + RemoveExtDisplayConnProv(); + } + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveDisplayWindow ---")); + return pos; + } + + +TInt CMediaClientVideoDisplayBody::SurfaceCreated(const TSurfaceId& aSurfaceId, const TRect& aCropRect, TVideoAspectRatio aAspectRatio, const TRect& aCropRegion) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SurfaceCreated +++")); + TBool emitEvent = EFalse; + if((iSurfaceId != aSurfaceId) && (!aSurfaceId.IsNull())) + { + emitEvent = ETrue; + } + + iSurfaceId = aSurfaceId; + iCropRect = aCropRect; + iAspectRatio = aAspectRatio; + iCropRegion = aCropRegion; + + if (emitEvent && iEventHandler) + { + iEventHandler->MmsehSurfaceCreated(iDisplayId, iSurfaceId, iCropRect, iAspectRatio); + } + + TInt err = KErrNone; + if(iExtDisplaySwitchingSupported && iClientRequestedExtDisplaySwitching) + { + TRAP(err, CreateExtDisplayConnProvAndRemoveSurfaceL(EFalse)); + } + + if(!iExtDisplayConnected) + { + err = RedrawWindows(aCropRegion); + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SurfaceCreated ---")); + return err; + } + +void CMediaClientVideoDisplayBody::RemoveBackgroundSurface(TBool aTriggerRedraw) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveBackgroundSurface +++")); + if (IsSurfaceCreated()) + { + TInt count = iWindows.Count(); + + RWsSession* ws = NULL; + for (TInt i = 0; i < count; ++i) + { + iWindows[i].iWindow->RemoveBackgroundSurface(aTriggerRedraw); + // Make sure all window rendering has completed before proceeding + ws = iWindows[i].iWindow->Session(); + if (ws) + { + ws->Finish(); + } + } + } + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveBackgroundSurface ---")); + } + +void CMediaClientVideoDisplayBody::RemoveSurface(TBool aControllerEvent) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveSurface +++")); + if (IsSurfaceCreated()) + { + if(!iExtDisplayConnected) + { + RemoveBackgroundSurface(ETrue); + } + + if (iEventHandler && aControllerEvent) + { + iEventHandler->MmsehRemoveSurface(iSurfaceId); + } + + iSurfaceId = TSurfaceId::CreateNullId(); + + RemoveExtDisplayConnProv(); + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveSurface ---")); + } + +TInt CMediaClientVideoDisplayBody::SurfaceParametersChanged(const TSurfaceId& aSurfaceId, const TRect& aCropRect, TVideoAspectRatio aAspectRatio) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SurfaceParametersChanged +++")); + if (!IsSurfaceCreated()) + { + return KErrNotSupported; + } + + if (iSurfaceId != aSurfaceId) + { + return KErrInUse; + } + + iCropRect = aCropRect; + iAspectRatio = aAspectRatio; + + if (iEventHandler) + { + iEventHandler->MmsehSurfaceParametersChanged(iSurfaceId, iCropRect, iAspectRatio); + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SurfaceParametersChanged ---")); + return KErrNone; + } + +TInt CMediaClientVideoDisplayBody::RedrawWindows(const TRect& aCropRegion) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RedrawWindows +++")); + TInt err = KErrNone; + + iCropRegion = aCropRegion; + + if(IsSurfaceCreated()) + { + TInt count = iWindows.Count(); + + for (TInt i = 0; i < count; ++i) + { + err = SetBackgroundSurface(iWindows[i], aCropRegion); + + if (err != KErrNone) + { + break; + } + } + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RedrawWindows ---")); + return err; + } + +void CMediaClientVideoDisplayBody::SetAutoScaleL(const RWindowBase& aWindow, TAutoScaleType aScaleType, TInt aHorizPos, TInt aVertPos, const TRect& aCropRegion) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetAutoScaleL +++")); + TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle); + User::LeaveIfError(pos); + + iWindows[pos].iAutoScaleType = aScaleType; + iWindows[pos].iHorizPos = aHorizPos; + iWindows[pos].iVertPos = aVertPos; + iCropRegion = aCropRegion; + + if (IsSurfaceCreated() && !iExtDisplayConnected) + { + User::LeaveIfError(SetBackgroundSurface(iWindows[pos], aCropRegion)); + } + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetAutoScaleL ---")); + } + + +void CMediaClientVideoDisplayBody::SetRotationL(const RWindowBase& aWindow, TVideoRotation aRotation, const TRect& aCropRegion) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetRotationL +++")); + TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle); + User::LeaveIfError(pos); + + iWindows[pos].iRotation = aRotation; + iCropRegion = aCropRegion; + + if (IsSurfaceCreated() && !iExtDisplayConnected) + { + User::LeaveIfError(SetBackgroundSurface(iWindows[pos], aCropRegion)); + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetRotationL ---")); + } + +TVideoRotation CMediaClientVideoDisplayBody::RotationL(const RWindowBase& aWindow) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RotationL +++")); + TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle); + User::LeaveIfError(pos); + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RotationL ---")); + return iWindows[pos].iRotation; + } + +void CMediaClientVideoDisplayBody::SetScaleFactorL(const RWindowBase& aWindow, TReal32 aWidthPercentage, TReal32 aHeightPercentage, const TRect& aCropRegion) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetScaleFactorL +++")); + TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle); + User::LeaveIfError(pos); + + if (aWidthPercentage <= 0.0 || aHeightPercentage <= 0.0) + { + User::Leave(KErrArgument); + } + + + iWindows[pos].iScaleWidth = aWidthPercentage; + iWindows[pos].iScaleHeight = aHeightPercentage; + iWindows[pos].iAutoScaleType = EAutoScaleNone; + iCropRegion = aCropRegion; + + if (IsSurfaceCreated() && !iExtDisplayConnected) + { + User::LeaveIfError(SetBackgroundSurface(iWindows[pos], aCropRegion)); + } + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetScaleFactorL ---")); + } + +void CMediaClientVideoDisplayBody::GetScaleFactorL(const RWindowBase& aWindow, TReal32& aWidthPercentage, TReal32& aHeightPercentage) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::GetScaleFactorL +++")); + TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle); + User::LeaveIfError(pos); + + aWidthPercentage = iWindows[pos].iScaleWidth; + aHeightPercentage = iWindows[pos].iScaleHeight; + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::GetScaleFactorL ---")); + } + +void CMediaClientVideoDisplayBody::SetAutoScaleL(TAutoScaleType aScaleType, TInt aHorizPos, TInt aVertPos, const TRect& aCropRegion) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetAutoScaleL +++")); + + iCropRegion = aCropRegion; + TInt count = iWindows.Count(); + + for (TInt i = 0; i < count; ++i) + { + iWindows[i].iAutoScaleType = aScaleType; + iWindows[i].iHorizPos = aHorizPos; + iWindows[i].iVertPos = aVertPos; + if (IsSurfaceCreated() && !iExtDisplayConnected) + { + User::LeaveIfError(SetBackgroundSurface(iWindows[i], aCropRegion)); + } + } + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetAutoScaleL ---")); + } + + +void CMediaClientVideoDisplayBody::SetRotationL(TVideoRotation aRotation, const TRect& aCropRegion) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetRotationL +++")); + iCropRegion = aCropRegion; + TInt count = iWindows.Count(); + + for (TInt i = 0; i < count; ++i) + { + iWindows[i].iRotation = aRotation; + if (IsSurfaceCreated() && !iExtDisplayConnected) + { + User::LeaveIfError(SetBackgroundSurface(iWindows[i], aCropRegion)); + } + } + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetRotationL ---")); + } + +void CMediaClientVideoDisplayBody::SetScaleFactorL(TReal32 aWidthPercentage, TReal32 aHeightPercentage, const TRect& aCropRegion) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetScaleFactorL +++")); + if (aWidthPercentage <= 0.0 || aHeightPercentage <= 0.0) + { + User::Leave(KErrArgument); + } + + iCropRegion = aCropRegion; + TInt count = iWindows.Count(); + + for (TInt i = 0; i < count; ++i) + { + iWindows[i].iScaleWidth = aWidthPercentage; + iWindows[i].iScaleHeight = aHeightPercentage; + iWindows[i].iAutoScaleType = EAutoScaleNone; + if (IsSurfaceCreated() && !iExtDisplayConnected) + { + User::LeaveIfError(SetBackgroundSurface(iWindows[i], aCropRegion)); + } + } + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetScaleFactorL ---")); + } + +void CMediaClientVideoDisplayBody::SetWindowClipRectL(const RWindowBase& aWindow, const TRect& aWindowClipRect, const TRect& aCropRegion) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetWindowClipRectL +++")); + + TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle); + User::LeaveIfError(pos); + + iWindows[pos].iClipRect = aWindowClipRect; + iCropRegion = aCropRegion; + + if (IsSurfaceCreated() && !iExtDisplayConnected) + { + User::LeaveIfError(SetBackgroundSurface(iWindows[pos], aCropRegion)); + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetWindowClipRectL ---")); + } + +void CMediaClientVideoDisplayBody::SetVideoExtentL(const RWindowBase& aWindow, const TRect& aVideoExtent, const TRect& aCropRegion) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetVideoExtentL +++")); + TInt pos = iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle); + User::LeaveIfError(pos); + + iWindows[pos].iVideoExtent = aVideoExtent; + iCropRegion = aCropRegion; + + if (IsSurfaceCreated() && !iExtDisplayConnected) + { + User::LeaveIfError(SetBackgroundSurface(iWindows[pos], aCropRegion)); + } + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetVideoExtentL ---")); + } + +TBool CMediaClientVideoDisplayBody::HasWindows() const + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::HasWindows +++")); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::HasWindows ---")); + return (iWindows.Count() > 0); + } + +TInt CMediaClientVideoDisplayBody::SetBackgroundSurface(TWindowData& aWindowData, + const TRect& aCropRegion) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetBackgroundSurface +++")); + + // required as this private function is called directly from external friend class + iCropRegion = aCropRegion; + + // viewport is the viewable area of surface + TRect viewport(iCropRect); + if (aCropRegion.Width() > 0 || aCropRegion.Height() > 0) + { + viewport.Intersection(aCropRegion); + } + + // Viewport is 0 size, don't show any video + if (viewport.Width() <= 0 || viewport.Height() <= 0) + { + return KErrArgument; + } + + TRect extent; + CalculateExtentAndViewport(aWindowData, extent, viewport); + + aWindowData.iSurfaceConfig.SetViewport(viewport); + aWindowData.iSurfaceConfig.SetExtent(extent); + aWindowData.iSurfaceConfig.SetOrientation(ConvertRotation(aWindowData.iRotation)); + + aWindowData.iSurfaceConfig.SetSurfaceId(iSurfaceId); + + // Get the rectangle that bounds the crop rectangle and the viewport. This should be + // the same as the crop rectangle as long as the viewport does not go outside this area. + TRect rect(iCropRect); + rect.BoundingRect(viewport); + TInt err = KErrNone; + + // Check if the viewport and extent can be displayed as a background surface. The viewport + // is valid if it is within the crop rectangle and is not empty. The extent is valid if + // it is not empty. + if (rect == iCropRect && !viewport.IsEmpty() && !extent.IsEmpty()) + { + err = aWindowData.iWindow->SetBackgroundSurface(aWindowData.iSurfaceConfig, ETrue); + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetBackgroundSurface ---")); + return err; + } + +void CMediaClientVideoDisplayBody::CalculateExtentAndViewport(const TWindowData& aWindowData, TRect& aExtent, TRect& aViewport) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CalculateExtentAndViewport +++")); + + TRect videoExtent(aWindowData.iVideoExtent); + + TReal32 inputWidth = 0.0f; + TReal32 inputHeight = 0.0f; + TReal32 pixelAspectRatio = 0.0f; + switch (aWindowData.iRotation) + { + case EVideoRotationNone: + case EVideoRotationClockwise180: + inputWidth = static_cast(aViewport.Width()); + inputHeight = static_cast(aViewport.Height()); + pixelAspectRatio = static_cast(iAspectRatio.iNumerator) / iAspectRatio.iDenominator; + break; + case EVideoRotationClockwise90: + case EVideoRotationClockwise270: + inputWidth = static_cast(aViewport.Height()); + inputHeight = static_cast(aViewport.Width()); + pixelAspectRatio = static_cast(iAspectRatio.iDenominator) / iAspectRatio.iNumerator; + break; + default: + // Should never get to default unless there's been some programming error. + User::Invariant(); + break; + } + + TReal32 viewportAspect = pixelAspectRatio * inputWidth / inputHeight; + TReal32 vidextAspect = static_cast(videoExtent.Width()) / static_cast(videoExtent.Height()); + + // Set the extent to the display area in the window. The final height and with is to + // be changed by deltaHeight and deltaWidth respectively. + aExtent = videoExtent; + + TInt deltaHeight = 0; + TInt deltaWidth = 0; + + if (aWindowData.iAutoScaleType == EAutoScaleBestFit) + { + if (viewportAspect > vidextAspect) + { + // Shrink height to get the correct aspect ratio + deltaHeight = (TInt) (aExtent.Width() / viewportAspect - aExtent.Height()); + } + else + { + // Shrink width to get the correct aspect ratio + deltaWidth = (TInt) (aExtent.Height() * viewportAspect - aExtent.Width()); + } + } + else if (aWindowData.iAutoScaleType == EAutoScaleClip) + { + if (viewportAspect > vidextAspect) + { + // Expand width to get the correct aspect ratio + deltaWidth = (TInt) (aExtent.Height() * viewportAspect - aExtent.Width()); + } + else + { + // Expand height to get the correct aspect ratio + deltaHeight = (TInt) (aExtent.Width() / viewportAspect - aExtent.Height()); + } + } + else if (aWindowData.iAutoScaleType == EAutoScaleStretch) + { + // Don't do anything: the extent is already set to the size of the video extent. + } + else if (aWindowData.iAutoScaleType == EAutoScaleNone) + { + // for non-square pixels, reduce one dimension + // TBD other option is to enlarge in the other dimension + if(pixelAspectRatio > 1) + { + inputHeight /= pixelAspectRatio; + } + else if(pixelAspectRatio < 1) + { + inputWidth *= pixelAspectRatio; + } + deltaHeight = (TInt) (inputHeight * aWindowData.iScaleHeight * 0.01 - videoExtent.Height()); + deltaWidth = (TInt) (inputWidth * aWindowData.iScaleWidth * 0.01 - videoExtent.Width()); + } + + // Change the width of the extent in the proper directions and propertions. + switch (aWindowData.iHorizPos) + { + case EHorizontalAlignCenter: + aExtent.iTl.iX -= deltaWidth / 2; + aExtent.iBr.iX += deltaWidth / 2; + break; + case EHorizontalAlignLeft: + aExtent.iBr.iX += deltaWidth; + break; + case EHorizontalAlignRight: + aExtent.iTl.iX -= deltaWidth; + break; + default: + TInt width = aExtent.Width() + deltaWidth; + aExtent.iTl.iX += aWindowData.iHorizPos; + aExtent.iBr.iX = aExtent.iTl.iX + width; + break; + } + + // Change the height of the extent in the proper directions and propertions. + switch (aWindowData.iVertPos) + { + case EVerticalAlignCenter: + aExtent.iTl.iY -= deltaHeight / 2; + aExtent.iBr.iY += deltaHeight / 2; + break; + case EVerticalAlignTop: + aExtent.iBr.iY += deltaHeight; + break; + case EVerticalAlignBottom: + aExtent.iTl.iY -= deltaHeight; + break; + default: + TInt height = aExtent.Height() + deltaHeight; + aExtent.iTl.iY += aWindowData.iVertPos; + aExtent.iBr.iY = aExtent.iTl.iY + height; + break; + } + + // The video should not be displayed outside the intended video extent or clipping rectangle. + // The extent already has the correct size and position for displaying the entire viewport. + // The viewport is clipped such that the video is not moved/distorted when we take the extent + // to be the intersection of itself and the intended video extent. + + TRect viewableArea(videoExtent); + viewableArea.Intersection(aWindowData.iClipRect); + + // Number of pixels (in window coordinates) to be clipped on the right, bottom, top and left sides of + // the video. + TInt dr = Max(0, aExtent.iBr.iX - viewableArea.iBr.iX); + TInt db = Max(0, aExtent.iBr.iY - viewableArea.iBr.iY); + TInt dt = Max(0, viewableArea.iTl.iY - aExtent.iTl.iY); + TInt dl = Max(0, viewableArea.iTl.iX - aExtent.iTl.iX); + + // Calculate the number of pixels in the video per window pixel in both x and y directions. + TReal32 wRatio = 0.0f; + TReal32 hRatio = 0.0f; + + // Make sure we don't divide by 0 + if (aExtent.Width() != 0) + { + wRatio = inputWidth / static_cast(aExtent.Width()); + } + + if (aExtent.Height() != 0) + { + hRatio = inputHeight / static_cast(aExtent.Height()); + } + + // Clip the viewport + switch (aWindowData.iRotation) + { + case EVideoRotationNone: + aViewport.iBr.iX -= (TInt) (wRatio * static_cast(dr)); + aViewport.iBr.iY -= (TInt) (hRatio * static_cast(db)); + aViewport.iTl.iX += (TInt) (wRatio * static_cast(dl)); + aViewport.iTl.iY += (TInt) (hRatio * static_cast(dt)); + break; + case EVideoRotationClockwise180: + aViewport.iBr.iX -= (TInt) (wRatio * static_cast(dl)); + aViewport.iBr.iY -= (TInt) (hRatio * static_cast(dt)); + aViewport.iTl.iX += (TInt) (wRatio * static_cast(dr)); + aViewport.iTl.iY += (TInt) (hRatio * static_cast(db)); + break; + case EVideoRotationClockwise90: + aViewport.iBr.iX -= (TInt) (wRatio * static_cast(db)); + aViewport.iBr.iY -= (TInt) (hRatio * static_cast(dl)); + aViewport.iTl.iX += (TInt) (wRatio * static_cast(dt)); + aViewport.iTl.iY += (TInt) (hRatio * static_cast(dr)); + break; + case EVideoRotationClockwise270: + aViewport.iBr.iX -= (TInt) (wRatio * static_cast(dt)); + aViewport.iBr.iY -= (TInt) (hRatio * static_cast(dr)); + aViewport.iTl.iX += (TInt) (wRatio * static_cast(db)); + aViewport.iTl.iY += (TInt) (hRatio * static_cast(dl)); + break; + default: + // Should never get to default unless there's been some programming error. + User::Invariant(); + break; + } + + // Clip the extent. + aExtent.Intersection(viewableArea); + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CalculateExtentAndViewport ---")); + } + +TBool CMediaClientVideoDisplayBody::IsUsed() const + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::IsUsed +++")); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::IsUsed ---")); + return (iEventHandler != NULL || iWindows.Count() > 0); + } + + +TBool CMediaClientVideoDisplayBody::IsSurfaceCreated() const + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::IsSurfaceCreated +++")); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::IsSurfaceCreated ---")); + return !(iSurfaceId.IsNull()); + } + +TInt CMediaClientVideoDisplayBody::DisplayId() const + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::DisplayId +++")); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::DisplayId ---")); + return iDisplayId; + } + +TInt CMediaClientVideoDisplayBody::CompareByDisplay(const TInt* aDisplayId, const CMediaClientVideoDisplayBody& aDisplay) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CompareByDisplay +++")); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CompareByDisplay ---")); + return (*aDisplayId - aDisplay.DisplayId()); + } + +TInt CMediaClientVideoDisplayBody::Compare(const CMediaClientVideoDisplayBody& aLeft, const CMediaClientVideoDisplayBody& aRight) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::Compare +++")); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::Compare ---")); + return (aLeft.DisplayId() - aRight.DisplayId()); + } + +CFbsBitGc::TGraphicsOrientation CMediaClientVideoDisplayBody::ConvertRotation(TVideoRotation aRotation) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::ConvertRotation +++")); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::ConvertRotation ---")); + switch(aRotation) + { + case EVideoRotationNone: + return CFbsBitGc::EGraphicsOrientationNormal; + case EVideoRotationClockwise90: + return CFbsBitGc::EGraphicsOrientationRotated270; + case EVideoRotationClockwise180: + return CFbsBitGc::EGraphicsOrientationRotated180; + case EVideoRotationClockwise270: + return CFbsBitGc::EGraphicsOrientationRotated90; + default: + // Should never get to default unless there's been some programming error. + User::Invariant(); + // This is never reached, just to keep the compiler happy + return CFbsBitGc::EGraphicsOrientationNormal; + } + } + +CMediaClientVideoDisplayBody* CMediaClientVideoDisplayBody::FindDisplayWithWindowL(const RPointerArray& aDisplays, const RWindowBase& aWindow) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::FindDisplayWithWindowL +++")); + TInt count = aDisplays.Count(); + + for (TInt i = 0; i < count; ++i) + { + CMediaClientVideoDisplayBody* display = aDisplays[i]; + + if (display->iWindows.Find(aWindow.WsHandle(), TWindowData::CompareByWsHandle) != KErrNotFound) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::FindDisplayWithWindowL ---")); + return display; + } + } + + User::Leave(KErrNotFound); + return NULL; + } + +RArray& CMediaClientVideoDisplayBody::Windows() + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::Windows +++")); + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::Windows ---")); + return iWindows; + } + +void CMediaClientVideoDisplayBody::MedcpcExtDisplayCalculateExtentAndViewportL(TRect& aExtent, TRect& aViewport, TRect& aExternalDisplayRect) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::MedcpcExtDisplayCalculateExtentAndViewportL +++")); + + TWindowData windowData; + windowData.iVideoExtent = aExternalDisplayRect; + windowData.iRotation = EVideoRotationNone; + windowData.iAutoScaleType = EAutoScaleBestFit; + windowData.iHorizPos = EHorizontalAlignCenter; + windowData.iVertPos = EVerticalAlignCenter; + windowData.iClipRect = aExternalDisplayRect; + + aViewport = iCropRect; + // Viewport is 0 size, don't show any video + if (aViewport.Width() <= 0 || aViewport.Height() <= 0) + { + User::Leave(KErrArgument); + } + + CalculateExtentAndViewport(windowData, aExtent, aViewport); + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::MedcpcExtDisplayCalculateExtentAndViewportL ---")); + } + +void CMediaClientVideoDisplayBody::CreateExtDisplayConnProvAndRemoveSurfaceL(TBool aRemoveBackgroundSurface) + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CreateExtDisplayConnProvAndRemoveSurfaceL +++")); + + if((iExtDisplayConnectionProvider == NULL) && (iWindows.Count() > 0)) + { + iExtDisplayConnectionProvider = CExtDisplayConnectionProviderInterface::NewL(*this, iSurfaceId); + iExtDisplayConnected = iExtDisplayConnectionProvider->ExtDisplayConnectedL(); + + if(iExtDisplayConnected && aRemoveBackgroundSurface) + { + RemoveBackgroundSurface(ETrue); + } + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::CreateExtDisplayConnProvAndRemoveSurfaceL ---")); + } + +void CMediaClientVideoDisplayBody::RemoveExtDisplayConnProvAndRedrawL() + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveExtDisplayConnProvAndRedrawL +++")); + + if(iExtDisplayConnectionProvider != NULL) + { + delete iExtDisplayConnectionProvider; + REComSession::FinalClose(); + iExtDisplayConnectionProvider = NULL; + iExtDisplayConnected = EFalse; + User::LeaveIfError(RedrawWindows(iCropRegion)); + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveExtDisplayConnProvAndRedrawL ---")); + } + +void CMediaClientVideoDisplayBody::RemoveExtDisplayConnProv() + { + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveExtDisplayConnProv +++")); + + if(iExtDisplayConnectionProvider != NULL) + { + delete iExtDisplayConnectionProvider; + REComSession::FinalClose(); + iExtDisplayConnectionProvider = NULL; + iExtDisplayConnected = EFalse; + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::RemoveExtDisplayConnProv ---")); + } + +void CMediaClientVideoDisplayBody::SetExternalDisplaySwitchingL(TBool aControl) + { + DEBUG_PRINT2(_L("CMediaClientVideoDisplayBody::SetExternalDisplaySwitchingL +++ aControl=%d"), aControl); + + // not supported + if(!iExtDisplaySwitchingSupported) + { + User::Leave(KErrNotSupported); + } + + // need active scheduler installed + if(CActiveScheduler::Current() == NULL) + { + User::Leave(KErrNotReady); + } + + if(iClientRequestedExtDisplaySwitching != aControl) + { + iClientRequestedExtDisplaySwitching = aControl; + + if(IsSurfaceCreated()) + { + if(iClientRequestedExtDisplaySwitching) + { + CreateExtDisplayConnProvAndRemoveSurfaceL(ETrue); + } + else + { + RemoveExtDisplayConnProvAndRedrawL(); + } + } + else + { + DEBUG_PRINT(_L("No Surface exists")); + } + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::SetExternalDisplaySwitchingL ---")); + } + +void CMediaClientVideoDisplayBody::MedcpcExtDisplayNotifyConnected(TBool aExtDisplayConnected) + { + DEBUG_PRINT2(_L("CMediaClientVideoDisplayBody::MedcpcExtDisplayNotifyConnected +++ aExtDisplayConnected=%d"), aExtDisplayConnected); + + if(iExtDisplayConnected != aExtDisplayConnected) + { + iExtDisplayConnected = aExtDisplayConnected; + if(iExtDisplayConnected) + { + RemoveBackgroundSurface(ETrue); + } + else + { + // ignore error - no need to tell provider - but lets log it in case it fails + TInt err = RedrawWindows(iCropRegion); + DEBUG_PRINT2(_L("RedrawWindows returned with %d"), err); + } + } + else + { + DEBUG_PRINT(_L("No change in ext display connection status")); + } + + DEBUG_PRINT(_L("CMediaClientVideoDisplayBody::MedcpcExtDisplayNotifyConnected ---")); + }