📄 omxipcs_cbycry422toycbcr420rotate_u8_c2p3r.c
字号:
/** * * * File Name: omxIPCS_CbYCrY422ToYCbCr420Rotate_U8_C2P3R.c * OpenMAX DL: v1.0.2 * Revision: 10586 * Date: Wednesday, March 5, 2008 * * (c) Copyright 2007-2008 ARM Limited. All Rights Reserved. * * * * Description : Integrated Colour Space Conversion and Rotate Routine. The Source is * in two-channel pixel domain format and the destination is in * three-channel, planar domain format. * */#include "omxtypes.h"#include "armOMX.h"#include "omxIP.h"#include "armCOMM.h"#include "armIP.h"/** * Function: omxIPCS_CbYCrY422ToYCbCr420Rotate_U8_C2P3R (4.4.3.6.1) * * Description: * CbYCrY422 to YCbCr420 planar format conversion with rotation function. * This function decimates the color space of the input image from CbYCrY 422 * to YCbCr 420, applies an optional rotation of -90, +90, or 180 degrees, and * then rearranges the data from the pixel-oriented input format to a planar * output format. * The size of output image: if roiSize.width or roiSize.height cannot be * divided by 8 exactly, it will be cut to be a multiple of 8. * * Input Arguments: * * pSrc - pointer to the start of the buffer containing the pixel-oriented * CbYCrY422 input; must be aligned on an 8-byte boundary. * srcStep - distance, in bytes, between the start of lines in the source * image; must be a multiple of 8. * dstStep - a 3-element vector containing the distance, in bytes, between * the start of lines in each of the output image planes. The * parameter dstStep[0] must be a multiple of 8; the parameters * dstStep[1] and dstStep[2] must be multiples of 4. * roiSize - dimensions, in pixels, of the source and destination regions * of interest * rotation - rotation control parameter; must be set to one of the * following pre-defined values: OMX_IP_DISABLE, OMX_IP_ROTATE90L, * OMX_IP_ROTATE90R, or OMX_IP_ROTATE180. OutputArguments * * Output Arguments: * pDst - a 3-element vector containing pointers to the start of each of * the YCbCr420 output planes. The pointer pDst[0] must be aligned * on an 8-byte boundary. The pointers pDst[1] and pDst[2]must be * aligned on 4-byte boundaries. * * Return Value: * If the function runs without error, it returns OMX_Sts_NoErr * If any of the following cases occurs, the function returns * OMX_Sts_BadArgErr: * - pSrc, pDst[0], pDst[1], or pDst[2] is NULL * - pSrc or pDst[0] is not aligned at 8 bytes boundary * - pDst[1] or pDst[2] is not aligned at 4-byte boundary * - srcStep, dstStep[1], dstStep[2], or dstStep[3] is less than 1 * - srcStep or dstStep[0] is not multiple of 8 * - dstStep[1] or dstStep[2] is not multiple of 4 * - roiSize.width is larger than half of srcStep * - rotation contains an invalid control parameter * - dstStep[0] is less than roiSize.width * - dstStep[1] or dstStep[2] is less than half roiSize.width * - roiSize.width or roiSize.height is less than 8 * */ OMXResult omxIPCS_CbYCrY422ToYCbCr420Rotate_U8_C2P3R( const OMX_U8 *pSrc, OMX_INT srcStep, OMX_U8 *pDst[3], OMX_INT dstStep[3], OMXSize roiSize, OMXIPRotation rotation ){ const OMX_U8 *pSrcRef, *pSrcRef2; OMX_INT chroma, chromaOffset, chromaOffsetRev, i, j; OMX_INT inWidthYUV, outWidthY, outHeightY, outWidthUV, outHeightUV; OMX_U8 *pDstRef; #if ARM_IPCS_INTERP_BILINEAR OMX_S16 interpPix;#endif armRetArgErrIf(!pSrc, OMX_Sts_BadArgErr); armRetArgErrIf(!pDst, OMX_Sts_BadArgErr); armRetArgErrIf(!pDst[0], OMX_Sts_BadArgErr); armRetArgErrIf(!pDst[1], OMX_Sts_BadArgErr); armRetArgErrIf(!pDst[2], OMX_Sts_BadArgErr); armRetArgErrIf(!dstStep, OMX_Sts_BadArgErr); armRetArgErrIf(!armIs8ByteAligned(pSrc), OMX_Sts_BadArgErr); armRetArgErrIf(!armIs8ByteAligned(pDst[0]), OMX_Sts_BadArgErr); armRetArgErrIf(!armIs4ByteAligned(pDst[1]), OMX_Sts_BadArgErr); armRetArgErrIf(!armIs4ByteAligned(pDst[2]), OMX_Sts_BadArgErr); armRetArgErrIf(srcStep < 1, OMX_Sts_BadArgErr); armRetArgErrIf(dstStep[0] < 1, OMX_Sts_BadArgErr); armRetArgErrIf(dstStep[1] < 1, OMX_Sts_BadArgErr); armRetArgErrIf(dstStep[2] < 1, OMX_Sts_BadArgErr); armRetArgErrIf(!armIs8ByteAligned(srcStep), OMX_Sts_BadArgErr); armRetArgErrIf(!armIs8ByteAligned(dstStep[0]), OMX_Sts_BadArgErr); armRetArgErrIf(!armIs4ByteAligned(dstStep[1]), OMX_Sts_BadArgErr); armRetArgErrIf(!armIs4ByteAligned(dstStep[2]), OMX_Sts_BadArgErr); armRetArgErrIf(roiSize.width > srcStep/2, OMX_Sts_BadArgErr); armRetArgErrIf(roiSize.width > dstStep[0], OMX_Sts_BadArgErr); armRetArgErrIf(roiSize.width > 2*dstStep[1], OMX_Sts_BadArgErr); armRetArgErrIf(roiSize.width > 2*dstStep[2], OMX_Sts_BadArgErr); armRetArgErrIf(roiSize.width < 8, OMX_Sts_BadArgErr); armRetArgErrIf(roiSize.height < 8, OMX_Sts_BadArgErr); armRetArgErrIf((rotation != OMX_IP_ROTATE180) && (rotation != OMX_IP_ROTATE90L) && (rotation != OMX_IP_ROTATE90R) && (rotation != OMX_IP_DISABLE), OMX_Sts_BadArgErr); roiSize.height = (roiSize.height >> 3) << 3; roiSize.width = (roiSize.width >> 3) << 3; inWidthYUV = roiSize.width * 2; outHeightY = roiSize.height; outWidthY = roiSize.width; outHeightUV = roiSize.height >> 1; outWidthUV = roiSize.width >> 1; /* ---------------------------------------------------------------------------------- The conversion from Colour Space YCbCr422 to YCbCr420 in planar domain is easier as Y remains unchanged and it is a simple case of interpolation for Cb and Cr planes. This function supports two interpolation methods (Not at the API level, but internally) - namely Nearest Neighbour and Bilinear, by setting a static global variable. The Rotation operation if combined with interpolation, becomes easier to carry out as we'll not have to do it in-place. The formulae for rotation by 180 is: OutPix(x,y) = InPix(width-x,height-y), 90R is: OutPix(y,x) = InPix(width-x,y) and 90L is: OutPix(y,x) = InPix(x,height-y). For each type of rotation, the Luma plane is separately handled but the two Chroma planes (having similar characteristics), are handled together in a loop. --------------------------------------------------------------------------------- */ if(rotation == OMX_IP_ROTATE90R) { pSrcRef = pSrc; pDstRef = pDst[0] + outWidthY - 1; for(i = 0; i < outHeightY; i++) { for(j = 0; j < outWidthY; j++) { pDstRef[dstStep[0] * j] = pSrcRef[2 * j+1]; /* changing from YCbYcr Src to CbYCrY */ } pSrcRef += srcStep; pDstRef--; } for(chroma = 1; chroma <= 2; chroma++) { chromaOffset = (chroma == 1) ? 0 : 2; pSrcRef = pSrc + chromaOffset; pSrcRef2 = pSrc + chromaOffset + srcStep; pDstRef = pDst[chroma] + outHeightUV - 1; for(i = 0; i < outHeightUV; i++) { for(j = 0; j < outWidthUV; j++) {#if ARM_IPCS_INTERP_NEAREST pDstRef[dstStep[chroma] * j] = pSrcRef[4 * j];#elif ARM_IPCS_INTERP_BILINEAR interpPix = armRoundFloatToS16(((OMX_F32)pSrcRef[4 * j] + (OMX_F32)pSrcRef2[4 * j]) / 2); pDstRef[dstStep[chroma] * j] = armClip(OMX_MIN_U8, OMX_MAX_U8, interpPix);#endif } pSrcRef += 2*srcStep; pSrcRef2 += 2*srcStep; pDstRef--; } } } else if(rotation == OMX_IP_ROTATE90L) { pSrcRef = pSrc; pDstRef = pDst[0]; for(i = 0; i < outHeightY; i++) { for(j = 0; j < outWidthY; j++) { pDstRef[dstStep[0] * j] = pSrcRef[inWidthYUV - 1 - (2 * j)]; } pSrcRef += srcStep; pDstRef++; } for(chroma = 1; chroma <= 2; chroma++) { chromaOffsetRev = (chroma == 1) ? 4 : 2; pSrcRef = pSrc; pSrcRef2 = pSrc + srcStep; pDstRef = pDst[chroma]; for(i = 0; i < outHeightUV; i++) { for(j = 0; j < outWidthUV; j++) {#if ARM_IPCS_INTERP_NEAREST pDstRef[dstStep[chroma] * j] = pSrcRef[inWidthYUV - chromaOffsetRev - (4 * j)];#elif ARM_IPCS_INTERP_BILINEAR interpPix = armRoundFloatToS16(((OMX_F32)pSrcRef[inWidthYUV - chromaOffsetRev - (4 * j)] + (OMX_F32)pSrcRef2[inWidthYUV - chromaOffsetRev - (4 * j)]) / 2); pDstRef[dstStep[chroma] * j] = armClip(OMX_MIN_U8, OMX_MAX_U8, interpPix);#endif } pSrcRef += 2*srcStep; pSrcRef2 += 2*srcStep; pDstRef++; } } } else if(rotation == OMX_IP_ROTATE180) { pSrcRef = pSrc; pDstRef = pDst[0] + (outHeightY-1) * dstStep[0]; for(i = 0; i < outHeightY; i++) { for(j = 0; j < outWidthY; j++) { pDstRef[outWidthY - j - 1] = pSrcRef[2 * j + 1]; } pSrcRef += srcStep; pDstRef -= dstStep[0]; } for(chroma = 1; chroma <= 2; chroma++) { chromaOffset = (chroma == 1) ? 0 : 2; pSrcRef = pSrc + chromaOffset; pSrcRef2 = pSrc + chromaOffset + srcStep; pDstRef = pDst[chroma] + (outHeightUV-1) * dstStep[chroma]; for(i = 0; i < outHeightUV; i++) { for(j = 0; j < outWidthUV; j++) {#if ARM_IPCS_INTERP_NEAREST pDstRef[outWidthUV - j - 1] = pSrcRef[4 * j];#elif ARM_IPCS_INTERP_BILINEAR interpPix = armRoundFloatToS16(((OMX_F32)pSrcRef[4 * j] + (OMX_F32)pSrcRef2[4 * j]) / 2); pDstRef[outWidthUV - j - 1] = armClip(OMX_MIN_U8, OMX_MAX_U8, interpPix);#endif } pSrcRef += 2*srcStep; pSrcRef2 += 2*srcStep; pDstRef -= dstStep[chroma]; } } } else if(rotation == OMX_IP_DISABLE) { pSrcRef = pSrc; pDstRef = pDst[0]; for(i = 0; i < outHeightY; i++) { for(j = 0; j < outWidthY; j++) { pDstRef[j] = pSrcRef[j * 2 + 1]; } pSrcRef += srcStep; pDstRef += dstStep[0]; } for(chroma = 1; chroma <= 2; chroma++) { chromaOffset = (chroma == 1) ? 0 : 2; pSrcRef = pSrc + chromaOffset; pSrcRef2 = pSrc + chromaOffset + srcStep; pDstRef = pDst[chroma]; for(i = 0; i < outHeightUV; i++) { for(j = 0; j < outWidthUV; j++) {#if ARM_IPCS_INTERP_NEAREST pDstRef[j] = pSrcRef[4 * j];#elif ARM_IPCS_INTERP_BILINEAR interpPix = armRoundFloatToS16(((OMX_F32)pSrcRef[4 * j] + (OMX_F32)pSrcRef2[4 * j]) / 2); pDstRef[j] = armClip(OMX_MIN_U8, OMX_MAX_U8, interpPix);#endif } pSrcRef += 2*srcStep; pSrcRef2 += 2*srcStep; pDstRef += dstStep[chroma]; } } } return OMX_Sts_NoErr;}/* End of file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -