1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 /** 17 **************************************************************************************** 18 * @file M4VIFI_BGR565toYUV420.c 19 * @brief Contain video library function 20 * @note Color Conversion Filter 21 * -# Contains the format conversion filters from BGR565 to YUV420 22 **************************************************************************************** 23 */ 24 25 /* Prototypes of functions, and type definitions */ 26 #include "M4VIFI_FiltersAPI.h" 27 /* Macro definitions */ 28 #include "M4VIFI_Defines.h" 29 /* Clip table declaration */ 30 #include "M4VIFI_Clip.h" 31 32 /** 33 ***************************************************************************************** 34 * M4VIFI_UInt8 M4VIFI_BGR565toYUV420 (void *pUserData, M4VIFI_ImagePlane *pPlaneIn, 35 * M4VIFI_ImagePlane *pPlaneOut) 36 * @brief Transform BGR565 image to a YUV420 image. 37 * @note Convert BGR565 to YUV420, 38 * Loop on each row ( 2 rows by 2 rows ) 39 * Loop on each column ( 2 col by 2 col ) 40 * Get 4 BGR samples from input data and build 4 output Y samples 41 * and each single U & V data 42 * end loop on col 43 * end loop on row 44 * @param pUserData: (IN) User Specific Data 45 * @param pPlaneIn: (IN) Pointer to BGR565 Plane 46 * @param pPlaneOut: (OUT) Pointer to YUV420 buffer Plane 47 * @return M4VIFI_OK: there is no error 48 * @return M4VIFI_ILLEGAL_FRAME_HEIGHT: YUV Plane height is ODD 49 * @return M4VIFI_ILLEGAL_FRAME_WIDTH: YUV Plane width is ODD 50 ***************************************************************************************** 51 */ 52 53 M4VIFI_UInt8 M4VIFI_BGR565toYUV420(void *pUserData, M4VIFI_ImagePlane *pPlaneIn, 54 M4VIFI_ImagePlane *pPlaneOut) 55 { 56 M4VIFI_UInt32 u32_width, u32_height; 57 M4VIFI_UInt32 u32_stride_Y, u32_stride2_Y, u32_stride_U, u32_stride_V; 58 M4VIFI_UInt32 u32_stride_bgr, u32_stride_2bgr; 59 M4VIFI_UInt32 u32_col, u32_row; 60 61 M4VIFI_Int32 i32_r00, i32_r01, i32_r10, i32_r11; 62 M4VIFI_Int32 i32_g00, i32_g01, i32_g10, i32_g11; 63 M4VIFI_Int32 i32_b00, i32_b01, i32_b10, i32_b11; 64 M4VIFI_Int32 i32_y00, i32_y01, i32_y10, i32_y11; 65 M4VIFI_Int32 i32_u00, i32_u01, i32_u10, i32_u11; 66 M4VIFI_Int32 i32_v00, i32_v01, i32_v10, i32_v11; 67 M4VIFI_UInt8 *pu8_yn, *pu8_ys, *pu8_u, *pu8_v; 68 M4VIFI_UInt8 *pu8_y_data, *pu8_u_data, *pu8_v_data; 69 M4VIFI_UInt8 *pu8_bgrn_data, *pu8_bgrn; 70 M4VIFI_UInt16 u16_pix1, u16_pix2, u16_pix3, u16_pix4; 71 72 /* Check planes height are appropriate */ 73 if( (pPlaneIn->u_height != pPlaneOut[0].u_height) || 74 (pPlaneOut[0].u_height != (pPlaneOut[1].u_height<<1)) || 75 (pPlaneOut[0].u_height != (pPlaneOut[2].u_height<<1))) 76 { 77 return M4VIFI_ILLEGAL_FRAME_HEIGHT; 78 } 79 80 /* Check planes width are appropriate */ 81 if( (pPlaneIn->u_width != pPlaneOut[0].u_width) || 82 (pPlaneOut[0].u_width != (pPlaneOut[1].u_width<<1)) || 83 (pPlaneOut[0].u_width != (pPlaneOut[2].u_width<<1))) 84 { 85 return M4VIFI_ILLEGAL_FRAME_WIDTH; 86 } 87 88 /* Set the pointer to the beginning of the output data buffers */ 89 pu8_y_data = pPlaneOut[0].pac_data + pPlaneOut[0].u_topleft; 90 pu8_u_data = pPlaneOut[1].pac_data + pPlaneOut[1].u_topleft; 91 pu8_v_data = pPlaneOut[2].pac_data + pPlaneOut[2].u_topleft; 92 93 /* Set the pointer to the beginning of the input data buffers */ 94 pu8_bgrn_data = pPlaneIn->pac_data + pPlaneIn->u_topleft; 95 96 /* Get the size of the output image */ 97 u32_width = pPlaneOut[0].u_width; 98 u32_height = pPlaneOut[0].u_height; 99 100 /* Set the size of the memory jumps corresponding to row jump in each output plane */ 101 u32_stride_Y = pPlaneOut[0].u_stride; 102 u32_stride2_Y = u32_stride_Y << 1; 103 u32_stride_U = pPlaneOut[1].u_stride; 104 u32_stride_V = pPlaneOut[2].u_stride; 105 106 /* Set the size of the memory jumps corresponding to row jump in input plane */ 107 u32_stride_bgr = pPlaneIn->u_stride; 108 u32_stride_2bgr = u32_stride_bgr << 1; 109 110 /* Loop on each row of the output image, input coordinates are estimated from output ones */ 111 /* Two YUV rows are computed at each pass */ 112 for (u32_row = u32_height ;u32_row != 0; u32_row -=2) 113 { 114 /* Current Y plane row pointers */ 115 pu8_yn = pu8_y_data; 116 /* Next Y plane row pointers */ 117 pu8_ys = pu8_yn + u32_stride_Y; 118 /* Current U plane row pointer */ 119 pu8_u = pu8_u_data; 120 /* Current V plane row pointer */ 121 pu8_v = pu8_v_data; 122 123 pu8_bgrn = pu8_bgrn_data; 124 125 /* Loop on each column of the output image */ 126 for (u32_col = u32_width; u32_col != 0 ; u32_col -=2) 127 { 128 /* Get four BGR 565 samples from input data */ 129 u16_pix1 = *( (M4VIFI_UInt16 *) pu8_bgrn); 130 u16_pix2 = *( (M4VIFI_UInt16 *) (pu8_bgrn + CST_RGB_16_SIZE)); 131 u16_pix3 = *( (M4VIFI_UInt16 *) (pu8_bgrn + u32_stride_bgr)); 132 u16_pix4 = *( (M4VIFI_UInt16 *) (pu8_bgrn + u32_stride_bgr + CST_RGB_16_SIZE)); 133 /* Unpack RGB565 to 8bit R, G, B */ 134 /* (x,y) */ 135 GET_BGR565(i32_b00, i32_g00, i32_r00, u16_pix1); 136 /* (x+1,y) */ 137 GET_BGR565(i32_b10, i32_g10, i32_r10, u16_pix2); 138 /* (x,y+1) */ 139 GET_BGR565(i32_b01, i32_g01, i32_r01, u16_pix3); 140 /* (x+1,y+1) */ 141 GET_BGR565(i32_b11, i32_g11, i32_r11, u16_pix4); 142 143 /* Convert BGR value to YUV */ 144 i32_u00 = U16(i32_r00, i32_g00, i32_b00); 145 i32_v00 = V16(i32_r00, i32_g00, i32_b00); 146 /* luminance value */ 147 i32_y00 = Y16(i32_r00, i32_g00, i32_b00); 148 149 i32_u10 = U16(i32_r10, i32_g10, i32_b10); 150 i32_v10 = V16(i32_r10, i32_g10, i32_b10); 151 /* luminance value */ 152 i32_y10 = Y16(i32_r10, i32_g10, i32_b10); 153 154 i32_u01 = U16(i32_r01, i32_g01, i32_b01); 155 i32_v01 = V16(i32_r01, i32_g01, i32_b01); 156 /* luminance value */ 157 i32_y01 = Y16(i32_r01, i32_g01, i32_b01); 158 159 i32_u11 = U16(i32_r11, i32_g11, i32_b11); 160 i32_v11 = V16(i32_r11, i32_g11, i32_b11); 161 /* luminance value */ 162 i32_y11 = Y16(i32_r11, i32_g11, i32_b11); 163 164 /* Store luminance data */ 165 pu8_yn[0] = (M4VIFI_UInt8)i32_y00; 166 pu8_yn[1] = (M4VIFI_UInt8)i32_y10; 167 pu8_ys[0] = (M4VIFI_UInt8)i32_y01; 168 pu8_ys[1] = (M4VIFI_UInt8)i32_y11; 169 170 /* Store chroma data */ 171 *pu8_u = (M4VIFI_UInt8)((i32_u00 + i32_u01 + i32_u10 + i32_u11 + 2) >> 2); 172 *pu8_v = (M4VIFI_UInt8)((i32_v00 + i32_v01 + i32_v10 + i32_v11 + 2) >> 2); 173 174 /* Prepare for next column */ 175 pu8_bgrn += (CST_RGB_16_SIZE<<1); 176 /* Update current Y plane line pointer*/ 177 pu8_yn += 2; 178 /* Update next Y plane line pointer*/ 179 pu8_ys += 2; 180 /* Update U plane line pointer*/ 181 pu8_u ++; 182 /* Update V plane line pointer*/ 183 pu8_v ++; 184 } /* End of horizontal scanning */ 185 186 /* Prepare pointers for the next row */ 187 pu8_y_data += u32_stride2_Y; 188 pu8_u_data += u32_stride_U; 189 pu8_v_data += u32_stride_V; 190 pu8_bgrn_data += u32_stride_2bgr; 191 192 } /* End of vertical scanning */ 193 194 return M4VIFI_OK; 195 } 196 /* End of file M4VIFI_BGR565toYUV420.c */ 197 198