1 /* ------------------------------------------------------------------ 2 * Copyright (C) 1998-2009 PacketVideo 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 13 * express or implied. 14 * See the License for the specific language governing permissions 15 * and limitations under the License. 16 * ------------------------------------------------------------------- 17 */ 18 //class CPVVideoBlend.cpp 19 #include "pvvideoblend.h" 20 21 // Use default DLL entry point 22 #include "oscl_dll.h" 23 OSCL_DLL_ENTRY_POINT_DEFAULT() 24 25 OSCL_EXPORT_REF CPVVideoBlend* CPVVideoBlend :: New() 26 { 27 CPVVideoBlend *pobj = OSCL_NEW(CPVVideoBlend, ()) ; 28 29 30 return pobj; 31 } 32 33 CPVVideoBlend :: CPVVideoBlend() 34 { 35 int err; 36 37 OSCL_TRY(err, 38 CameraInput = (CCYUV422toYUV420*) CCYUV422toYUV420::New(); 39 BitmapInput = (CCRGB16toYUV420*) CCRGB16toYUV420::New(); 40 DecoderOutput = (ColorConvert16*) ColorConvert16::NewL(); 41 EncoderInput = (ColorConvert16*) ColorConvert16::NewL(); 42 ); 43 44 if (err != OsclErrNone) 45 { 46 OSCL_LEAVE(err); 47 } 48 } 49 50 51 52 OSCL_EXPORT_REF CPVVideoBlend :: ~CPVVideoBlend() 53 { 54 55 } 56 57 58 OSCL_EXPORT_REF int32 CPVVideoBlend::InitInputBlend(PVDimension *frameSize, PVRotationCLKWise rotation) 59 { 60 uint32 width_src, height_src, pitch_src, width_dst, height_dst, pitch_dst; 61 int rot = 0; 62 63 mInitInputBlend = false; 64 65 width_src = frameSize->width; 66 height_src = frameSize->height; 67 pitch_src = frameSize->width; 68 69 switch (rotation) 70 { 71 case Rotation0 : 72 rot = 0; 73 break; 74 case Rotation90 : 75 rot = 3; 76 break; 77 case Rotation180 : 78 rot = 2; 79 break; 80 case Rotation270 : 81 rot = 1; 82 break; 83 } 84 85 if (rotation&1) /* rotation 90 or 270 degree */ 86 { 87 width_dst = height_src; 88 height_dst = width_src; 89 pitch_dst = height_src; 90 } 91 else 92 { 93 width_dst = width_src; 94 height_dst = height_src; 95 pitch_dst = pitch_src; 96 } 97 98 if (!CameraInput->Init(width_src, height_src, pitch_src, width_dst, height_dst, pitch_dst, rot)) 99 { 100 return 0; 101 } 102 103 if (!BitmapInput->Init(width_dst, height_dst, pitch_dst, width_dst, height_dst, pitch_dst, 0)) 104 { 105 return 0; 106 } 107 108 mInitInputBlend = true; 109 110 return 1; 111 } 112 113 // Still need some optimization to save time during the init. 114 // If the param is the same, we shouldn't call init all the time. 115 OSCL_EXPORT_REF int32 CPVVideoBlend :: BlendInput(PVBlendFrame *pCameraInput, PVBitmap *pBitmap, PVBlendFrame *pToEncode) 116 { 117 uint8 *inputRGB; 118 uint8 *outYUV; 119 uint8 *srcBuffer, *dstBuffer; 120 PVYUVFormat format; 121 uint32 width_src, height_src, pitch_src, width_dst, height_dst, pitch_dst; 122 int16 colorkey; 123 124 if (mInitInputBlend == false || (pCameraInput == NULL && pBitmap == NULL) || (pToEncode == NULL)) 125 { 126 return 0; 127 } 128 129 /*********** For YUV422 to YUV420 conversion **********/ 130 if (pCameraInput != NULL) 131 { 132 srcBuffer = pCameraInput->pBuffer; 133 width_src = pCameraInput->width; 134 height_src = pCameraInput->height; 135 format = pCameraInput->format; 136 pitch_src = width_src; 137 138 dstBuffer = pToEncode->pBuffer; 139 Dst_width = pToEncode->width; // 1:1, so equal to source 140 Dst_height = pToEncode->height; // 1:1, so equal to source 141 pitch_dst = pToEncode->width; // width of the destination buffer 142 143 if (format == YUV422) 144 { 145 /* check the buffer size */ 146 if ((pCameraInput->bufSize < pitch_src*height_src*2) || 147 (pToEncode->bufSize < ((pitch_dst*Dst_height*3) >> 1))) 148 { 149 return 0; 150 } 151 152 /* perform the conversion */ 153 if (!CameraInput->Convert(srcBuffer, dstBuffer)) 154 { 155 return 0; 156 } 157 158 } 159 else 160 { 161 return 0; 162 } 163 } 164 165 /********** For RGB16 to YUV420 conversion **********/ 166 if (pBitmap != NULL) 167 { 168 inputRGB = pBitmap->pBuffer; 169 width_src = pBitmap->width; 170 height_src = pBitmap->height; 171 colorkey = pBitmap->color_key; 172 pitch_src = width_src; // equal to the source width 173 174 // to YUV420 output 175 outYUV = pToEncode->pBuffer; 176 width_dst = width_src; // 1:1, set it to source 177 height_dst = height_src; // 1:1, set it to source 178 pitch_dst = pToEncode->width; 179 Dst_height = pToEncode->height; // 1:1, so equal to source 180 181 /* check buffer size */ 182 if ((pBitmap->bufSize < (pitch_src*height_src*2)) || 183 (pToEncode->bufSize < ((pitch_dst*Dst_height*3) >> 1))) 184 { 185 return 0; 186 } 187 188 if (pCameraInput != NULL) // use color key when camera input is present 189 { 190 BitmapInput->SetColorkey(colorkey); 191 } 192 193 if (!BitmapInput->Convert(inputRGB, outYUV)) 194 { 195 return 0; 196 } 197 } 198 199 return 1; 200 } 201 202 203 OSCL_EXPORT_REF int32 CPVVideoBlend :: InitOutputBlend(PVDimension *srcDecodeFrm, 204 PVDimension *dstDecodeFrm, 205 PVDimension *srcEncodeFrm, 206 PVDimension *dstEncodeFrm, 207 int32 rotateMirrorForEncFrm, 208 int32 pitch) 209 { 210 211 mInitOutputBlend = false; 212 213 if (srcDecodeFrm != NULL) 214 { 215 Src_width = srcDecodeFrm->width; 216 Src_height = srcDecodeFrm->height; 217 Src_pitch = Src_width; 218 219 Dst_width = dstDecodeFrm->width; 220 Dst_height = dstDecodeFrm->height; 221 Dst_pitch = pitch; 222 223 Rotation = 0; 224 225 if (!DecoderOutput->Init(Src_width, Src_height, Src_pitch, Dst_width, Dst_height, Dst_pitch, Rotation)) 226 { 227 return 0; 228 } 229 230 if (!DecoderOutput->SetMode(1)) 231 { 232 return 0; 233 } 234 } 235 236 if (srcEncodeFrm != NULL) 237 { 238 Src_width = srcEncodeFrm->width; 239 Src_height = srcEncodeFrm->height; 240 Src_pitch = Src_width; 241 242 Dst_width = dstEncodeFrm->width; 243 Dst_height = dstEncodeFrm->height; 244 Dst_pitch = pitch; 245 246 Rotation = rotateMirrorForEncFrm; // for clockwise rotation CC16.lib supports counter clock wise rotation 247 switch (Rotation) 248 { 249 case 0 : 250 Rotation = 0; 251 break; 252 case 1 : 253 Rotation = 3; 254 break; 255 case 2 : 256 Rotation = 2; 257 break; 258 case 3 : 259 Rotation = 1; 260 break; 261 case 4 : 262 Rotation = 4; 263 break; 264 case 5 : 265 Rotation = 7; 266 break; 267 case 6 : 268 Rotation = 6; 269 break; 270 case 7 : 271 Rotation = 5; 272 break; 273 default : 274 break; 275 } 276 277 278 if (!EncoderInput->Init(Src_width, Src_height, Src_pitch, Dst_width, Dst_height, Dst_pitch, Rotation)) 279 { 280 return 0; 281 } 282 if (!EncoderInput->SetMode(1)) 283 { 284 return 0; 285 } 286 } 287 288 mInitOutputBlend = true; 289 290 return 1; 291 } 292 293 294 OSCL_EXPORT_REF int32 CPVVideoBlend :: BlendOutput(PVBlendFrame *pFromDecode, PVCoordinate *pos1, 295 PVBlendFrame *pToEncode, PVCoordinate *pos2, 296 PVBitmap *pDropDownMenu, PVCoordinate *pos3, 297 uint32 changeOutputOrder, 298 PVBitmap *pDisplayOutput) 299 { 300 301 uint8 *yuvBuf[3], *yuvBufDec[3], *rgbBuf = NULL, *temprgbBuf; 302 int32 srcFrameSizeEnc = 0; 303 int32 srcFrameSizeDec = 0; 304 305 if (mInitOutputBlend == false) 306 { 307 return 0; 308 } 309 310 rgbBuf = pDisplayOutput->pBuffer; 311 312 if (pToEncode) 313 { 314 srcFrameSizeEnc = pToEncode->width * pToEncode->height; 315 } 316 317 if (pFromDecode) 318 { 319 srcFrameSizeDec = pFromDecode->width * pFromDecode->height; 320 } 321 322 if (changeOutputOrder) 323 { 324 if (pToEncode != NULL) 325 { 326 yuvBuf[0] = pToEncode->pBuffer; 327 yuvBuf[1] = yuvBuf[0] + srcFrameSizeEnc; 328 yuvBuf[2] = yuvBuf[1] + srcFrameSizeEnc / 4; 329 EncoderInput->Convert(yuvBuf, rgbBuf + (pos2->y * pDisplayOutput->width + pos2->x)*2); 330 } 331 if (pFromDecode != NULL) 332 { 333 yuvBufDec[0] = pFromDecode->pBuffer; 334 yuvBufDec[1] = yuvBufDec[0] + srcFrameSizeDec; 335 yuvBufDec[2] = yuvBufDec[1] + srcFrameSizeDec / 4; 336 DecoderOutput->Convert(yuvBufDec, rgbBuf + (pos1->y * pDisplayOutput->width + pos1->x)*2); 337 } 338 } 339 else 340 { 341 if (pFromDecode != NULL) 342 { 343 yuvBufDec[0] = pFromDecode->pBuffer; 344 yuvBufDec[1] = yuvBufDec[0] + srcFrameSizeDec; 345 yuvBufDec[2] = yuvBufDec[1] + srcFrameSizeDec / 4; 346 DecoderOutput->Convert(yuvBufDec, rgbBuf + (pos1->y * pDisplayOutput->width + pos1->x)*2); 347 } 348 if (pToEncode != NULL) 349 { 350 yuvBuf[0] = pToEncode->pBuffer; 351 yuvBuf[1] = yuvBuf[0] + srcFrameSizeEnc; 352 yuvBuf[2] = yuvBuf[1] + srcFrameSizeEnc / 4; 353 EncoderInput->Convert(yuvBuf, rgbBuf + (pos2->y * pDisplayOutput->width + pos2->x)*2); 354 } 355 } 356 357 if (pDropDownMenu != NULL) 358 { 359 temprgbBuf = pDropDownMenu->pBuffer ; 360 rgbBuf += (pos3->y * pDisplayOutput->width + pos3->x) * 2; 361 for (int i = 0; i < pDropDownMenu->height; i++) 362 { 363 for (int j = 0; j < pDropDownMenu->width*2; j++) 364 { 365 *rgbBuf++ = *temprgbBuf++; 366 } 367 368 rgbBuf += (Dst_pitch * 2) - (pDropDownMenu->width * 2); 369 } 370 } 371 372 return 1; 373 } 374 375