sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32test\multimedia\t_camera_display.cpp sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "t_camera_display.h" sl@0: sl@0: _LIT(KFrameSizeConfTitle,"Current frame size :"); sl@0: _LIT(KFrameSize, " %d x %d"); sl@0: sl@0: #define CLIP(a) if (a < 0) a = 0; else if (a > 255) a = 255; sl@0: sl@0: /** sl@0: Constructor sl@0: */ sl@0: TCamDisplayHandler::TCamDisplayHandler() sl@0: {} sl@0: sl@0: /** sl@0: Initialise the display handler. sl@0: @return KErrNone if write was successful, otherwise one of the other system wide error codes. sl@0: */ sl@0: TInt TCamDisplayHandler::Init() sl@0: { sl@0: TScreenInfoV01 screenInfo; sl@0: TPckg screenInfoBuf(screenInfo); sl@0: UserSvr::ScreenInfo(screenInfoBuf); sl@0: iVideoAddress = (TUint8*) screenInfo.iScreenAddress; sl@0: iScreenWidth = screenInfo.iScreenSize.iWidth; sl@0: iScreenHeight = screenInfo.iScreenSize.iHeight; sl@0: sl@0: TPckgBuf videoInfoBuf; sl@0: UserSvr::HalFunction(EHalGroupDisplay, EDisplayHalCurrentModeInfo, &videoInfoBuf, NULL); sl@0: iBitsPerPixel = videoInfoBuf().iBitsPerPixel; sl@0: sl@0: return(KErrNone); sl@0: } sl@0: sl@0: TInt TCamDisplayHandler::Min(TInt aA, TInt aB) sl@0: { sl@0: return (aA < aB) ? aA : aB; sl@0: } sl@0: sl@0: TInt TCamDisplayHandler::SetConfig(const SDevCamFrameSize& aSize,const SDevCamPixelFormat& aPixelFormat) sl@0: { sl@0: if (aPixelFormat.iPixelFormat==EUidPixelFormatYUV_422Interleaved || aPixelFormat.iPixelFormat==EUidPixelFormatRGB_565) sl@0: iPixelFormat=aPixelFormat; sl@0: else sl@0: return(KErrArgument); sl@0: sl@0: iWidth = aSize.iWidth; sl@0: iHeight = aSize.iHeight; sl@0: sl@0: return(KErrNone); sl@0: } sl@0: sl@0: /** sl@0: Post process a received image. sl@0: @return KErrNone if write was successful, otherwise one of the other system wide error codes. sl@0: */ sl@0: TInt TCamDisplayHandler::Process(TUint8* aImageBaseAddress) sl@0: { sl@0: switch (iPixelFormat.iPixelFormat) sl@0: { sl@0: case EUidPixelFormatYUV_422Interleaved: sl@0: return(ProcessYUV422(aImageBaseAddress)); sl@0: case EUidPixelFormatRGB_565: sl@0: return(ProcessRGB565(aImageBaseAddress)); sl@0: default: sl@0: return(KErrNotSupported); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Post process a received RGB565 image. sl@0: @return KErrNone if write was successful, otherwise one of the other system wide error codes. sl@0: */ sl@0: TInt TCamDisplayHandler::ProcessRGB565(TUint8* aImageBaseAddress) sl@0: { sl@0: TUint16* source = (TUint16*) aImageBaseAddress; sl@0: TUint16 pixel; sl@0: TInt sourceModulo, destModulo, width, height; sl@0: TInt r = KErrNone; sl@0: sl@0: // Determine whether the screen or the picture to display is the widest, and calculate modulos sl@0: // and clipping sizes appropriately sl@0: if (iWidth < iScreenWidth) sl@0: { sl@0: width = iWidth; sl@0: sourceModulo = 0; sl@0: destModulo = (iScreenWidth - iWidth); sl@0: } sl@0: else sl@0: { sl@0: width = iScreenWidth; sl@0: sourceModulo = (iWidth - iScreenWidth); sl@0: destModulo = 0; sl@0: } sl@0: sl@0: // Determine whether the screen or the picture to display is the highest sl@0: height = (iHeight < iScreenHeight) ? iHeight : iScreenHeight; sl@0: sl@0: if (iBitsPerPixel == 16) sl@0: { sl@0: TUint16* dest = (TUint16*) iVideoAddress; sl@0: sl@0: // Loop around and copy the data directly onto the screen sl@0: for (TInt line = 0; line < height; ++line) sl@0: { sl@0: for (TInt x = 0; x < width; ++x) sl@0: { sl@0: *dest++ = *source++; sl@0: } sl@0: sl@0: source += sourceModulo; sl@0: dest += destModulo; sl@0: } sl@0: } sl@0: else if (iBitsPerPixel == 32) sl@0: { sl@0: TUint8* dest = iVideoAddress; sl@0: sl@0: destModulo *= 4; sl@0: sl@0: // Loop around and convert whatever part of the picture will fit onto the screen into BGRA, sl@0: // writing it directly onto the screen sl@0: for (TInt line = 0; line < height; ++line) sl@0: { sl@0: for (TInt x = 0; x < width; ++x) sl@0: { sl@0: pixel = *source++; sl@0: *dest++= (TUint8) ((pixel & 0x001f) << 3); sl@0: *dest++= (TUint8) ((pixel & 0x07e0) >> 3); sl@0: *dest++= (TUint8) ((pixel & 0xf800) >> 8); sl@0: *dest++ = 0xff; sl@0: } sl@0: sl@0: source += sourceModulo; sl@0: dest += destModulo; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: r = KErrNotSupported; sl@0: } sl@0: sl@0: return r; sl@0: } sl@0: sl@0: /** sl@0: Post process a received YUV422 image. sl@0: @return KErrNone if write was successful, otherwise one of the other system wide error codes. sl@0: */ sl@0: TInt TCamDisplayHandler::ProcessYUV422(TUint8* aImageBaseAddress) sl@0: { sl@0: TUint16* dest16 = (TUint16*) iVideoAddress; sl@0: TUint32* dest32 = (TUint32*) iVideoAddress; sl@0: TUint8* source = aImageBaseAddress; sl@0: TInt y, u, v, r, g, b, sourceModulo, destModulo, width, height; sl@0: TInt retVal = KErrNone; sl@0: sl@0: // Determine whether the screen or the picture to display is the widest, and calculate modulos sl@0: // and clipping sizes appropriately sl@0: if (iWidth < iScreenWidth) sl@0: { sl@0: width = (iWidth / 2); sl@0: sourceModulo = 0; sl@0: destModulo = (iScreenWidth - iWidth); sl@0: } sl@0: else sl@0: { sl@0: width = (iScreenWidth / 2); sl@0: sourceModulo = ((iWidth - iScreenWidth) * 2); sl@0: destModulo = 0; sl@0: } sl@0: sl@0: // Determine whether the screen or the picture to display is the highest sl@0: height = (iHeight < iScreenHeight) ? iHeight : iScreenHeight; sl@0: sl@0: // Only 16 and 32 bits per pixel are supported. It is also assumed that 16 bit will be RGB565 and sl@0: // 32 bit will be BGRA. You will need to add support for new formats if required sl@0: if ((iBitsPerPixel == 16) || (iBitsPerPixel == 32)) sl@0: { sl@0: // Loop around and convert whatever part of the picture will fit onto the screen into RGB565 or BGRA, sl@0: // writing it directly onto the screen sl@0: for (TInt line = 0; line < height; ++line) sl@0: { sl@0: for (TInt x = 0; x < width; ++x) sl@0: { sl@0: u = (source[0] - 128); sl@0: v = (source[2] - 128); sl@0: y = (source[3] - 16); sl@0: sl@0: r = ((298 * y + 409 * u) / 256); sl@0: g = ((298 * y - 100 * v - 208 * u) / 256); sl@0: b = ((298 * y + 516 * v) / 256); sl@0: sl@0: CLIP(r); sl@0: CLIP(g); sl@0: CLIP(b); sl@0: sl@0: if (iBitsPerPixel == 16) sl@0: { sl@0: *dest16++ = (TUint16) (((b & 0xf8) << 8) | ((g & 0xfc) << 3) | ((r & 0xf8) >> 3)); sl@0: } sl@0: else sl@0: { sl@0: *dest32++ = (0xff000000 | (r << 16) | (g << 8) | b); sl@0: } sl@0: sl@0: y = (source[1] - 16); sl@0: sl@0: r = ((298 * y + 409 * u) / 256); sl@0: g = ((298 * y - 100 * v - 208 * u) / 256); sl@0: b = ((298 * y + 516 * v) / 256); sl@0: sl@0: CLIP(r); sl@0: CLIP(g); sl@0: CLIP(b); sl@0: sl@0: if (iBitsPerPixel == 16) sl@0: { sl@0: *dest16++ = (TUint16) (((b & 0xf8) << 8) | ((g & 0xfc) << 3) | ((r & 0xf8) >> 3)); sl@0: } sl@0: else sl@0: { sl@0: *dest32++ = (0xff000000 | (r << 16) | (g << 8) | b); sl@0: } sl@0: sl@0: source += 4; sl@0: } sl@0: sl@0: source += sourceModulo; sl@0: dest16 += destModulo; sl@0: dest32 += destModulo; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: retVal = KErrNotSupported; sl@0: } sl@0: sl@0: return retVal; sl@0: } sl@0: sl@0: /** sl@0: Appends a string representing a pixel format UID onto a descriptor. sl@0: @param aBuffer Reference to the descriptor into which to append the string. It is up to the sl@0: caller to ensure that this is large enough. sl@0: @param aPixelFormat UID of the pixel format to be converted into a string. sl@0: */ sl@0: void AppendPixelFormat(TDes& aBuffer, TUidPixelFormat aPixelFormat) sl@0: { sl@0: if (aPixelFormat == EUidPixelFormatRGB_565) sl@0: aBuffer.Append(KPixelFormatRGB_565); sl@0: else if (aPixelFormat == EUidPixelFormatYUV_422Interleaved) sl@0: aBuffer.Append(KPixelFormatYUV_422Interleaved); sl@0: else if (aPixelFormat == EUidPixelFormatSpeedTaggedJPEG) sl@0: aBuffer.Append(KPixelFormatSpeedTaggedJPEG); sl@0: else if (aPixelFormat == EUidPixelFormatJPEG) sl@0: aBuffer.Append(KPixelFormatJPEG); sl@0: else sl@0: aBuffer.Append(KPixelFormatUnknown); sl@0: } sl@0: sl@0: void PrintCamModes(TCameraCapsV02* aCaps,RTest& aTest) sl@0: { sl@0: TBuf<80> buf; sl@0: sl@0: // Display the supported capture modes sl@0: buf.Zero(); sl@0: buf.Append(KCaptureModeCapsTitle); sl@0: if (aCaps->iNumImagePixelFormats) sl@0: buf.Append(KCaptureModeImage); sl@0: if (aCaps->iNumVideoPixelFormats) sl@0: buf.Append(KCaptureModeVideo); sl@0: if (aCaps->iNumViewFinderPixelFormats) sl@0: buf.Append(KCaptureModeViewFinder); sl@0: buf.Append(_L("\r\n")); sl@0: aTest.Printf(buf); sl@0: sl@0: // Display the supported video pixel formats sl@0: TUint i; sl@0: SDevCamPixelFormat* pixelFormat; sl@0: if (aCaps->iNumImagePixelFormats) sl@0: { sl@0: buf.Zero(); sl@0: buf.Append(KPixelFormatCapsTitle); sl@0: buf.Append(KCaptureModeImage); sl@0: pixelFormat = (SDevCamPixelFormat*) (aCaps + 1); sl@0: for (i = 0; i < aCaps->iNumImagePixelFormats; i++) sl@0: { sl@0: AppendPixelFormat(buf, pixelFormat->iPixelFormat); sl@0: pixelFormat++; sl@0: } sl@0: buf.Append(_L("\r\n")); sl@0: aTest.Printf(buf); sl@0: } sl@0: sl@0: if (aCaps->iNumVideoPixelFormats) sl@0: { sl@0: buf.Zero(); sl@0: buf.Append(KPixelFormatCapsTitle); sl@0: buf.Append(KCaptureModeVideo); sl@0: pixelFormat = (SDevCamPixelFormat*) (aCaps + 1); sl@0: for (i = aCaps->iNumImagePixelFormats; i < (aCaps->iNumImagePixelFormats + aCaps->iNumVideoPixelFormats); i++) sl@0: { sl@0: AppendPixelFormat(buf, pixelFormat->iPixelFormat); sl@0: pixelFormat++; sl@0: } sl@0: buf.Append(_L("\r\n")); sl@0: aTest.Printf(buf); sl@0: } sl@0: sl@0: if (aCaps->iNumViewFinderPixelFormats) sl@0: { sl@0: buf.Zero(); sl@0: buf.Append(KPixelFormatCapsTitle); sl@0: buf.Append(KCaptureModeViewFinder); sl@0: pixelFormat = (SDevCamPixelFormat*) (aCaps + 1); sl@0: i = aCaps->iNumImagePixelFormats + aCaps->iNumImagePixelFormats + 1; sl@0: for (i = aCaps->iNumImagePixelFormats + aCaps->iNumVideoPixelFormats; i < (aCaps->iNumImagePixelFormats + aCaps->iNumVideoPixelFormats + aCaps->iNumViewFinderPixelFormats); i++) sl@0: { sl@0: AppendPixelFormat(buf, pixelFormat->iPixelFormat); sl@0: pixelFormat++; sl@0: } sl@0: buf.Append(_L("\r\n")); sl@0: aTest.Printf(buf); sl@0: } sl@0: } sl@0: sl@0: void PrintCamConf(TCameraConfigV02& aConf,RTest& aTest) sl@0: { sl@0: TBuf<80> buf; sl@0: sl@0: // Display the current frame size sl@0: buf.Zero(); sl@0: buf.Append(KFrameSizeConfTitle); sl@0: buf.AppendFormat(KFrameSize, aConf.iFrameSize.iWidth, aConf.iFrameSize.iHeight); sl@0: buf.Append(_L("\r\n")); sl@0: aTest.Printf(buf); sl@0: sl@0: // Display the current pixel format sl@0: buf.Zero(); sl@0: buf.Append(KPixelFormatConfTitle); sl@0: AppendPixelFormat(buf, aConf.iPixelFormat.iPixelFormat); sl@0: buf.Append(_L("\r\n")); sl@0: aTest.Printf(buf); sl@0: sl@0: // Display the current frame rate sl@0: buf.Zero(); sl@0: buf.Format(_L("Current frame rate : %d fps\r\n"),aConf.iFrameRate); sl@0: aTest.Printf(buf); sl@0: } sl@0: sl@0: void PrintBufferConf(TMmSharedChunkBufConfig& aBufConf,RTest& aTest) sl@0: { sl@0: TBuf<80> buf(0); sl@0: sl@0: SBufSpecList* tempSpec = aBufConf.iSpec; sl@0: sl@0: // Display the buffer configuration sl@0: buf.Format(_L("Buffer Config : NumBufs:%d Size:%xH\r\n"),aBufConf.iNumBuffers,aBufConf.iBufferSizeInBytes); sl@0: aTest.Printf(buf); sl@0: if (aBufConf.iFlags & KScFlagBufOffsetListInUse) sl@0: { sl@0: buf.Format(_L(" Offsets[%08xH,%08xH,%08xH,%08xH]\r\n"),tempSpec[0].iBufferOffset,tempSpec[1].iBufferOffset,tempSpec[2].iBufferOffset,tempSpec[3].iBufferOffset); sl@0: aTest.Printf(buf); sl@0: buf.Format(_L(" Offsets[%08xH,%08xH,%08xH,%08xH]\r\n"),tempSpec[4].iBufferOffset,tempSpec[5].iBufferOffset,tempSpec[6].iBufferOffset,tempSpec[7].iBufferOffset); sl@0: aTest.Printf(buf); sl@0: } sl@0: }