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 M4xVSS_internal.c 19 * @brief Internal functions of extended Video Studio Service (Video Studio 2.1) 20 * @note 21 ****************************************************************************** 22 */ 23 #include "M4OSA_Debug.h" 24 #include "M4OSA_CharStar.h" 25 26 #include "NXPSW_CompilerSwitches.h" 27 28 #include "M4VSS3GPP_API.h" 29 #include "M4VSS3GPP_ErrorCodes.h" 30 31 #include "M4xVSS_API.h" 32 #include "M4xVSS_Internal.h" 33 34 /*for rgb16 color effect*/ 35 #include "M4VIFI_Defines.h" 36 #include "M4VIFI_Clip.h" 37 38 /** 39 * component includes */ 40 #include "M4VFL_transition.h" /**< video effects */ 41 42 /* Internal header file of VSS is included because of MMS use case */ 43 #include "M4VSS3GPP_InternalTypes.h" 44 45 /*Exif header files to add image rendering support (cropping, black borders)*/ 46 #include "M4EXIFC_CommonAPI.h" 47 // StageFright encoders require %16 resolution 48 #include "M4ENCODER_common.h" 49 50 #define TRANSPARENT_COLOR 0x7E0 51 52 /* Prototype of M4VIFI_xVSS_RGB565toYUV420 function (avoid green effect of transparency color) */ 53 M4VIFI_UInt8 M4VIFI_xVSS_RGB565toYUV420(void *pUserData, M4VIFI_ImagePlane *pPlaneIn, 54 M4VIFI_ImagePlane *pPlaneOut); 55 56 57 /*special MCS function used only in VideoArtist and VideoStudio to open the media in the normal 58 mode. That way the media duration is accurate*/ 59 extern M4OSA_ERR M4MCS_open_normalMode(M4MCS_Context pContext, M4OSA_Void* pFileIn, 60 M4VIDEOEDITING_FileType InputFileType, 61 M4OSA_Void* pFileOut, M4OSA_Void* pTempFile); 62 63 64 /** 65 ****************************************************************************** 66 * prototype M4OSA_ERR M4xVSS_internalStartTranscoding(M4OSA_Context pContext) 67 * @brief This function initializes MCS (3GP transcoder) with the given 68 * parameters 69 * @note The transcoding parameters are given by the internal xVSS context. 70 * This context contains a pointer on the current element of the 71 * chained list of MCS parameters. 72 * 73 * @param pContext (IN) Pointer on the xVSS edit context 74 * @return M4NO_ERROR: No error 75 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL 76 * @return M4ERR_ALLOC: Memory allocation has failed 77 ****************************************************************************** 78 */ 79 M4OSA_ERR M4xVSS_internalStartTranscoding(M4OSA_Context pContext, 80 M4OSA_UInt32 *rotationDegree) 81 { 82 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 83 M4OSA_ERR err; 84 M4MCS_Context mcs_context; 85 M4MCS_OutputParams Params; 86 M4MCS_EncodingParams Rates; 87 M4OSA_UInt32 i; 88 M4VIDEOEDITING_ClipProperties clipProps; 89 90 err = M4MCS_init(&mcs_context, xVSS_context->pFileReadPtr, xVSS_context->pFileWritePtr); 91 if(err != M4NO_ERROR) 92 { 93 M4OSA_TRACE1_1("Error in M4MCS_init: 0x%x", err); 94 return err; 95 } 96 97 err = M4MCS_open(mcs_context, xVSS_context->pMCScurrentParams->pFileIn, 98 xVSS_context->pMCScurrentParams->InputFileType, 99 xVSS_context->pMCScurrentParams->pFileOut, 100 xVSS_context->pMCScurrentParams->pFileTemp); 101 if (err != M4NO_ERROR) 102 { 103 M4OSA_TRACE1_1("Error in M4MCS_open: 0x%x", err); 104 M4MCS_abort(mcs_context); 105 return err; 106 } 107 108 /** Get the clip properties 109 */ 110 err = M4MCS_getInputFileProperties(mcs_context, &clipProps); 111 if (err != M4NO_ERROR) { 112 M4OSA_TRACE1_1("Error in M4MCS_getInputFileProperties: 0x%x", err); 113 M4MCS_abort(mcs_context); 114 return err; 115 } 116 *rotationDegree = clipProps.videoRotationDegrees; 117 118 /** 119 * Fill MCS parameters with the parameters contained in the current element of the 120 MCS parameters chained list */ 121 Params.OutputFileType = xVSS_context->pMCScurrentParams->OutputFileType; 122 Params.OutputVideoFormat = xVSS_context->pMCScurrentParams->OutputVideoFormat; 123 Params.outputVideoProfile= xVSS_context->pMCScurrentParams->outputVideoProfile; 124 Params.outputVideoLevel = xVSS_context->pMCScurrentParams->outputVideoLevel; 125 Params.OutputVideoFrameSize = xVSS_context->pMCScurrentParams->OutputVideoFrameSize; 126 Params.OutputVideoFrameRate = xVSS_context->pMCScurrentParams->OutputVideoFrameRate; 127 Params.OutputAudioFormat = xVSS_context->pMCScurrentParams->OutputAudioFormat; 128 Params.OutputAudioSamplingFrequency = 129 xVSS_context->pMCScurrentParams->OutputAudioSamplingFrequency; 130 Params.bAudioMono = xVSS_context->pMCScurrentParams->bAudioMono; 131 Params.pOutputPCMfile = M4OSA_NULL; 132 /*FB 2008/10/20: add media rendering parameter to keep aspect ratio*/ 133 switch(xVSS_context->pMCScurrentParams->MediaRendering) 134 { 135 case M4xVSS_kResizing: 136 Params.MediaRendering = M4MCS_kResizing; 137 break; 138 case M4xVSS_kCropping: 139 Params.MediaRendering = M4MCS_kCropping; 140 break; 141 case M4xVSS_kBlackBorders: 142 Params.MediaRendering = M4MCS_kBlackBorders; 143 break; 144 default: 145 break; 146 } 147 /**/ 148 // new params after integrating MCS 2.0 149 // Set the number of audio effects; 0 for now. 150 Params.nbEffects = 0; 151 152 // Set the audio effect; null for now. 153 Params.pEffects = NULL; 154 155 // Set the audio effect; null for now. 156 Params.bDiscardExif = M4OSA_FALSE; 157 158 // Set the audio effect; null for now. 159 Params.bAdjustOrientation = M4OSA_FALSE; 160 // new params after integrating MCS 2.0 161 162 /** 163 * Set output parameters */ 164 err = M4MCS_setOutputParams(mcs_context, &Params); 165 if (err != M4NO_ERROR) 166 { 167 M4OSA_TRACE1_1("Error in M4MCS_setOutputParams: 0x%x", err); 168 M4MCS_abort(mcs_context); 169 return err; 170 } 171 172 Rates.OutputVideoBitrate = xVSS_context->pMCScurrentParams->OutputVideoBitrate; 173 Rates.OutputAudioBitrate = xVSS_context->pMCScurrentParams->OutputAudioBitrate; 174 Rates.BeginCutTime = 0; 175 Rates.EndCutTime = 0; 176 Rates.OutputFileSize = 0; 177 178 /*FB: transcoding per parts*/ 179 Rates.BeginCutTime = xVSS_context->pMCScurrentParams->BeginCutTime; 180 Rates.EndCutTime = xVSS_context->pMCScurrentParams->EndCutTime; 181 Rates.OutputVideoTimescale = xVSS_context->pMCScurrentParams->OutputVideoTimescale; 182 183 err = M4MCS_setEncodingParams(mcs_context, &Rates); 184 if (err != M4NO_ERROR) 185 { 186 M4OSA_TRACE1_1("Error in M4MCS_setEncodingParams: 0x%x", err); 187 M4MCS_abort(mcs_context); 188 return err; 189 } 190 191 err = M4MCS_checkParamsAndStart(mcs_context); 192 if (err != M4NO_ERROR) 193 { 194 M4OSA_TRACE1_1("Error in M4MCS_checkParamsAndStart: 0x%x", err); 195 M4MCS_abort(mcs_context); 196 return err; 197 } 198 199 /** 200 * Save MCS context to be able to call MCS step function in M4xVSS_step function */ 201 xVSS_context->pMCS_Ctxt = mcs_context; 202 203 return M4NO_ERROR; 204 } 205 206 /** 207 ****************************************************************************** 208 * prototype M4OSA_ERR M4xVSS_internalStopTranscoding(M4OSA_Context pContext) 209 * @brief This function cleans up MCS (3GP transcoder) 210 * @note 211 * 212 * @param pContext (IN) Pointer on the xVSS edit context 213 * @return M4NO_ERROR: No error 214 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL 215 * @return M4ERR_ALLOC: Memory allocation has failed 216 ****************************************************************************** 217 */ 218 M4OSA_ERR M4xVSS_internalStopTranscoding(M4OSA_Context pContext) 219 { 220 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 221 M4OSA_ERR err; 222 223 err = M4MCS_close(xVSS_context->pMCS_Ctxt); 224 if (err != M4NO_ERROR) 225 { 226 M4OSA_TRACE1_1("M4xVSS_internalStopTranscoding: Error in M4MCS_close: 0x%x", err); 227 M4MCS_abort(xVSS_context->pMCS_Ctxt); 228 return err; 229 } 230 231 /** 232 * Free this MCS instance */ 233 err = M4MCS_cleanUp(xVSS_context->pMCS_Ctxt); 234 if (err != M4NO_ERROR) 235 { 236 M4OSA_TRACE1_1("M4xVSS_internalStopTranscoding: Error in M4MCS_cleanUp: 0x%x", err); 237 return err; 238 } 239 240 xVSS_context->pMCS_Ctxt = M4OSA_NULL; 241 242 return M4NO_ERROR; 243 } 244 245 /** 246 ****************************************************************************** 247 * M4OSA_ERR M4xVSS_internalConvertAndResizeARGB8888toYUV420(M4OSA_Void* pFileIn, 248 * M4OSA_FileReadPointer* pFileReadPtr, 249 * M4VIFI_ImagePlane* pImagePlanes, 250 * M4OSA_UInt32 width, 251 * M4OSA_UInt32 height); 252 * @brief It Coverts and resizes a ARGB8888 image to YUV420 253 * @note 254 * @param pFileIn (IN) The Image input file 255 * @param pFileReadPtr (IN) Pointer on filesystem functions 256 * @param pImagePlanes (IN/OUT) Pointer on YUV420 output planes allocated by the user 257 * ARGB8888 image will be converted and resized to output 258 * YUV420 plane size 259 *@param width (IN) width of the ARGB8888 260 *@param height (IN) height of the ARGB8888 261 * @return M4NO_ERROR: No error 262 * @return M4ERR_ALLOC: memory error 263 * @return M4ERR_PARAMETER: At least one of the function parameters is null 264 ****************************************************************************** 265 */ 266 267 M4OSA_ERR M4xVSS_internalConvertAndResizeARGB8888toYUV420(M4OSA_Void* pFileIn, 268 M4OSA_FileReadPointer* pFileReadPtr, 269 M4VIFI_ImagePlane* pImagePlanes, 270 M4OSA_UInt32 width,M4OSA_UInt32 height) 271 { 272 M4OSA_Context pARGBIn; 273 M4VIFI_ImagePlane rgbPlane1 ,rgbPlane2; 274 M4OSA_UInt32 frameSize_argb=(width * height * 4); 275 M4OSA_UInt32 frameSize = (width * height * 3); //Size of RGB888 data. 276 M4OSA_UInt32 i = 0,j= 0; 277 M4OSA_ERR err=M4NO_ERROR; 278 279 280 M4OSA_UInt8 *pTmpData = (M4OSA_UInt8*) M4OSA_32bitAlignedMalloc(frameSize_argb, 281 M4VS, (M4OSA_Char*)"Image argb data"); 282 M4OSA_TRACE1_0("M4xVSS_internalConvertAndResizeARGB8888toYUV420 Entering :"); 283 if(pTmpData == M4OSA_NULL) { 284 M4OSA_TRACE1_0("M4xVSS_internalConvertAndResizeARGB8888toYUV420 :\ 285 Failed to allocate memory for Image clip"); 286 return M4ERR_ALLOC; 287 } 288 289 M4OSA_TRACE1_2("M4xVSS_internalConvertAndResizeARGB8888toYUV420 :width and height %d %d", 290 width ,height); 291 /* Get file size (mandatory for chunk decoding) */ 292 err = pFileReadPtr->openRead(&pARGBIn, pFileIn, M4OSA_kFileRead); 293 if(err != M4NO_ERROR) 294 { 295 M4OSA_TRACE1_2("M4xVSS_internalConvertAndResizeARGB8888toYUV420 :\ 296 Can't open input ARGB8888 file %s, error: 0x%x\n",pFileIn, err); 297 free(pTmpData); 298 pTmpData = M4OSA_NULL; 299 goto cleanup; 300 } 301 302 err = pFileReadPtr->readData(pARGBIn,(M4OSA_MemAddr8)pTmpData, &frameSize_argb); 303 if(err != M4NO_ERROR) 304 { 305 M4OSA_TRACE1_2("M4xVSS_internalConvertAndResizeARGB8888toYUV420 Can't close ARGB8888\ 306 file %s, error: 0x%x\n",pFileIn, err); 307 pFileReadPtr->closeRead(pARGBIn); 308 free(pTmpData); 309 pTmpData = M4OSA_NULL; 310 goto cleanup; 311 } 312 313 err = pFileReadPtr->closeRead(pARGBIn); 314 if(err != M4NO_ERROR) 315 { 316 M4OSA_TRACE1_2("M4xVSS_internalConvertAndResizeARGB8888toYUV420 Can't close ARGB8888 \ 317 file %s, error: 0x%x\n",pFileIn, err); 318 free(pTmpData); 319 pTmpData = M4OSA_NULL; 320 goto cleanup; 321 } 322 323 rgbPlane1.pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(frameSize, M4VS, 324 (M4OSA_Char*)"Image clip RGB888 data"); 325 if(rgbPlane1.pac_data == M4OSA_NULL) 326 { 327 M4OSA_TRACE1_0("M4xVSS_internalConvertAndResizeARGB8888toYUV420 \ 328 Failed to allocate memory for Image clip"); 329 free(pTmpData); 330 return M4ERR_ALLOC; 331 } 332 333 rgbPlane1.u_height = height; 334 rgbPlane1.u_width = width; 335 rgbPlane1.u_stride = width*3; 336 rgbPlane1.u_topleft = 0; 337 338 339 /** Remove the alpha channel */ 340 for (i=0, j = 0; i < frameSize_argb; i++) { 341 if ((i % 4) == 0) continue; 342 rgbPlane1.pac_data[j] = pTmpData[i]; 343 j++; 344 } 345 free(pTmpData); 346 347 /* To Check if resizing is required with color conversion */ 348 if(width != pImagePlanes->u_width || height != pImagePlanes->u_height) 349 { 350 M4OSA_TRACE1_0("M4xVSS_internalConvertAndResizeARGB8888toYUV420 Resizing :"); 351 frameSize = ( pImagePlanes->u_width * pImagePlanes->u_height * 3); 352 rgbPlane2.pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(frameSize, M4VS, 353 (M4OSA_Char*)"Image clip RGB888 data"); 354 if(rgbPlane2.pac_data == M4OSA_NULL) 355 { 356 M4OSA_TRACE1_0("Failed to allocate memory for Image clip"); 357 free(pTmpData); 358 return M4ERR_ALLOC; 359 } 360 rgbPlane2.u_height = pImagePlanes->u_height; 361 rgbPlane2.u_width = pImagePlanes->u_width; 362 rgbPlane2.u_stride = pImagePlanes->u_width*3; 363 rgbPlane2.u_topleft = 0; 364 365 /* Resizing RGB888 to RGB888 */ 366 err = M4VIFI_ResizeBilinearRGB888toRGB888(M4OSA_NULL, &rgbPlane1, &rgbPlane2); 367 if(err != M4NO_ERROR) 368 { 369 M4OSA_TRACE1_1("error when converting from Resize RGB888 to RGB888: 0x%x\n", err); 370 free(rgbPlane2.pac_data); 371 free(rgbPlane1.pac_data); 372 return err; 373 } 374 /*Converting Resized RGB888 to YUV420 */ 375 err = M4VIFI_RGB888toYUV420(M4OSA_NULL, &rgbPlane2, pImagePlanes); 376 if(err != M4NO_ERROR) 377 { 378 M4OSA_TRACE1_1("error when converting from RGB888 to YUV: 0x%x\n", err); 379 free(rgbPlane2.pac_data); 380 free(rgbPlane1.pac_data); 381 return err; 382 } 383 free(rgbPlane2.pac_data); 384 free(rgbPlane1.pac_data); 385 386 M4OSA_TRACE1_0("RGB to YUV done"); 387 388 389 } 390 else 391 { 392 M4OSA_TRACE1_0("M4xVSS_internalConvertAndResizeARGB8888toYUV420 NO Resizing :"); 393 err = M4VIFI_RGB888toYUV420(M4OSA_NULL, &rgbPlane1, pImagePlanes); 394 if(err != M4NO_ERROR) 395 { 396 M4OSA_TRACE1_1("error when converting from RGB to YUV: 0x%x\n", err); 397 } 398 free(rgbPlane1.pac_data); 399 400 M4OSA_TRACE1_0("RGB to YUV done"); 401 } 402 cleanup: 403 M4OSA_TRACE1_0("M4xVSS_internalConvertAndResizeARGB8888toYUV420 leaving :"); 404 return err; 405 } 406 407 /** 408 ****************************************************************************** 409 * M4OSA_ERR M4xVSS_internalConvertARGB8888toYUV420(M4OSA_Void* pFileIn, 410 * M4OSA_FileReadPointer* pFileReadPtr, 411 * M4VIFI_ImagePlane* pImagePlanes, 412 * M4OSA_UInt32 width, 413 * M4OSA_UInt32 height); 414 * @brief It Coverts a ARGB8888 image to YUV420 415 * @note 416 * @param pFileIn (IN) The Image input file 417 * @param pFileReadPtr (IN) Pointer on filesystem functions 418 * @param pImagePlanes (IN/OUT) Pointer on YUV420 output planes allocated by the user 419 * ARGB8888 image will be converted and resized to output 420 * YUV420 plane size 421 * @param width (IN) width of the ARGB8888 422 * @param height (IN) height of the ARGB8888 423 * @return M4NO_ERROR: No error 424 * @return M4ERR_ALLOC: memory error 425 * @return M4ERR_PARAMETER: At least one of the function parameters is null 426 ****************************************************************************** 427 */ 428 429 M4OSA_ERR M4xVSS_internalConvertARGB8888toYUV420(M4OSA_Void* pFileIn, 430 M4OSA_FileReadPointer* pFileReadPtr, 431 M4VIFI_ImagePlane** pImagePlanes, 432 M4OSA_UInt32 width,M4OSA_UInt32 height) 433 { 434 M4OSA_ERR err = M4NO_ERROR; 435 M4VIFI_ImagePlane *yuvPlane = M4OSA_NULL; 436 437 yuvPlane = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(3*sizeof(M4VIFI_ImagePlane), 438 M4VS, (M4OSA_Char*)"M4xVSS_internalConvertRGBtoYUV: Output plane YUV"); 439 if(yuvPlane == M4OSA_NULL) { 440 M4OSA_TRACE1_0("M4xVSS_internalConvertAndResizeARGB8888toYUV420 :\ 441 Failed to allocate memory for Image clip"); 442 return M4ERR_ALLOC; 443 } 444 yuvPlane[0].u_height = height; 445 yuvPlane[0].u_width = width; 446 yuvPlane[0].u_stride = width; 447 yuvPlane[0].u_topleft = 0; 448 yuvPlane[0].pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(yuvPlane[0].u_height \ 449 * yuvPlane[0].u_width * 1.5, M4VS, (M4OSA_Char*)"imageClip YUV data"); 450 451 yuvPlane[1].u_height = yuvPlane[0].u_height >>1; 452 yuvPlane[1].u_width = yuvPlane[0].u_width >> 1; 453 yuvPlane[1].u_stride = yuvPlane[1].u_width; 454 yuvPlane[1].u_topleft = 0; 455 yuvPlane[1].pac_data = (M4VIFI_UInt8*)(yuvPlane[0].pac_data + yuvPlane[0].u_height \ 456 * yuvPlane[0].u_width); 457 458 yuvPlane[2].u_height = yuvPlane[0].u_height >>1; 459 yuvPlane[2].u_width = yuvPlane[0].u_width >> 1; 460 yuvPlane[2].u_stride = yuvPlane[2].u_width; 461 yuvPlane[2].u_topleft = 0; 462 yuvPlane[2].pac_data = (M4VIFI_UInt8*)(yuvPlane[1].pac_data + yuvPlane[1].u_height \ 463 * yuvPlane[1].u_width); 464 err = M4xVSS_internalConvertAndResizeARGB8888toYUV420( pFileIn,pFileReadPtr, 465 yuvPlane, width, height); 466 if(err != M4NO_ERROR) 467 { 468 M4OSA_TRACE1_1("M4xVSS_internalConvertAndResizeARGB8888toYUV420 return error: 0x%x\n", err); 469 free(yuvPlane); 470 return err; 471 } 472 473 *pImagePlanes = yuvPlane; 474 475 M4OSA_TRACE1_0("M4xVSS_internalConvertARGB8888toYUV420 :Leaving"); 476 return err; 477 478 } 479 480 /** 481 ****************************************************************************** 482 * M4OSA_ERR M4xVSS_PictureCallbackFct (M4OSA_Void* pPictureCtxt, 483 * M4VIFI_ImagePlane* pImagePlanes, 484 * M4OSA_UInt32* pPictureDuration); 485 * @brief It feeds the PTO3GPP with YUV420 pictures. 486 * @note This function is given to the PTO3GPP in the M4PTO3GPP_Params structure 487 * @param pContext (IN) The integrator own context 488 * @param pImagePlanes(IN/OUT) Pointer to an array of three valid image planes 489 * @param pPictureDuration(OUT) Duration of the returned picture 490 * 491 * @return M4NO_ERROR: No error 492 * @return M4PTO3GPP_WAR_LAST_PICTURE: The returned image is the last one 493 * @return M4ERR_PARAMETER: At least one of the function parameters is null 494 ****************************************************************************** 495 */ 496 M4OSA_ERR M4xVSS_PictureCallbackFct(M4OSA_Void* pPictureCtxt, M4VIFI_ImagePlane* pImagePlanes, 497 M4OSA_Double* pPictureDuration) 498 { 499 M4OSA_ERR err = M4NO_ERROR; 500 M4OSA_UInt8 last_frame_flag = 0; 501 M4xVSS_PictureCallbackCtxt* pC = (M4xVSS_PictureCallbackCtxt*) (pPictureCtxt); 502 503 /*Used for pan&zoom*/ 504 M4OSA_UInt8 tempPanzoomXa = 0; 505 M4OSA_UInt8 tempPanzoomXb = 0; 506 M4AIR_Params Params; 507 /**/ 508 509 /*Used for cropping and black borders*/ 510 M4OSA_Context pPictureContext = M4OSA_NULL; 511 M4OSA_FilePosition pictureSize = 0 ; 512 M4OSA_UInt8* pictureBuffer = M4OSA_NULL; 513 //M4EXIFC_Context pExifContext = M4OSA_NULL; 514 M4EXIFC_BasicTags pBasicTags; 515 M4VIFI_ImagePlane pImagePlanes1 = pImagePlanes[0]; 516 M4VIFI_ImagePlane pImagePlanes2 = pImagePlanes[1]; 517 M4VIFI_ImagePlane pImagePlanes3 = pImagePlanes[2]; 518 /**/ 519 520 /** 521 * Check input parameters */ 522 M4OSA_DEBUG_IF2((M4OSA_NULL==pPictureCtxt), M4ERR_PARAMETER, 523 "M4xVSS_PictureCallbackFct: pPictureCtxt is M4OSA_NULL"); 524 M4OSA_DEBUG_IF2((M4OSA_NULL==pImagePlanes), M4ERR_PARAMETER, 525 "M4xVSS_PictureCallbackFct: pImagePlanes is M4OSA_NULL"); 526 M4OSA_DEBUG_IF2((M4OSA_NULL==pPictureDuration), M4ERR_PARAMETER, 527 "M4xVSS_PictureCallbackFct: pPictureDuration is M4OSA_NULL"); 528 M4OSA_TRACE1_0("M4xVSS_PictureCallbackFct :Entering"); 529 /*PR P4ME00003181 In case the image number is 0, pan&zoom can not be used*/ 530 if(M4OSA_TRUE == pC->m_pPto3GPPparams->isPanZoom && pC->m_NbImage == 0) 531 { 532 pC->m_pPto3GPPparams->isPanZoom = M4OSA_FALSE; 533 } 534 535 /*If no cropping/black borders or pan&zoom, just decode and resize the picture*/ 536 if(pC->m_mediaRendering == M4xVSS_kResizing && M4OSA_FALSE == pC->m_pPto3GPPparams->isPanZoom) 537 { 538 /** 539 * Convert and resize input ARGB8888 file to YUV420 */ 540 /*To support ARGB8888 : */ 541 M4OSA_TRACE1_2("M4xVSS_PictureCallbackFct 1: width and heght %d %d", 542 pC->m_pPto3GPPparams->width,pC->m_pPto3GPPparams->height); 543 err = M4xVSS_internalConvertAndResizeARGB8888toYUV420(pC->m_FileIn, 544 pC->m_pFileReadPtr, pImagePlanes,pC->m_pPto3GPPparams->width, 545 pC->m_pPto3GPPparams->height); 546 if(err != M4NO_ERROR) 547 { 548 M4OSA_TRACE1_1("M4xVSS_PictureCallbackFct: Error when decoding JPEG: 0x%x\n", err); 549 return err; 550 } 551 } 552 /*In case of cropping, black borders or pan&zoom, call the EXIF reader and the AIR*/ 553 else 554 { 555 /** 556 * Computes ratios */ 557 if(pC->m_pDecodedPlane == M4OSA_NULL) 558 { 559 /** 560 * Convert input ARGB8888 file to YUV420 */ 561 M4OSA_TRACE1_2("M4xVSS_PictureCallbackFct 2: width and heght %d %d", 562 pC->m_pPto3GPPparams->width,pC->m_pPto3GPPparams->height); 563 err = M4xVSS_internalConvertARGB8888toYUV420(pC->m_FileIn, pC->m_pFileReadPtr, 564 &(pC->m_pDecodedPlane),pC->m_pPto3GPPparams->width,pC->m_pPto3GPPparams->height); 565 if(err != M4NO_ERROR) 566 { 567 M4OSA_TRACE1_1("M4xVSS_PictureCallbackFct: Error when decoding JPEG: 0x%x\n", err); 568 if(pC->m_pDecodedPlane != M4OSA_NULL) 569 { 570 /* YUV420 planar is returned but allocation is made only once 571 (contigous planes in memory) */ 572 if(pC->m_pDecodedPlane->pac_data != M4OSA_NULL) 573 { 574 free(pC->m_pDecodedPlane->pac_data); 575 } 576 free(pC->m_pDecodedPlane); 577 pC->m_pDecodedPlane = M4OSA_NULL; 578 } 579 return err; 580 } 581 } 582 583 /*Initialize AIR Params*/ 584 Params.m_inputCoord.m_x = 0; 585 Params.m_inputCoord.m_y = 0; 586 Params.m_inputSize.m_height = pC->m_pDecodedPlane->u_height; 587 Params.m_inputSize.m_width = pC->m_pDecodedPlane->u_width; 588 Params.m_outputSize.m_width = pImagePlanes->u_width; 589 Params.m_outputSize.m_height = pImagePlanes->u_height; 590 Params.m_bOutputStripe = M4OSA_FALSE; 591 Params.m_outputOrientation = M4COMMON_kOrientationTopLeft; 592 593 /*Initialize Exif params structure*/ 594 pBasicTags.orientation = M4COMMON_kOrientationUnknown; 595 596 /** 597 Pan&zoom params*/ 598 if(M4OSA_TRUE == pC->m_pPto3GPPparams->isPanZoom) 599 { 600 /*Save ratio values, they can be reused if the new ratios are 0*/ 601 tempPanzoomXa = (M4OSA_UInt8)pC->m_pPto3GPPparams->PanZoomXa; 602 tempPanzoomXb = (M4OSA_UInt8)pC->m_pPto3GPPparams->PanZoomXb; 603 /*Check that the ratio is not 0*/ 604 /*Check (a) parameters*/ 605 if(pC->m_pPto3GPPparams->PanZoomXa == 0) 606 { 607 M4OSA_UInt8 maxRatio = 0; 608 if(pC->m_pPto3GPPparams->PanZoomTopleftXa >= 609 pC->m_pPto3GPPparams->PanZoomTopleftYa) 610 { 611 /*The ratio is 0, that means the area of the picture defined with (a) 612 parameters is bigger than the image size*/ 613 if(pC->m_pPto3GPPparams->PanZoomTopleftXa + tempPanzoomXa > 1000) 614 { 615 /*The oversize is maxRatio*/ 616 maxRatio = pC->m_pPto3GPPparams->PanZoomTopleftXa + tempPanzoomXa - 1000; 617 } 618 } 619 else 620 { 621 /*The ratio is 0, that means the area of the picture defined with (a) 622 parameters is bigger than the image size*/ 623 if(pC->m_pPto3GPPparams->PanZoomTopleftYa + tempPanzoomXa > 1000) 624 { 625 /*The oversize is maxRatio*/ 626 maxRatio = pC->m_pPto3GPPparams->PanZoomTopleftYa + tempPanzoomXa - 1000; 627 } 628 } 629 /*Modify the (a) parameters:*/ 630 if(pC->m_pPto3GPPparams->PanZoomTopleftXa >= maxRatio) 631 { 632 /*The (a) topleft parameters can be moved to keep the same area size*/ 633 pC->m_pPto3GPPparams->PanZoomTopleftXa -= maxRatio; 634 } 635 else 636 { 637 /*Move the (a) topleft parameter to 0 but the ratio will be also further 638 modified to match the image size*/ 639 pC->m_pPto3GPPparams->PanZoomTopleftXa = 0; 640 } 641 if(pC->m_pPto3GPPparams->PanZoomTopleftYa >= maxRatio) 642 { 643 /*The (a) topleft parameters can be moved to keep the same area size*/ 644 pC->m_pPto3GPPparams->PanZoomTopleftYa -= maxRatio; 645 } 646 else 647 { 648 /*Move the (a) topleft parameter to 0 but the ratio will be also further 649 modified to match the image size*/ 650 pC->m_pPto3GPPparams->PanZoomTopleftYa = 0; 651 } 652 /*The new ratio is the original one*/ 653 pC->m_pPto3GPPparams->PanZoomXa = tempPanzoomXa; 654 if(pC->m_pPto3GPPparams->PanZoomXa + pC->m_pPto3GPPparams->PanZoomTopleftXa > 1000) 655 { 656 /*Change the ratio if the area of the picture defined with (a) parameters is 657 bigger than the image size*/ 658 pC->m_pPto3GPPparams->PanZoomXa = 1000 - pC->m_pPto3GPPparams->PanZoomTopleftXa; 659 } 660 if(pC->m_pPto3GPPparams->PanZoomXa + pC->m_pPto3GPPparams->PanZoomTopleftYa > 1000) 661 { 662 /*Change the ratio if the area of the picture defined with (a) parameters is 663 bigger than the image size*/ 664 pC->m_pPto3GPPparams->PanZoomXa = 1000 - pC->m_pPto3GPPparams->PanZoomTopleftYa; 665 } 666 } 667 /*Check (b) parameters*/ 668 if(pC->m_pPto3GPPparams->PanZoomXb == 0) 669 { 670 M4OSA_UInt8 maxRatio = 0; 671 if(pC->m_pPto3GPPparams->PanZoomTopleftXb >= 672 pC->m_pPto3GPPparams->PanZoomTopleftYb) 673 { 674 /*The ratio is 0, that means the area of the picture defined with (b) 675 parameters is bigger than the image size*/ 676 if(pC->m_pPto3GPPparams->PanZoomTopleftXb + tempPanzoomXb > 1000) 677 { 678 /*The oversize is maxRatio*/ 679 maxRatio = pC->m_pPto3GPPparams->PanZoomTopleftXb + tempPanzoomXb - 1000; 680 } 681 } 682 else 683 { 684 /*The ratio is 0, that means the area of the picture defined with (b) 685 parameters is bigger than the image size*/ 686 if(pC->m_pPto3GPPparams->PanZoomTopleftYb + tempPanzoomXb > 1000) 687 { 688 /*The oversize is maxRatio*/ 689 maxRatio = pC->m_pPto3GPPparams->PanZoomTopleftYb + tempPanzoomXb - 1000; 690 } 691 } 692 /*Modify the (b) parameters:*/ 693 if(pC->m_pPto3GPPparams->PanZoomTopleftXb >= maxRatio) 694 { 695 /*The (b) topleft parameters can be moved to keep the same area size*/ 696 pC->m_pPto3GPPparams->PanZoomTopleftXb -= maxRatio; 697 } 698 else 699 { 700 /*Move the (b) topleft parameter to 0 but the ratio will be also further 701 modified to match the image size*/ 702 pC->m_pPto3GPPparams->PanZoomTopleftXb = 0; 703 } 704 if(pC->m_pPto3GPPparams->PanZoomTopleftYb >= maxRatio) 705 { 706 /*The (b) topleft parameters can be moved to keep the same area size*/ 707 pC->m_pPto3GPPparams->PanZoomTopleftYb -= maxRatio; 708 } 709 else 710 { 711 /*Move the (b) topleft parameter to 0 but the ratio will be also further 712 modified to match the image size*/ 713 pC->m_pPto3GPPparams->PanZoomTopleftYb = 0; 714 } 715 /*The new ratio is the original one*/ 716 pC->m_pPto3GPPparams->PanZoomXb = tempPanzoomXb; 717 if(pC->m_pPto3GPPparams->PanZoomXb + pC->m_pPto3GPPparams->PanZoomTopleftXb > 1000) 718 { 719 /*Change the ratio if the area of the picture defined with (b) parameters is 720 bigger than the image size*/ 721 pC->m_pPto3GPPparams->PanZoomXb = 1000 - pC->m_pPto3GPPparams->PanZoomTopleftXb; 722 } 723 if(pC->m_pPto3GPPparams->PanZoomXb + pC->m_pPto3GPPparams->PanZoomTopleftYb > 1000) 724 { 725 /*Change the ratio if the area of the picture defined with (b) parameters is 726 bigger than the image size*/ 727 pC->m_pPto3GPPparams->PanZoomXb = 1000 - pC->m_pPto3GPPparams->PanZoomTopleftYb; 728 } 729 } 730 731 /** 732 * Computes AIR parameters */ 733 /* Params.m_inputCoord.m_x = (M4OSA_UInt32)(pC->m_pDecodedPlane->u_width * 734 (pC->m_pPto3GPPparams->PanZoomTopleftXa + 735 (M4OSA_Int16)((pC->m_pPto3GPPparams->PanZoomTopleftXb \ 736 - pC->m_pPto3GPPparams->PanZoomTopleftXa) * 737 pC->m_ImageCounter) / (M4OSA_Double)pC->m_NbImage)) / 100; 738 Params.m_inputCoord.m_y = (M4OSA_UInt32)(pC->m_pDecodedPlane->u_height * 739 (pC->m_pPto3GPPparams->PanZoomTopleftYa + 740 (M4OSA_Int16)((pC->m_pPto3GPPparams->PanZoomTopleftYb\ 741 - pC->m_pPto3GPPparams->PanZoomTopleftYa) * 742 pC->m_ImageCounter) / (M4OSA_Double)pC->m_NbImage)) / 100; 743 744 Params.m_inputSize.m_width = (M4OSA_UInt32)(pC->m_pDecodedPlane->u_width * 745 (pC->m_pPto3GPPparams->PanZoomXa + 746 (M4OSA_Int16)((pC->m_pPto3GPPparams->PanZoomXb - pC->m_pPto3GPPparams->PanZoomXa) * 747 pC->m_ImageCounter) / (M4OSA_Double)pC->m_NbImage)) / 100; 748 749 Params.m_inputSize.m_height = (M4OSA_UInt32)(pC->m_pDecodedPlane->u_height * 750 (pC->m_pPto3GPPparams->PanZoomXa + 751 (M4OSA_Int16)((pC->m_pPto3GPPparams->PanZoomXb - pC->m_pPto3GPPparams->PanZoomXa) * 752 pC->m_ImageCounter) / (M4OSA_Double)pC->m_NbImage)) / 100; 753 */ 754 // Instead of using pC->m_NbImage we have to use (pC->m_NbImage-1) as pC->m_ImageCounter 755 // will be x-1 max for x no. of frames 756 Params.m_inputCoord.m_x = (M4OSA_UInt32)((((M4OSA_Double)pC->m_pDecodedPlane->u_width * 757 (pC->m_pPto3GPPparams->PanZoomTopleftXa + 758 (M4OSA_Double)((M4OSA_Double)(pC->m_pPto3GPPparams->PanZoomTopleftXb\ 759 - pC->m_pPto3GPPparams->PanZoomTopleftXa) * 760 pC->m_ImageCounter) / (M4OSA_Double)pC->m_NbImage-1)) / 1000)); 761 Params.m_inputCoord.m_y = 762 (M4OSA_UInt32)((((M4OSA_Double)pC->m_pDecodedPlane->u_height * 763 (pC->m_pPto3GPPparams->PanZoomTopleftYa + 764 (M4OSA_Double)((M4OSA_Double)(pC->m_pPto3GPPparams->PanZoomTopleftYb\ 765 - pC->m_pPto3GPPparams->PanZoomTopleftYa) * 766 pC->m_ImageCounter) / (M4OSA_Double)pC->m_NbImage-1)) / 1000)); 767 768 Params.m_inputSize.m_width = 769 (M4OSA_UInt32)((((M4OSA_Double)pC->m_pDecodedPlane->u_width * 770 (pC->m_pPto3GPPparams->PanZoomXa + 771 (M4OSA_Double)((M4OSA_Double)(pC->m_pPto3GPPparams->PanZoomXb\ 772 - pC->m_pPto3GPPparams->PanZoomXa) * 773 pC->m_ImageCounter) / (M4OSA_Double)pC->m_NbImage-1)) / 1000)); 774 775 Params.m_inputSize.m_height = 776 (M4OSA_UInt32)((((M4OSA_Double)pC->m_pDecodedPlane->u_height * 777 (pC->m_pPto3GPPparams->PanZoomXa + 778 (M4OSA_Double)((M4OSA_Double)(pC->m_pPto3GPPparams->PanZoomXb \ 779 - pC->m_pPto3GPPparams->PanZoomXa) * 780 pC->m_ImageCounter) / (M4OSA_Double)pC->m_NbImage-1)) / 1000)); 781 782 if((Params.m_inputSize.m_width + Params.m_inputCoord.m_x)\ 783 > pC->m_pDecodedPlane->u_width) 784 { 785 Params.m_inputSize.m_width = pC->m_pDecodedPlane->u_width \ 786 - Params.m_inputCoord.m_x; 787 } 788 789 if((Params.m_inputSize.m_height + Params.m_inputCoord.m_y)\ 790 > pC->m_pDecodedPlane->u_height) 791 { 792 Params.m_inputSize.m_height = pC->m_pDecodedPlane->u_height\ 793 - Params.m_inputCoord.m_y; 794 } 795 796 797 798 Params.m_inputSize.m_width = (Params.m_inputSize.m_width>>1)<<1; 799 Params.m_inputSize.m_height = (Params.m_inputSize.m_height>>1)<<1; 800 } 801 802 803 804 /** 805 Picture rendering: Black borders*/ 806 807 if(pC->m_mediaRendering == M4xVSS_kBlackBorders) 808 { 809 memset((void *)pImagePlanes[0].pac_data,Y_PLANE_BORDER_VALUE, 810 (pImagePlanes[0].u_height*pImagePlanes[0].u_stride)); 811 memset((void *)pImagePlanes[1].pac_data,U_PLANE_BORDER_VALUE, 812 (pImagePlanes[1].u_height*pImagePlanes[1].u_stride)); 813 memset((void *)pImagePlanes[2].pac_data,V_PLANE_BORDER_VALUE, 814 (pImagePlanes[2].u_height*pImagePlanes[2].u_stride)); 815 816 /** 817 First without pan&zoom*/ 818 if(M4OSA_FALSE == pC->m_pPto3GPPparams->isPanZoom) 819 { 820 switch(pBasicTags.orientation) 821 { 822 default: 823 case M4COMMON_kOrientationUnknown: 824 Params.m_outputOrientation = M4COMMON_kOrientationTopLeft; 825 case M4COMMON_kOrientationTopLeft: 826 case M4COMMON_kOrientationTopRight: 827 case M4COMMON_kOrientationBottomRight: 828 case M4COMMON_kOrientationBottomLeft: 829 if((M4OSA_UInt32)((pC->m_pDecodedPlane->u_height * pImagePlanes->u_width)\ 830 /pC->m_pDecodedPlane->u_width) <= pImagePlanes->u_height) 831 //Params.m_inputSize.m_height < Params.m_inputSize.m_width) 832 { 833 /*it is height so black borders will be on the top and on the bottom side*/ 834 Params.m_outputSize.m_width = pImagePlanes->u_width; 835 Params.m_outputSize.m_height = 836 (M4OSA_UInt32)((pC->m_pDecodedPlane->u_height \ 837 * pImagePlanes->u_width) /pC->m_pDecodedPlane->u_width); 838 /*number of lines at the top*/ 839 pImagePlanes[0].u_topleft = 840 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[0].u_height\ 841 -Params.m_outputSize.m_height)>>1))*pImagePlanes[0].u_stride; 842 pImagePlanes[0].u_height = Params.m_outputSize.m_height; 843 pImagePlanes[1].u_topleft = 844 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[1].u_height\ 845 -(Params.m_outputSize.m_height>>1)))>>1)*pImagePlanes[1].u_stride; 846 pImagePlanes[1].u_height = Params.m_outputSize.m_height>>1; 847 pImagePlanes[2].u_topleft = 848 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[2].u_height\ 849 -(Params.m_outputSize.m_height>>1)))>>1)*pImagePlanes[2].u_stride; 850 pImagePlanes[2].u_height = Params.m_outputSize.m_height>>1; 851 } 852 else 853 { 854 /*it is width so black borders will be on the left and right side*/ 855 Params.m_outputSize.m_height = pImagePlanes->u_height; 856 Params.m_outputSize.m_width = 857 (M4OSA_UInt32)((pC->m_pDecodedPlane->u_width \ 858 * pImagePlanes->u_height) /pC->m_pDecodedPlane->u_height); 859 860 pImagePlanes[0].u_topleft = 861 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[0].u_width\ 862 -Params.m_outputSize.m_width)>>1)); 863 pImagePlanes[0].u_width = Params.m_outputSize.m_width; 864 pImagePlanes[1].u_topleft = 865 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[1].u_width\ 866 -(Params.m_outputSize.m_width>>1)))>>1); 867 pImagePlanes[1].u_width = Params.m_outputSize.m_width>>1; 868 pImagePlanes[2].u_topleft = 869 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[2].u_width\ 870 -(Params.m_outputSize.m_width>>1)))>>1); 871 pImagePlanes[2].u_width = Params.m_outputSize.m_width>>1; 872 } 873 break; 874 case M4COMMON_kOrientationLeftTop: 875 case M4COMMON_kOrientationLeftBottom: 876 case M4COMMON_kOrientationRightTop: 877 case M4COMMON_kOrientationRightBottom: 878 if((M4OSA_UInt32)((pC->m_pDecodedPlane->u_width * pImagePlanes->u_width)\ 879 /pC->m_pDecodedPlane->u_height) < pImagePlanes->u_height) 880 //Params.m_inputSize.m_height > Params.m_inputSize.m_width) 881 { 882 /*it is height so black borders will be on the top and on 883 the bottom side*/ 884 Params.m_outputSize.m_height = pImagePlanes->u_width; 885 Params.m_outputSize.m_width = 886 (M4OSA_UInt32)((pC->m_pDecodedPlane->u_width \ 887 * pImagePlanes->u_width) /pC->m_pDecodedPlane->u_height); 888 /*number of lines at the top*/ 889 pImagePlanes[0].u_topleft = 890 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[0].u_height\ 891 -Params.m_outputSize.m_width))>>1)*pImagePlanes[0].u_stride)+1; 892 pImagePlanes[0].u_height = Params.m_outputSize.m_width; 893 pImagePlanes[1].u_topleft = 894 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[1].u_height\ 895 -(Params.m_outputSize.m_width>>1)))>>1)\ 896 *pImagePlanes[1].u_stride)+1; 897 pImagePlanes[1].u_height = Params.m_outputSize.m_width>>1; 898 pImagePlanes[2].u_topleft = 899 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[2].u_height\ 900 -(Params.m_outputSize.m_width>>1)))>>1)\ 901 *pImagePlanes[2].u_stride)+1; 902 pImagePlanes[2].u_height = Params.m_outputSize.m_width>>1; 903 } 904 else 905 { 906 /*it is width so black borders will be on the left and right side*/ 907 Params.m_outputSize.m_width = pImagePlanes->u_height; 908 Params.m_outputSize.m_height = 909 (M4OSA_UInt32)((pC->m_pDecodedPlane->u_height\ 910 * pImagePlanes->u_height) /pC->m_pDecodedPlane->u_width); 911 912 pImagePlanes[0].u_topleft = 913 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[0].u_width\ 914 -Params.m_outputSize.m_height))>>1))+1; 915 pImagePlanes[0].u_width = Params.m_outputSize.m_height; 916 pImagePlanes[1].u_topleft = 917 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[1].u_width\ 918 -(Params.m_outputSize.m_height>>1)))>>1))+1; 919 pImagePlanes[1].u_width = Params.m_outputSize.m_height>>1; 920 pImagePlanes[2].u_topleft = 921 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[2].u_width\ 922 -(Params.m_outputSize.m_height>>1)))>>1))+1; 923 pImagePlanes[2].u_width = Params.m_outputSize.m_height>>1; 924 } 925 break; 926 } 927 } 928 929 /** 930 Secondly with pan&zoom*/ 931 else 932 { 933 switch(pBasicTags.orientation) 934 { 935 default: 936 case M4COMMON_kOrientationUnknown: 937 Params.m_outputOrientation = M4COMMON_kOrientationTopLeft; 938 case M4COMMON_kOrientationTopLeft: 939 case M4COMMON_kOrientationTopRight: 940 case M4COMMON_kOrientationBottomRight: 941 case M4COMMON_kOrientationBottomLeft: 942 /*NO ROTATION*/ 943 if((M4OSA_UInt32)((pC->m_pDecodedPlane->u_height * pImagePlanes->u_width)\ 944 /pC->m_pDecodedPlane->u_width) <= pImagePlanes->u_height) 945 //Params.m_inputSize.m_height < Params.m_inputSize.m_width) 946 { 947 /*Black borders will be on the top and bottom of the output video*/ 948 /*Maximum output height if the input image aspect ratio is kept and if 949 the output width is the screen width*/ 950 M4OSA_UInt32 tempOutputSizeHeight = 951 (M4OSA_UInt32)((pC->m_pDecodedPlane->u_height\ 952 * pImagePlanes->u_width) /pC->m_pDecodedPlane->u_width); 953 M4OSA_UInt32 tempInputSizeHeightMax = 0; 954 M4OSA_UInt32 tempFinalInputHeight = 0; 955 /*The output width is the screen width*/ 956 Params.m_outputSize.m_width = pImagePlanes->u_width; 957 tempOutputSizeHeight = (tempOutputSizeHeight>>1)<<1; 958 959 /*Maximum input height according to the maximum output height 960 (proportional to the maximum output height)*/ 961 tempInputSizeHeightMax = (pImagePlanes->u_height\ 962 *Params.m_inputSize.m_height)/tempOutputSizeHeight; 963 tempInputSizeHeightMax = (tempInputSizeHeightMax>>1)<<1; 964 965 /*Check if the maximum possible input height is contained into the 966 input image height*/ 967 if(tempInputSizeHeightMax <= pC->m_pDecodedPlane->u_height) 968 { 969 /*The maximum possible input height is contained in the input 970 image height, 971 that means no black borders, the input pan zoom area will be extended 972 so that the input AIR height will be the maximum possible*/ 973 if(((tempInputSizeHeightMax - Params.m_inputSize.m_height)>>1)\ 974 <= Params.m_inputCoord.m_y 975 && ((tempInputSizeHeightMax - Params.m_inputSize.m_height)>>1)\ 976 <= pC->m_pDecodedPlane->u_height -(Params.m_inputCoord.m_y\ 977 + Params.m_inputSize.m_height)) 978 { 979 /*The input pan zoom area can be extended symmetrically on the 980 top and bottom side*/ 981 Params.m_inputCoord.m_y -= ((tempInputSizeHeightMax \ 982 - Params.m_inputSize.m_height)>>1); 983 } 984 else if(Params.m_inputCoord.m_y < pC->m_pDecodedPlane->u_height\ 985 -(Params.m_inputCoord.m_y + Params.m_inputSize.m_height)) 986 { 987 /*There is not enough place above the input pan zoom area to 988 extend it symmetrically, 989 so extend it to the maximum on the top*/ 990 Params.m_inputCoord.m_y = 0; 991 } 992 else 993 { 994 /*There is not enough place below the input pan zoom area to 995 extend it symmetrically, 996 so extend it to the maximum on the bottom*/ 997 Params.m_inputCoord.m_y = pC->m_pDecodedPlane->u_height \ 998 - tempInputSizeHeightMax; 999 } 1000 /*The input height of the AIR is the maximum possible height*/ 1001 Params.m_inputSize.m_height = tempInputSizeHeightMax; 1002 } 1003 else 1004 { 1005 /*The maximum possible input height is greater than the input 1006 image height, 1007 that means black borders are necessary to keep aspect ratio 1008 The input height of the AIR is all the input image height*/ 1009 Params.m_outputSize.m_height = 1010 (tempOutputSizeHeight*pC->m_pDecodedPlane->u_height)\ 1011 /Params.m_inputSize.m_height; 1012 Params.m_outputSize.m_height = (Params.m_outputSize.m_height>>1)<<1; 1013 Params.m_inputCoord.m_y = 0; 1014 Params.m_inputSize.m_height = pC->m_pDecodedPlane->u_height; 1015 pImagePlanes[0].u_topleft = 1016 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[0].u_height\ 1017 -Params.m_outputSize.m_height)>>1))*pImagePlanes[0].u_stride; 1018 pImagePlanes[0].u_height = Params.m_outputSize.m_height; 1019 pImagePlanes[1].u_topleft = 1020 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[1].u_height\ 1021 -(Params.m_outputSize.m_height>>1)))>>1)\ 1022 *pImagePlanes[1].u_stride); 1023 pImagePlanes[1].u_height = Params.m_outputSize.m_height>>1; 1024 pImagePlanes[2].u_topleft = 1025 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[2].u_height\ 1026 -(Params.m_outputSize.m_height>>1)))>>1)\ 1027 *pImagePlanes[2].u_stride); 1028 pImagePlanes[2].u_height = Params.m_outputSize.m_height>>1; 1029 } 1030 } 1031 else 1032 { 1033 /*Black borders will be on the left and right side of the output video*/ 1034 /*Maximum output width if the input image aspect ratio is kept and if the 1035 output height is the screen height*/ 1036 M4OSA_UInt32 tempOutputSizeWidth = 1037 (M4OSA_UInt32)((pC->m_pDecodedPlane->u_width \ 1038 * pImagePlanes->u_height) /pC->m_pDecodedPlane->u_height); 1039 M4OSA_UInt32 tempInputSizeWidthMax = 0; 1040 M4OSA_UInt32 tempFinalInputWidth = 0; 1041 /*The output height is the screen height*/ 1042 Params.m_outputSize.m_height = pImagePlanes->u_height; 1043 tempOutputSizeWidth = (tempOutputSizeWidth>>1)<<1; 1044 1045 /*Maximum input width according to the maximum output width 1046 (proportional to the maximum output width)*/ 1047 tempInputSizeWidthMax = 1048 (pImagePlanes->u_width*Params.m_inputSize.m_width)\ 1049 /tempOutputSizeWidth; 1050 tempInputSizeWidthMax = (tempInputSizeWidthMax>>1)<<1; 1051 1052 /*Check if the maximum possible input width is contained into the input 1053 image width*/ 1054 if(tempInputSizeWidthMax <= pC->m_pDecodedPlane->u_width) 1055 { 1056 /*The maximum possible input width is contained in the input 1057 image width, 1058 that means no black borders, the input pan zoom area will be extended 1059 so that the input AIR width will be the maximum possible*/ 1060 if(((tempInputSizeWidthMax - Params.m_inputSize.m_width)>>1) \ 1061 <= Params.m_inputCoord.m_x 1062 && ((tempInputSizeWidthMax - Params.m_inputSize.m_width)>>1)\ 1063 <= pC->m_pDecodedPlane->u_width -(Params.m_inputCoord.m_x \ 1064 + Params.m_inputSize.m_width)) 1065 { 1066 /*The input pan zoom area can be extended symmetrically on the 1067 right and left side*/ 1068 Params.m_inputCoord.m_x -= ((tempInputSizeWidthMax\ 1069 - Params.m_inputSize.m_width)>>1); 1070 } 1071 else if(Params.m_inputCoord.m_x < pC->m_pDecodedPlane->u_width\ 1072 -(Params.m_inputCoord.m_x + Params.m_inputSize.m_width)) 1073 { 1074 /*There is not enough place above the input pan zoom area to 1075 extend it symmetrically, 1076 so extend it to the maximum on the left*/ 1077 Params.m_inputCoord.m_x = 0; 1078 } 1079 else 1080 { 1081 /*There is not enough place below the input pan zoom area 1082 to extend it symmetrically, 1083 so extend it to the maximum on the right*/ 1084 Params.m_inputCoord.m_x = pC->m_pDecodedPlane->u_width \ 1085 - tempInputSizeWidthMax; 1086 } 1087 /*The input width of the AIR is the maximum possible width*/ 1088 Params.m_inputSize.m_width = tempInputSizeWidthMax; 1089 } 1090 else 1091 { 1092 /*The maximum possible input width is greater than the input 1093 image width, 1094 that means black borders are necessary to keep aspect ratio 1095 The input width of the AIR is all the input image width*/ 1096 Params.m_outputSize.m_width =\ 1097 (tempOutputSizeWidth*pC->m_pDecodedPlane->u_width)\ 1098 /Params.m_inputSize.m_width; 1099 Params.m_outputSize.m_width = (Params.m_outputSize.m_width>>1)<<1; 1100 Params.m_inputCoord.m_x = 0; 1101 Params.m_inputSize.m_width = pC->m_pDecodedPlane->u_width; 1102 pImagePlanes[0].u_topleft = 1103 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[0].u_width\ 1104 -Params.m_outputSize.m_width)>>1)); 1105 pImagePlanes[0].u_width = Params.m_outputSize.m_width; 1106 pImagePlanes[1].u_topleft = 1107 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[1].u_width\ 1108 -(Params.m_outputSize.m_width>>1)))>>1); 1109 pImagePlanes[1].u_width = Params.m_outputSize.m_width>>1; 1110 pImagePlanes[2].u_topleft = 1111 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[2].u_width\ 1112 -(Params.m_outputSize.m_width>>1)))>>1); 1113 pImagePlanes[2].u_width = Params.m_outputSize.m_width>>1; 1114 } 1115 } 1116 break; 1117 case M4COMMON_kOrientationLeftTop: 1118 case M4COMMON_kOrientationLeftBottom: 1119 case M4COMMON_kOrientationRightTop: 1120 case M4COMMON_kOrientationRightBottom: 1121 /*ROTATION*/ 1122 if((M4OSA_UInt32)((pC->m_pDecodedPlane->u_width * pImagePlanes->u_width)\ 1123 /pC->m_pDecodedPlane->u_height) < pImagePlanes->u_height) 1124 //Params.m_inputSize.m_height > Params.m_inputSize.m_width) 1125 { 1126 /*Black borders will be on the left and right side of the output video*/ 1127 /*Maximum output height if the input image aspect ratio is kept and if 1128 the output height is the screen width*/ 1129 M4OSA_UInt32 tempOutputSizeHeight = 1130 (M4OSA_UInt32)((pC->m_pDecodedPlane->u_width * pImagePlanes->u_width)\ 1131 /pC->m_pDecodedPlane->u_height); 1132 M4OSA_UInt32 tempInputSizeHeightMax = 0; 1133 M4OSA_UInt32 tempFinalInputHeight = 0; 1134 /*The output width is the screen height*/ 1135 Params.m_outputSize.m_height = pImagePlanes->u_width; 1136 Params.m_outputSize.m_width= pImagePlanes->u_height; 1137 tempOutputSizeHeight = (tempOutputSizeHeight>>1)<<1; 1138 1139 /*Maximum input height according to the maximum output height 1140 (proportional to the maximum output height)*/ 1141 tempInputSizeHeightMax = 1142 (pImagePlanes->u_height*Params.m_inputSize.m_width)\ 1143 /tempOutputSizeHeight; 1144 tempInputSizeHeightMax = (tempInputSizeHeightMax>>1)<<1; 1145 1146 /*Check if the maximum possible input height is contained into the 1147 input image width (rotation included)*/ 1148 if(tempInputSizeHeightMax <= pC->m_pDecodedPlane->u_width) 1149 { 1150 /*The maximum possible input height is contained in the input 1151 image width (rotation included), 1152 that means no black borders, the input pan zoom area will be extended 1153 so that the input AIR width will be the maximum possible*/ 1154 if(((tempInputSizeHeightMax - Params.m_inputSize.m_width)>>1) \ 1155 <= Params.m_inputCoord.m_x 1156 && ((tempInputSizeHeightMax - Params.m_inputSize.m_width)>>1)\ 1157 <= pC->m_pDecodedPlane->u_width -(Params.m_inputCoord.m_x \ 1158 + Params.m_inputSize.m_width)) 1159 { 1160 /*The input pan zoom area can be extended symmetrically on the 1161 right and left side*/ 1162 Params.m_inputCoord.m_x -= ((tempInputSizeHeightMax \ 1163 - Params.m_inputSize.m_width)>>1); 1164 } 1165 else if(Params.m_inputCoord.m_x < pC->m_pDecodedPlane->u_width\ 1166 -(Params.m_inputCoord.m_x + Params.m_inputSize.m_width)) 1167 { 1168 /*There is not enough place on the left of the input pan 1169 zoom area to extend it symmetrically, 1170 so extend it to the maximum on the left*/ 1171 Params.m_inputCoord.m_x = 0; 1172 } 1173 else 1174 { 1175 /*There is not enough place on the right of the input pan zoom 1176 area to extend it symmetrically, 1177 so extend it to the maximum on the right*/ 1178 Params.m_inputCoord.m_x = 1179 pC->m_pDecodedPlane->u_width - tempInputSizeHeightMax; 1180 } 1181 /*The input width of the AIR is the maximum possible width*/ 1182 Params.m_inputSize.m_width = tempInputSizeHeightMax; 1183 } 1184 else 1185 { 1186 /*The maximum possible input height is greater than the input 1187 image width (rotation included), 1188 that means black borders are necessary to keep aspect ratio 1189 The input width of the AIR is all the input image width*/ 1190 Params.m_outputSize.m_width = 1191 (tempOutputSizeHeight*pC->m_pDecodedPlane->u_width)\ 1192 /Params.m_inputSize.m_width; 1193 Params.m_outputSize.m_width = (Params.m_outputSize.m_width>>1)<<1; 1194 Params.m_inputCoord.m_x = 0; 1195 Params.m_inputSize.m_width = pC->m_pDecodedPlane->u_width; 1196 pImagePlanes[0].u_topleft = 1197 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[0].u_height\ 1198 -Params.m_outputSize.m_width))>>1)*pImagePlanes[0].u_stride)+1; 1199 pImagePlanes[0].u_height = Params.m_outputSize.m_width; 1200 pImagePlanes[1].u_topleft = 1201 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[1].u_height\ 1202 -(Params.m_outputSize.m_width>>1)))>>1)\ 1203 *pImagePlanes[1].u_stride)+1; 1204 pImagePlanes[1].u_height = Params.m_outputSize.m_width>>1; 1205 pImagePlanes[2].u_topleft = 1206 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[2].u_height\ 1207 -(Params.m_outputSize.m_width>>1)))>>1)\ 1208 *pImagePlanes[2].u_stride)+1; 1209 pImagePlanes[2].u_height = Params.m_outputSize.m_width>>1; 1210 } 1211 } 1212 else 1213 { 1214 /*Black borders will be on the top and bottom of the output video*/ 1215 /*Maximum output width if the input image aspect ratio is kept and if 1216 the output width is the screen height*/ 1217 M4OSA_UInt32 tempOutputSizeWidth = 1218 (M4OSA_UInt32)((pC->m_pDecodedPlane->u_height * pImagePlanes->u_height)\ 1219 /pC->m_pDecodedPlane->u_width); 1220 M4OSA_UInt32 tempInputSizeWidthMax = 0; 1221 M4OSA_UInt32 tempFinalInputWidth = 0, tempFinalOutputWidth = 0; 1222 /*The output height is the screen width*/ 1223 Params.m_outputSize.m_width = pImagePlanes->u_height; 1224 Params.m_outputSize.m_height= pImagePlanes->u_width; 1225 tempOutputSizeWidth = (tempOutputSizeWidth>>1)<<1; 1226 1227 /*Maximum input width according to the maximum output width 1228 (proportional to the maximum output width)*/ 1229 tempInputSizeWidthMax = 1230 (pImagePlanes->u_width*Params.m_inputSize.m_height)/tempOutputSizeWidth; 1231 tempInputSizeWidthMax = (tempInputSizeWidthMax>>1)<<1; 1232 1233 /*Check if the maximum possible input width is contained into the input 1234 image height (rotation included)*/ 1235 if(tempInputSizeWidthMax <= pC->m_pDecodedPlane->u_height) 1236 { 1237 /*The maximum possible input width is contained in the input 1238 image height (rotation included), 1239 that means no black borders, the input pan zoom area will be extended 1240 so that the input AIR height will be the maximum possible*/ 1241 if(((tempInputSizeWidthMax - Params.m_inputSize.m_height)>>1) \ 1242 <= Params.m_inputCoord.m_y 1243 && ((tempInputSizeWidthMax - Params.m_inputSize.m_height)>>1)\ 1244 <= pC->m_pDecodedPlane->u_height -(Params.m_inputCoord.m_y \ 1245 + Params.m_inputSize.m_height)) 1246 { 1247 /*The input pan zoom area can be extended symmetrically on 1248 the right and left side*/ 1249 Params.m_inputCoord.m_y -= ((tempInputSizeWidthMax \ 1250 - Params.m_inputSize.m_height)>>1); 1251 } 1252 else if(Params.m_inputCoord.m_y < pC->m_pDecodedPlane->u_height\ 1253 -(Params.m_inputCoord.m_y + Params.m_inputSize.m_height)) 1254 { 1255 /*There is not enough place on the top of the input pan zoom 1256 area to extend it symmetrically, 1257 so extend it to the maximum on the top*/ 1258 Params.m_inputCoord.m_y = 0; 1259 } 1260 else 1261 { 1262 /*There is not enough place on the bottom of the input pan zoom 1263 area to extend it symmetrically, 1264 so extend it to the maximum on the bottom*/ 1265 Params.m_inputCoord.m_y = pC->m_pDecodedPlane->u_height\ 1266 - tempInputSizeWidthMax; 1267 } 1268 /*The input height of the AIR is the maximum possible height*/ 1269 Params.m_inputSize.m_height = tempInputSizeWidthMax; 1270 } 1271 else 1272 { 1273 /*The maximum possible input width is greater than the input\ 1274 image height (rotation included), 1275 that means black borders are necessary to keep aspect ratio 1276 The input height of the AIR is all the input image height*/ 1277 Params.m_outputSize.m_height = 1278 (tempOutputSizeWidth*pC->m_pDecodedPlane->u_height)\ 1279 /Params.m_inputSize.m_height; 1280 Params.m_outputSize.m_height = (Params.m_outputSize.m_height>>1)<<1; 1281 Params.m_inputCoord.m_y = 0; 1282 Params.m_inputSize.m_height = pC->m_pDecodedPlane->u_height; 1283 pImagePlanes[0].u_topleft = 1284 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[0].u_width\ 1285 -Params.m_outputSize.m_height))>>1))+1; 1286 pImagePlanes[0].u_width = Params.m_outputSize.m_height; 1287 pImagePlanes[1].u_topleft = 1288 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[1].u_width\ 1289 -(Params.m_outputSize.m_height>>1)))>>1))+1; 1290 pImagePlanes[1].u_width = Params.m_outputSize.m_height>>1; 1291 pImagePlanes[2].u_topleft = 1292 ((M4xVSS_ABS((M4OSA_Int32)(pImagePlanes[2].u_width\ 1293 -(Params.m_outputSize.m_height>>1)))>>1))+1; 1294 pImagePlanes[2].u_width = Params.m_outputSize.m_height>>1; 1295 } 1296 } 1297 break; 1298 } 1299 } 1300 1301 /*Width and height have to be even*/ 1302 Params.m_outputSize.m_width = (Params.m_outputSize.m_width>>1)<<1; 1303 Params.m_outputSize.m_height = (Params.m_outputSize.m_height>>1)<<1; 1304 Params.m_inputSize.m_width = (Params.m_inputSize.m_width>>1)<<1; 1305 Params.m_inputSize.m_height = (Params.m_inputSize.m_height>>1)<<1; 1306 pImagePlanes[0].u_width = (pImagePlanes[0].u_width>>1)<<1; 1307 pImagePlanes[1].u_width = (pImagePlanes[1].u_width>>1)<<1; 1308 pImagePlanes[2].u_width = (pImagePlanes[2].u_width>>1)<<1; 1309 pImagePlanes[0].u_height = (pImagePlanes[0].u_height>>1)<<1; 1310 pImagePlanes[1].u_height = (pImagePlanes[1].u_height>>1)<<1; 1311 pImagePlanes[2].u_height = (pImagePlanes[2].u_height>>1)<<1; 1312 1313 /*Check that values are coherent*/ 1314 if(Params.m_inputSize.m_height == Params.m_outputSize.m_height) 1315 { 1316 Params.m_inputSize.m_width = Params.m_outputSize.m_width; 1317 } 1318 else if(Params.m_inputSize.m_width == Params.m_outputSize.m_width) 1319 { 1320 Params.m_inputSize.m_height = Params.m_outputSize.m_height; 1321 } 1322 } 1323 1324 /** 1325 Picture rendering: Resizing and Cropping*/ 1326 if(pC->m_mediaRendering != M4xVSS_kBlackBorders) 1327 { 1328 switch(pBasicTags.orientation) 1329 { 1330 default: 1331 case M4COMMON_kOrientationUnknown: 1332 Params.m_outputOrientation = M4COMMON_kOrientationTopLeft; 1333 case M4COMMON_kOrientationTopLeft: 1334 case M4COMMON_kOrientationTopRight: 1335 case M4COMMON_kOrientationBottomRight: 1336 case M4COMMON_kOrientationBottomLeft: 1337 Params.m_outputSize.m_height = pImagePlanes->u_height; 1338 Params.m_outputSize.m_width = pImagePlanes->u_width; 1339 break; 1340 case M4COMMON_kOrientationLeftTop: 1341 case M4COMMON_kOrientationLeftBottom: 1342 case M4COMMON_kOrientationRightTop: 1343 case M4COMMON_kOrientationRightBottom: 1344 Params.m_outputSize.m_height = pImagePlanes->u_width; 1345 Params.m_outputSize.m_width = pImagePlanes->u_height; 1346 break; 1347 } 1348 } 1349 1350 /** 1351 Picture rendering: Cropping*/ 1352 if(pC->m_mediaRendering == M4xVSS_kCropping) 1353 { 1354 if((Params.m_outputSize.m_height * Params.m_inputSize.m_width)\ 1355 /Params.m_outputSize.m_width<Params.m_inputSize.m_height) 1356 { 1357 M4OSA_UInt32 tempHeight = Params.m_inputSize.m_height; 1358 /*height will be cropped*/ 1359 Params.m_inputSize.m_height = (M4OSA_UInt32)((Params.m_outputSize.m_height \ 1360 * Params.m_inputSize.m_width) /Params.m_outputSize.m_width); 1361 Params.m_inputSize.m_height = (Params.m_inputSize.m_height>>1)<<1; 1362 if(M4OSA_FALSE == pC->m_pPto3GPPparams->isPanZoom) 1363 { 1364 Params.m_inputCoord.m_y = (M4OSA_Int32)((M4OSA_Int32)\ 1365 ((pC->m_pDecodedPlane->u_height - Params.m_inputSize.m_height))>>1); 1366 } 1367 else 1368 { 1369 Params.m_inputCoord.m_y += (M4OSA_Int32)((M4OSA_Int32)\ 1370 ((tempHeight - Params.m_inputSize.m_height))>>1); 1371 } 1372 } 1373 else 1374 { 1375 M4OSA_UInt32 tempWidth= Params.m_inputSize.m_width; 1376 /*width will be cropped*/ 1377 Params.m_inputSize.m_width = (M4OSA_UInt32)((Params.m_outputSize.m_width \ 1378 * Params.m_inputSize.m_height) /Params.m_outputSize.m_height); 1379 Params.m_inputSize.m_width = (Params.m_inputSize.m_width>>1)<<1; 1380 if(M4OSA_FALSE == pC->m_pPto3GPPparams->isPanZoom) 1381 { 1382 Params.m_inputCoord.m_x = (M4OSA_Int32)((M4OSA_Int32)\ 1383 ((pC->m_pDecodedPlane->u_width - Params.m_inputSize.m_width))>>1); 1384 } 1385 else 1386 { 1387 Params.m_inputCoord.m_x += (M4OSA_Int32)\ 1388 (((M4OSA_Int32)(tempWidth - Params.m_inputSize.m_width))>>1); 1389 } 1390 } 1391 } 1392 1393 1394 1395 /** 1396 * Call AIR functions */ 1397 if(M4OSA_NULL == pC->m_air_context) 1398 { 1399 err = M4AIR_create(&pC->m_air_context, M4AIR_kYUV420P); 1400 if(err != M4NO_ERROR) 1401 { 1402 free(pC->m_pDecodedPlane[0].pac_data); 1403 free(pC->m_pDecodedPlane); 1404 pC->m_pDecodedPlane = M4OSA_NULL; 1405 M4OSA_TRACE1_1("M4xVSS_PictureCallbackFct:\ 1406 Error when initializing AIR: 0x%x", err); 1407 return err; 1408 } 1409 } 1410 1411 err = M4AIR_configure(pC->m_air_context, &Params); 1412 if(err != M4NO_ERROR) 1413 { 1414 M4OSA_TRACE1_1("M4xVSS_PictureCallbackFct:\ 1415 Error when configuring AIR: 0x%x", err); 1416 M4AIR_cleanUp(pC->m_air_context); 1417 free(pC->m_pDecodedPlane[0].pac_data); 1418 free(pC->m_pDecodedPlane); 1419 pC->m_pDecodedPlane = M4OSA_NULL; 1420 return err; 1421 } 1422 1423 err = M4AIR_get(pC->m_air_context, pC->m_pDecodedPlane, pImagePlanes); 1424 if(err != M4NO_ERROR) 1425 { 1426 M4OSA_TRACE1_1("M4xVSS_PictureCallbackFct: Error when getting AIR plane: 0x%x", err); 1427 M4AIR_cleanUp(pC->m_air_context); 1428 free(pC->m_pDecodedPlane[0].pac_data); 1429 free(pC->m_pDecodedPlane); 1430 pC->m_pDecodedPlane = M4OSA_NULL; 1431 return err; 1432 } 1433 pImagePlanes[0] = pImagePlanes1; 1434 pImagePlanes[1] = pImagePlanes2; 1435 pImagePlanes[2] = pImagePlanes3; 1436 } 1437 1438 1439 /** 1440 * Increment the image counter */ 1441 pC->m_ImageCounter++; 1442 1443 /** 1444 * Check end of sequence */ 1445 last_frame_flag = (pC->m_ImageCounter >= pC->m_NbImage); 1446 1447 /** 1448 * Keep the picture duration */ 1449 *pPictureDuration = pC->m_timeDuration; 1450 1451 if (1 == last_frame_flag) 1452 { 1453 if(M4OSA_NULL != pC->m_air_context) 1454 { 1455 err = M4AIR_cleanUp(pC->m_air_context); 1456 if(err != M4NO_ERROR) 1457 { 1458 M4OSA_TRACE1_1("M4xVSS_PictureCallbackFct: Error when cleaning AIR: 0x%x", err); 1459 return err; 1460 } 1461 } 1462 if(M4OSA_NULL != pC->m_pDecodedPlane) 1463 { 1464 free(pC->m_pDecodedPlane[0].pac_data); 1465 free(pC->m_pDecodedPlane); 1466 pC->m_pDecodedPlane = M4OSA_NULL; 1467 } 1468 return M4PTO3GPP_WAR_LAST_PICTURE; 1469 } 1470 1471 M4OSA_TRACE1_0("M4xVSS_PictureCallbackFct: Leaving "); 1472 return M4NO_ERROR; 1473 } 1474 1475 /** 1476 ****************************************************************************** 1477 * M4OSA_ERR M4xVSS_internalStartConvertPictureTo3gp(M4OSA_Context pContext) 1478 * @brief This function initializes Pto3GPP with the given parameters 1479 * @note The "Pictures to 3GPP" parameters are given by the internal xVSS 1480 * context. This context contains a pointer on the current element 1481 * of the chained list of Pto3GPP parameters. 1482 * @param pContext (IN) The integrator own context 1483 * 1484 * @return M4NO_ERROR: No error 1485 * @return M4PTO3GPP_WAR_LAST_PICTURE: The returned image is the last one 1486 * @return M4ERR_PARAMETER: At least one of the function parameters is null 1487 ****************************************************************************** 1488 */ 1489 M4OSA_ERR M4xVSS_internalStartConvertPictureTo3gp(M4OSA_Context pContext) 1490 { 1491 /************************************************************************/ 1492 /* Definitions to generate dummy AMR file used to add AMR silence in files generated 1493 by Pto3GPP */ 1494 #define M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE 13 1495 /* This constant is defined in M4VSS3GPP_InternalConfig.h */ 1496 extern const M4OSA_UInt8\ 1497 M4VSS3GPP_AMR_AU_SILENCE_FRAME_048[M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE]; 1498 1499 /* AMR silent frame used to compute dummy AMR silence file */ 1500 #define M4VSS3GPP_AMR_HEADER_SIZE 6 1501 const M4OSA_UInt8 M4VSS3GPP_AMR_HEADER[M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE] = 1502 { 0x23, 0x21, 0x41, 0x4d, 0x52, 0x0a }; 1503 /************************************************************************/ 1504 1505 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 1506 M4OSA_ERR err; 1507 M4PTO3GPP_Context pM4PTO3GPP_Ctxt = M4OSA_NULL; 1508 M4PTO3GPP_Params Params; 1509 M4xVSS_PictureCallbackCtxt* pCallBackCtxt; 1510 M4OSA_Bool cmpResult=M4OSA_FALSE; 1511 M4OSA_Context pDummyAMRFile; 1512 M4OSA_Char out_amr[M4XVSS_MAX_PATH_LEN]; 1513 /*UTF conversion support*/ 1514 M4OSA_Char* pDecodedPath = M4OSA_NULL; 1515 M4OSA_UInt32 i; 1516 1517 /** 1518 * Create a M4PTO3GPP instance */ 1519 err = M4PTO3GPP_Init( &pM4PTO3GPP_Ctxt, xVSS_context->pFileReadPtr, 1520 xVSS_context->pFileWritePtr); 1521 if (err != M4NO_ERROR) 1522 { 1523 M4OSA_TRACE1_1("M4xVSS_internalStartConvertPictureTo3gp returned %ld\n",err); 1524 return err; 1525 } 1526 1527 pCallBackCtxt = (M4xVSS_PictureCallbackCtxt*)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_PictureCallbackCtxt), 1528 M4VS,(M4OSA_Char *) "Pto3gpp callback struct"); 1529 if(pCallBackCtxt == M4OSA_NULL) 1530 { 1531 M4OSA_TRACE1_0("Allocation error in M4xVSS_internalStartConvertPictureTo3gp"); 1532 return M4ERR_ALLOC; 1533 } 1534 1535 Params.OutputVideoFrameSize = xVSS_context->pSettings->xVSS.outputVideoSize; 1536 Params.OutputVideoFormat = xVSS_context->pSettings->xVSS.outputVideoFormat; 1537 Params.videoProfile = xVSS_context->pSettings->xVSS.outputVideoProfile; 1538 Params.videoLevel = xVSS_context->pSettings->xVSS.outputVideoLevel; 1539 1540 /** 1541 * Generate "dummy" amr file containing silence in temporary folder */ 1542 M4OSA_chrNCopy(out_amr, xVSS_context->pTempPath, M4XVSS_MAX_PATH_LEN - 1); 1543 strncat((char *)out_amr, (const char *)"dummy.amr\0", 10); 1544 1545 /** 1546 * UTF conversion: convert the temporary path into the customer format*/ 1547 pDecodedPath = out_amr; 1548 1549 if(xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL 1550 && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL) 1551 { 1552 M4OSA_UInt32 length = 0; 1553 err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void*) out_amr, 1554 (M4OSA_Void*) xVSS_context->UTFConversionContext.pTempOutConversionBuffer, &length); 1555 if(err != M4NO_ERROR) 1556 { 1557 M4OSA_TRACE1_1("M4xVSS_internalStartConvertPictureTo3gp:\ 1558 M4xVSS_internalConvertFromUTF8 returns err: 0x%x",err); 1559 return err; 1560 } 1561 pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; 1562 } 1563 1564 /** 1565 * End of the conversion, now use the converted path*/ 1566 1567 err = xVSS_context->pFileWritePtr->openWrite(&pDummyAMRFile, pDecodedPath, M4OSA_kFileWrite); 1568 1569 /*Commented because of the use of the UTF conversion see above*/ 1570 /* err = xVSS_context->pFileWritePtr->openWrite(&pDummyAMRFile, out_amr, M4OSA_kFileWrite); 1571 */ 1572 if(err != M4NO_ERROR) 1573 { 1574 M4OSA_TRACE1_2("M4xVSS_internalConvertPictureTo3gp: Can't open output dummy amr file %s,\ 1575 error: 0x%x\n",out_amr, err); 1576 return err; 1577 } 1578 1579 err = xVSS_context->pFileWritePtr->writeData(pDummyAMRFile, 1580 (M4OSA_Int8*)M4VSS3GPP_AMR_HEADER, M4VSS3GPP_AMR_HEADER_SIZE); 1581 if(err != M4NO_ERROR) 1582 { 1583 M4OSA_TRACE1_2("M4xVSS_internalConvertPictureTo3gp: Can't write output dummy amr file %s,\ 1584 error: 0x%x\n",out_amr, err); 1585 return err; 1586 } 1587 1588 err = xVSS_context->pFileWritePtr->writeData(pDummyAMRFile, 1589 (M4OSA_Int8*)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048, M4VSS3GPP_AMR_AU_SILENCE_FRAME_048_SIZE); 1590 if(err != M4NO_ERROR) 1591 { 1592 M4OSA_TRACE1_2("M4xVSS_internalConvertPictureTo3gp: \ 1593 Can't write output dummy amr file %s, error: 0x%x\n",out_amr, err); 1594 return err; 1595 } 1596 1597 err = xVSS_context->pFileWritePtr->closeWrite(pDummyAMRFile); 1598 if(err != M4NO_ERROR) 1599 { 1600 M4OSA_TRACE1_2("M4xVSS_internalConvertPictureTo3gp: \ 1601 Can't close output dummy amr file %s, error: 0x%x\n",out_amr, err); 1602 return err; 1603 } 1604 1605 /** 1606 * Fill parameters for Pto3GPP with the parameters contained in the current element of the 1607 * Pto3GPP parameters chained list and with default parameters */ 1608 /*+ New Encoder bitrates */ 1609 if(xVSS_context->pSettings->xVSS.outputVideoBitrate == 0) { 1610 Params.OutputVideoBitrate = M4VIDEOEDITING_kVARIABLE_KBPS; 1611 } 1612 else { 1613 Params.OutputVideoBitrate = xVSS_context->pSettings->xVSS.outputVideoBitrate; 1614 } 1615 M4OSA_TRACE1_1("M4xVSS_internalStartConvertPicTo3GP: video bitrate = %d", 1616 Params.OutputVideoBitrate); 1617 /*- New Encoder bitrates */ 1618 Params.OutputFileMaxSize = M4PTO3GPP_kUNLIMITED; 1619 Params.pPictureCallbackFct = M4xVSS_PictureCallbackFct; 1620 Params.pPictureCallbackCtxt = pCallBackCtxt; 1621 /*FB: change to use the converted path (UTF conversion) see the conversion above*/ 1622 /*Fix :- Adding Audio Track in Image as input :AudioTarckFile Setting to NULL */ 1623 Params.pInputAudioTrackFile = M4OSA_NULL;//(M4OSA_Void*)pDecodedPath;//out_amr; 1624 Params.AudioPaddingMode = M4PTO3GPP_kAudioPaddingMode_Loop; 1625 Params.AudioFileFormat = M4VIDEOEDITING_kFileType_AMR; 1626 Params.pOutput3gppFile = xVSS_context->pPTo3GPPcurrentParams->pFileOut; 1627 Params.pTemporaryFile = xVSS_context->pPTo3GPPcurrentParams->pFileTemp; 1628 /*+PR No: blrnxpsw#223*/ 1629 /*Increasing frequency of Frame, calculating Nos of Frame = duration /FPS */ 1630 /*Other changes made is @ M4xVSS_API.c @ line 3841 in M4xVSS_SendCommand*/ 1631 /*If case check for PanZoom removed */ 1632 Params.NbVideoFrames = (M4OSA_UInt32) 1633 (xVSS_context->pPTo3GPPcurrentParams->duration \ 1634 / xVSS_context->pPTo3GPPcurrentParams->framerate); /* */ 1635 pCallBackCtxt->m_timeDuration = xVSS_context->pPTo3GPPcurrentParams->framerate; 1636 /*-PR No: blrnxpsw#223*/ 1637 pCallBackCtxt->m_ImageCounter = 0; 1638 pCallBackCtxt->m_FileIn = xVSS_context->pPTo3GPPcurrentParams->pFileIn; 1639 pCallBackCtxt->m_NbImage = Params.NbVideoFrames; 1640 pCallBackCtxt->m_pFileReadPtr = xVSS_context->pFileReadPtr; 1641 pCallBackCtxt->m_pDecodedPlane = M4OSA_NULL; 1642 pCallBackCtxt->m_pPto3GPPparams = xVSS_context->pPTo3GPPcurrentParams; 1643 pCallBackCtxt->m_air_context = M4OSA_NULL; 1644 pCallBackCtxt->m_mediaRendering = xVSS_context->pPTo3GPPcurrentParams->MediaRendering; 1645 1646 /** 1647 * Set the input and output files */ 1648 err = M4PTO3GPP_Open(pM4PTO3GPP_Ctxt, &Params); 1649 if (err != M4NO_ERROR) 1650 { 1651 M4OSA_TRACE1_1("M4PTO3GPP_Open returned: 0x%x\n",err); 1652 if(pCallBackCtxt != M4OSA_NULL) 1653 { 1654 free(pCallBackCtxt); 1655 pCallBackCtxt = M4OSA_NULL; 1656 } 1657 M4PTO3GPP_CleanUp(pM4PTO3GPP_Ctxt); 1658 return err; 1659 } 1660 1661 /** 1662 * Save context to be able to call Pto3GPP step function in M4xVSS_step function */ 1663 xVSS_context->pM4PTO3GPP_Ctxt = pM4PTO3GPP_Ctxt; 1664 xVSS_context->pCallBackCtxt = pCallBackCtxt; 1665 1666 return M4NO_ERROR; 1667 } 1668 1669 /** 1670 ****************************************************************************** 1671 * M4OSA_ERR M4xVSS_internalStopConvertPictureTo3gp(M4OSA_Context pContext) 1672 * @brief This function cleans up Pto3GPP 1673 * @note 1674 * @param pContext (IN) The integrator own context 1675 * 1676 * @return M4NO_ERROR: No error 1677 * @return M4ERR_PARAMETER: At least one of the function parameters is null 1678 ****************************************************************************** 1679 */ 1680 M4OSA_ERR M4xVSS_internalStopConvertPictureTo3gp(M4OSA_Context pContext) 1681 { 1682 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 1683 M4OSA_ERR err; 1684 M4OSA_Char out_amr[M4XVSS_MAX_PATH_LEN]; 1685 /*UTF conversion support*/ 1686 M4OSA_Char* pDecodedPath = M4OSA_NULL; 1687 1688 /** 1689 * Free the PTO3GPP callback context */ 1690 if(M4OSA_NULL != xVSS_context->pCallBackCtxt) 1691 { 1692 free(xVSS_context->pCallBackCtxt); 1693 xVSS_context->pCallBackCtxt = M4OSA_NULL; 1694 } 1695 1696 /** 1697 * Finalize the output file */ 1698 err = M4PTO3GPP_Close(xVSS_context->pM4PTO3GPP_Ctxt); 1699 if (err != M4NO_ERROR) 1700 { 1701 M4OSA_TRACE1_1("M4PTO3GPP_Close returned 0x%x\n",err); 1702 M4PTO3GPP_CleanUp(xVSS_context->pM4PTO3GPP_Ctxt); 1703 return err; 1704 } 1705 1706 /** 1707 * Free this M4PTO3GPP instance */ 1708 err = M4PTO3GPP_CleanUp(xVSS_context->pM4PTO3GPP_Ctxt); 1709 if (err != M4NO_ERROR) 1710 { 1711 M4OSA_TRACE1_1("M4PTO3GPP_CleanUp returned 0x%x\n",err); 1712 return err; 1713 } 1714 1715 /** 1716 * Remove dummy.amr file */ 1717 M4OSA_chrNCopy(out_amr, xVSS_context->pTempPath, M4XVSS_MAX_PATH_LEN - 1); 1718 strncat((char *)out_amr, (const char *)"dummy.amr\0", 10); 1719 1720 /** 1721 * UTF conversion: convert the temporary path into the customer format*/ 1722 pDecodedPath = out_amr; 1723 1724 if(xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL 1725 && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL) 1726 { 1727 M4OSA_UInt32 length = 0; 1728 err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void*) out_amr, 1729 (M4OSA_Void*) xVSS_context->UTFConversionContext.pTempOutConversionBuffer, &length); 1730 if(err != M4NO_ERROR) 1731 { 1732 M4OSA_TRACE1_1("M4xVSS_internalStopConvertPictureTo3gp:\ 1733 M4xVSS_internalConvertFromUTF8 returns err: 0x%x",err); 1734 return err; 1735 } 1736 pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; 1737 } 1738 /** 1739 * End of the conversion, now use the decoded path*/ 1740 remove((const char *)pDecodedPath); 1741 1742 /*Commented because of the use of the UTF conversion*/ 1743 /* remove(out_amr); 1744 */ 1745 1746 xVSS_context->pM4PTO3GPP_Ctxt = M4OSA_NULL; 1747 xVSS_context->pCallBackCtxt = M4OSA_NULL; 1748 1749 return M4NO_ERROR; 1750 } 1751 1752 /** 1753 ****************************************************************************** 1754 * prototype M4OSA_ERR M4xVSS_internalConvertRGBtoYUV(M4xVSS_FramingStruct* framingCtx) 1755 * @brief This function converts an RGB565 plane to YUV420 planar 1756 * @note It is used only for framing effect 1757 * It allocates output YUV planes 1758 * @param framingCtx (IN) The framing struct containing input RGB565 plane 1759 * 1760 * @return M4NO_ERROR: No error 1761 * @return M4ERR_PARAMETER: At least one of the function parameters is null 1762 * @return M4ERR_ALLOC: Allocation error (no more memory) 1763 ****************************************************************************** 1764 */ 1765 M4OSA_ERR M4xVSS_internalConvertRGBtoYUV(M4xVSS_FramingStruct* framingCtx) 1766 { 1767 M4OSA_ERR err; 1768 1769 /** 1770 * Allocate output YUV planes */ 1771 framingCtx->FramingYuv = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(3*sizeof(M4VIFI_ImagePlane), 1772 M4VS, (M4OSA_Char *)"M4xVSS_internalConvertRGBtoYUV: Output plane YUV"); 1773 if(framingCtx->FramingYuv == M4OSA_NULL) 1774 { 1775 M4OSA_TRACE1_0("Allocation error in M4xVSS_internalConvertRGBtoYUV"); 1776 return M4ERR_ALLOC; 1777 } 1778 framingCtx->FramingYuv[0].u_width = framingCtx->FramingRgb->u_width; 1779 framingCtx->FramingYuv[0].u_height = framingCtx->FramingRgb->u_height; 1780 framingCtx->FramingYuv[0].u_topleft = 0; 1781 framingCtx->FramingYuv[0].u_stride = framingCtx->FramingRgb->u_width; 1782 framingCtx->FramingYuv[0].pac_data = 1783 (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc((framingCtx->FramingYuv[0].u_width\ 1784 *framingCtx->FramingYuv[0].u_height*3)>>1, M4VS, (M4OSA_Char *)\ 1785 "Alloc for the Convertion output YUV");; 1786 if(framingCtx->FramingYuv[0].pac_data == M4OSA_NULL) 1787 { 1788 M4OSA_TRACE1_0("Allocation error in M4xVSS_internalConvertRGBtoYUV"); 1789 return M4ERR_ALLOC; 1790 } 1791 framingCtx->FramingYuv[1].u_width = (framingCtx->FramingRgb->u_width)>>1; 1792 framingCtx->FramingYuv[1].u_height = (framingCtx->FramingRgb->u_height)>>1; 1793 framingCtx->FramingYuv[1].u_topleft = 0; 1794 framingCtx->FramingYuv[1].u_stride = (framingCtx->FramingRgb->u_width)>>1; 1795 framingCtx->FramingYuv[1].pac_data = framingCtx->FramingYuv[0].pac_data \ 1796 + framingCtx->FramingYuv[0].u_width * framingCtx->FramingYuv[0].u_height; 1797 framingCtx->FramingYuv[2].u_width = (framingCtx->FramingRgb->u_width)>>1; 1798 framingCtx->FramingYuv[2].u_height = (framingCtx->FramingRgb->u_height)>>1; 1799 framingCtx->FramingYuv[2].u_topleft = 0; 1800 framingCtx->FramingYuv[2].u_stride = (framingCtx->FramingRgb->u_width)>>1; 1801 framingCtx->FramingYuv[2].pac_data = framingCtx->FramingYuv[1].pac_data \ 1802 + framingCtx->FramingYuv[1].u_width * framingCtx->FramingYuv[1].u_height; 1803 1804 /** 1805 * Convert input RGB 565 to YUV 420 to be able to merge it with output video in framing 1806 effect */ 1807 err = M4VIFI_xVSS_RGB565toYUV420(M4OSA_NULL, framingCtx->FramingRgb, framingCtx->FramingYuv); 1808 if(err != M4NO_ERROR) 1809 { 1810 M4OSA_TRACE1_1("M4xVSS_internalConvertRGBtoYUV:\ 1811 error when converting from RGB to YUV: 0x%x\n", err); 1812 } 1813 1814 framingCtx->duration = 0; 1815 framingCtx->previousClipTime = -1; 1816 framingCtx->previewOffsetClipTime = -1; 1817 1818 /** 1819 * Only one element in the chained list (no animated image with RGB buffer...) */ 1820 framingCtx->pCurrent = framingCtx; 1821 framingCtx->pNext = framingCtx; 1822 1823 return M4NO_ERROR; 1824 } 1825 1826 M4OSA_ERR M4xVSS_internalSetPlaneTransparent(M4OSA_UInt8* planeIn, M4OSA_UInt32 size) 1827 { 1828 M4OSA_UInt32 i; 1829 M4OSA_UInt8* plane = planeIn; 1830 M4OSA_UInt8 transparent1 = (M4OSA_UInt8)((TRANSPARENT_COLOR & 0xFF00)>>8); 1831 M4OSA_UInt8 transparent2 = (M4OSA_UInt8)TRANSPARENT_COLOR; 1832 1833 for(i=0; i<(size>>1); i++) 1834 { 1835 *plane++ = transparent1; 1836 *plane++ = transparent2; 1837 } 1838 1839 return M4NO_ERROR; 1840 } 1841 1842 1843 /** 1844 ****************************************************************************** 1845 * prototype M4OSA_ERR M4xVSS_internalConvertARBG888toYUV420_FrammingEffect(M4OSA_Context pContext, 1846 * M4VSS3GPP_EffectSettings* pEffect, 1847 * M4xVSS_FramingStruct* framingCtx, 1848 M4VIDEOEDITING_VideoFrameSize OutputVideoResolution) 1849 * 1850 * @brief This function converts ARGB8888 input file to YUV420 whenused for framming effect 1851 * @note The input ARGB8888 file path is contained in the pEffect structure 1852 * If the ARGB8888 must be resized to fit output video size, this function 1853 * will do it. 1854 * @param pContext (IN) The integrator own context 1855 * @param pEffect (IN) The effect structure containing all informations on 1856 * the file to decode, resizing ... 1857 * @param framingCtx (IN/OUT) Structure in which the output RGB will be stored 1858 * 1859 * @return M4NO_ERROR: No error 1860 * @return M4ERR_PARAMETER: At least one of the function parameters is null 1861 * @return M4ERR_ALLOC: Allocation error (no more memory) 1862 * @return M4ERR_FILE_NOT_FOUND: File not found. 1863 ****************************************************************************** 1864 */ 1865 1866 1867 M4OSA_ERR M4xVSS_internalConvertARGB888toYUV420_FrammingEffect(M4OSA_Context pContext, 1868 M4VSS3GPP_EffectSettings* pEffect, 1869 M4xVSS_FramingStruct* framingCtx, 1870 M4VIDEOEDITING_VideoFrameSize\ 1871 OutputVideoResolution) 1872 { 1873 M4OSA_ERR err = M4NO_ERROR; 1874 M4OSA_Context pARGBIn; 1875 M4OSA_UInt32 file_size; 1876 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 1877 M4OSA_UInt32 width, height, width_out, height_out; 1878 M4OSA_Void* pFile = pEffect->xVSS.pFramingFilePath; 1879 M4OSA_UInt8 transparent1 = (M4OSA_UInt8)((TRANSPARENT_COLOR & 0xFF00)>>8); 1880 M4OSA_UInt8 transparent2 = (M4OSA_UInt8)TRANSPARENT_COLOR; 1881 /*UTF conversion support*/ 1882 M4OSA_Char* pDecodedPath = M4OSA_NULL; 1883 M4OSA_UInt32 i = 0,j = 0; 1884 M4VIFI_ImagePlane rgbPlane; 1885 M4OSA_UInt32 frameSize_argb=(framingCtx->width * framingCtx->height * 4); 1886 M4OSA_UInt32 frameSize; 1887 M4OSA_UInt32 tempAlphaPercent = 0; 1888 M4VIFI_UInt8* TempPacData = M4OSA_NULL; 1889 M4OSA_UInt16 *ptr = M4OSA_NULL; 1890 M4OSA_UInt32 z = 0; 1891 1892 M4OSA_TRACE3_0("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect: Entering "); 1893 1894 M4OSA_TRACE1_2("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect width and height %d %d ", 1895 framingCtx->width,framingCtx->height); 1896 1897 M4OSA_UInt8 *pTmpData = (M4OSA_UInt8*) M4OSA_32bitAlignedMalloc(frameSize_argb, M4VS, (M4OSA_Char*)\ 1898 "Image argb data"); 1899 if(pTmpData == M4OSA_NULL) { 1900 M4OSA_TRACE1_0("Failed to allocate memory for Image clip"); 1901 return M4ERR_ALLOC; 1902 } 1903 /** 1904 * UTF conversion: convert the file path into the customer format*/ 1905 pDecodedPath = pFile; 1906 1907 if(xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL 1908 && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL) 1909 { 1910 M4OSA_UInt32 length = 0; 1911 err = M4xVSS_internalConvertFromUTF8(xVSS_context, (M4OSA_Void*) pFile, 1912 (M4OSA_Void*) xVSS_context->UTFConversionContext.pTempOutConversionBuffer, &length); 1913 if(err != M4NO_ERROR) 1914 { 1915 M4OSA_TRACE1_1("M4xVSS_internalDecodePNG:\ 1916 M4xVSS_internalConvertFromUTF8 returns err: 0x%x",err); 1917 free(pTmpData); 1918 pTmpData = M4OSA_NULL; 1919 return err; 1920 } 1921 pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; 1922 } 1923 1924 /** 1925 * End of the conversion, now use the decoded path*/ 1926 1927 /* Open input ARGB8888 file and store it into memory */ 1928 err = xVSS_context->pFileReadPtr->openRead(&pARGBIn, pDecodedPath, M4OSA_kFileRead); 1929 1930 if(err != M4NO_ERROR) 1931 { 1932 M4OSA_TRACE1_2("Can't open input ARGB8888 file %s, error: 0x%x\n",pFile, err); 1933 free(pTmpData); 1934 pTmpData = M4OSA_NULL; 1935 return err; 1936 } 1937 1938 err = xVSS_context->pFileReadPtr->readData(pARGBIn,(M4OSA_MemAddr8)pTmpData, &frameSize_argb); 1939 if(err != M4NO_ERROR) 1940 { 1941 xVSS_context->pFileReadPtr->closeRead(pARGBIn); 1942 free(pTmpData); 1943 pTmpData = M4OSA_NULL; 1944 return err; 1945 } 1946 1947 1948 err = xVSS_context->pFileReadPtr->closeRead(pARGBIn); 1949 if(err != M4NO_ERROR) 1950 { 1951 M4OSA_TRACE1_2("Can't close input png file %s, error: 0x%x\n",pFile, err); 1952 free(pTmpData); 1953 pTmpData = M4OSA_NULL; 1954 return err; 1955 } 1956 1957 1958 rgbPlane.u_height = framingCtx->height; 1959 rgbPlane.u_width = framingCtx->width; 1960 rgbPlane.u_stride = rgbPlane.u_width*3; 1961 rgbPlane.u_topleft = 0; 1962 1963 frameSize = (rgbPlane.u_width * rgbPlane.u_height * 3); //Size of RGB888 data 1964 rgbPlane.pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(((frameSize)+ (2 * framingCtx->width)), 1965 M4VS, (M4OSA_Char*)"Image clip RGB888 data"); 1966 if(rgbPlane.pac_data == M4OSA_NULL) 1967 { 1968 M4OSA_TRACE1_0("Failed to allocate memory for Image clip"); 1969 free(pTmpData); 1970 return M4ERR_ALLOC; 1971 } 1972 1973 M4OSA_TRACE1_0("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect:\ 1974 Remove the alpha channel "); 1975 1976 /* premultiplied alpha % on RGB */ 1977 for (i=0, j = 0; i < frameSize_argb; i += 4) { 1978 /* this is alpha value */ 1979 if ((i % 4) == 0) 1980 { 1981 tempAlphaPercent = pTmpData[i]; 1982 } 1983 1984 /* R */ 1985 rgbPlane.pac_data[j] = pTmpData[i+1]; 1986 j++; 1987 1988 /* G */ 1989 if (tempAlphaPercent > 0) { 1990 rgbPlane.pac_data[j] = pTmpData[i+2]; 1991 j++; 1992 } else {/* In case of alpha value 0, make GREEN to 255 */ 1993 rgbPlane.pac_data[j] = 255; //pTmpData[i+2]; 1994 j++; 1995 } 1996 1997 /* B */ 1998 rgbPlane.pac_data[j] = pTmpData[i+3]; 1999 j++; 2000 } 2001 2002 free(pTmpData); 2003 pTmpData = M4OSA_NULL; 2004 2005 /* convert RGB888 to RGB565 */ 2006 2007 /* allocate temp RGB 565 buffer */ 2008 TempPacData = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(frameSize + 2009 (4 * (framingCtx->width + framingCtx->height + 1)), 2010 M4VS, (M4OSA_Char*)"Image clip RGB565 data"); 2011 if (TempPacData == M4OSA_NULL) { 2012 M4OSA_TRACE1_0("Failed to allocate memory for Image clip RGB565 data"); 2013 free(rgbPlane.pac_data); 2014 return M4ERR_ALLOC; 2015 } 2016 2017 ptr = (M4OSA_UInt16 *)TempPacData; 2018 z = 0; 2019 2020 for (i = 0; i < j ; i += 3) 2021 { 2022 ptr[z++] = PACK_RGB565(0, rgbPlane.pac_data[i], 2023 rgbPlane.pac_data[i+1], 2024 rgbPlane.pac_data[i+2]); 2025 } 2026 2027 /* free the RBG888 and assign RGB565 */ 2028 free(rgbPlane.pac_data); 2029 rgbPlane.pac_data = TempPacData; 2030 2031 /** 2032 * Check if output sizes are odd */ 2033 if(rgbPlane.u_height % 2 != 0) 2034 { 2035 M4VIFI_UInt8* output_pac_data = rgbPlane.pac_data; 2036 M4OSA_UInt32 i; 2037 M4OSA_TRACE1_0("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect:\ 2038 output height is odd "); 2039 output_pac_data +=rgbPlane.u_width * rgbPlane.u_height*2; 2040 2041 for(i=0;i<rgbPlane.u_width;i++) 2042 { 2043 *output_pac_data++ = transparent1; 2044 *output_pac_data++ = transparent2; 2045 } 2046 2047 /** 2048 * We just add a white line to the PNG that will be transparent */ 2049 rgbPlane.u_height++; 2050 } 2051 if(rgbPlane.u_width % 2 != 0) 2052 { 2053 /** 2054 * We add a new column of white (=transparent), but we need to parse all RGB lines ... */ 2055 M4OSA_UInt32 i; 2056 M4VIFI_UInt8* newRGBpac_data; 2057 M4VIFI_UInt8* output_pac_data, *input_pac_data; 2058 2059 rgbPlane.u_width++; 2060 M4OSA_TRACE1_0("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect: \ 2061 output width is odd "); 2062 /** 2063 * We need to allocate a new RGB output buffer in which all decoded data 2064 + white line will be copied */ 2065 newRGBpac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(rgbPlane.u_height*rgbPlane.u_width*2\ 2066 *sizeof(M4VIFI_UInt8), M4VS, (M4OSA_Char *)"New Framing GIF Output pac_data RGB"); 2067 2068 if(newRGBpac_data == M4OSA_NULL) 2069 { 2070 M4OSA_TRACE1_0("Allocation error in \ 2071 M4xVSS_internalConvertARGB888toYUV420_FrammingEffect"); 2072 free(rgbPlane.pac_data); 2073 return M4ERR_ALLOC; 2074 } 2075 2076 output_pac_data= newRGBpac_data; 2077 input_pac_data = rgbPlane.pac_data; 2078 2079 for(i=0;i<rgbPlane.u_height;i++) 2080 { 2081 memcpy((void *)output_pac_data, (void *)input_pac_data, 2082 (rgbPlane.u_width-1)*2); 2083 2084 output_pac_data += ((rgbPlane.u_width-1)*2); 2085 /* Put the pixel to transparency color */ 2086 *output_pac_data++ = transparent1; 2087 *output_pac_data++ = transparent2; 2088 2089 input_pac_data += ((rgbPlane.u_width-1)*2); 2090 } 2091 free(rgbPlane.pac_data); 2092 rgbPlane.pac_data = newRGBpac_data; 2093 } 2094 2095 /* reset stride */ 2096 rgbPlane.u_stride = rgbPlane.u_width*2; 2097 2098 /** 2099 * Initialize chained list parameters */ 2100 framingCtx->duration = 0; 2101 framingCtx->previousClipTime = -1; 2102 framingCtx->previewOffsetClipTime = -1; 2103 2104 /** 2105 * Only one element in the chained list (no animated image ...) */ 2106 framingCtx->pCurrent = framingCtx; 2107 framingCtx->pNext = framingCtx; 2108 2109 /** 2110 * Get output width/height */ 2111 switch(OutputVideoResolution) 2112 //switch(xVSS_context->pSettings->xVSS.outputVideoSize) 2113 { 2114 case M4VIDEOEDITING_kSQCIF: 2115 width_out = 128; 2116 height_out = 96; 2117 break; 2118 case M4VIDEOEDITING_kQQVGA: 2119 width_out = 160; 2120 height_out = 120; 2121 break; 2122 case M4VIDEOEDITING_kQCIF: 2123 width_out = 176; 2124 height_out = 144; 2125 break; 2126 case M4VIDEOEDITING_kQVGA: 2127 width_out = 320; 2128 height_out = 240; 2129 break; 2130 case M4VIDEOEDITING_kCIF: 2131 width_out = 352; 2132 height_out = 288; 2133 break; 2134 case M4VIDEOEDITING_kVGA: 2135 width_out = 640; 2136 height_out = 480; 2137 break; 2138 case M4VIDEOEDITING_kWVGA: 2139 width_out = 800; 2140 height_out = 480; 2141 break; 2142 case M4VIDEOEDITING_kNTSC: 2143 width_out = 720; 2144 height_out = 480; 2145 break; 2146 case M4VIDEOEDITING_k640_360: 2147 width_out = 640; 2148 height_out = 360; 2149 break; 2150 case M4VIDEOEDITING_k854_480: 2151 // StageFright encoders require %16 resolution 2152 width_out = M4ENCODER_854_480_Width; 2153 height_out = 480; 2154 break; 2155 case M4VIDEOEDITING_k1280_720: 2156 width_out = 1280; 2157 height_out = 720; 2158 break; 2159 case M4VIDEOEDITING_k1080_720: 2160 // StageFright encoders require %16 resolution 2161 width_out = M4ENCODER_1080_720_Width; 2162 height_out = 720; 2163 break; 2164 case M4VIDEOEDITING_k960_720: 2165 width_out = 960; 2166 height_out = 720; 2167 break; 2168 case M4VIDEOEDITING_k1920_1080: 2169 width_out = 1920; 2170 height_out = M4ENCODER_1920_1080_Height; 2171 break; 2172 /** 2173 * If output video size is not given, we take QCIF size, 2174 * should not happen, because already done in M4xVSS_sendCommand */ 2175 default: 2176 width_out = 176; 2177 height_out = 144; 2178 break; 2179 } 2180 2181 /** 2182 * Allocate output planes structures */ 2183 framingCtx->FramingRgb = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(sizeof(M4VIFI_ImagePlane), M4VS, 2184 (M4OSA_Char *)"Framing Output plane RGB"); 2185 if(framingCtx->FramingRgb == M4OSA_NULL) 2186 { 2187 M4OSA_TRACE1_0("Allocation error in M4xVSS_internalConvertARGB888toYUV420_FrammingEffect"); 2188 return M4ERR_ALLOC; 2189 } 2190 /** 2191 * Resize RGB if needed */ 2192 if((pEffect->xVSS.bResize) && 2193 (rgbPlane.u_width != width_out || rgbPlane.u_height != height_out)) 2194 { 2195 width = width_out; 2196 height = height_out; 2197 2198 M4OSA_TRACE1_2("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect: \ 2199 New Width and height %d %d ",width,height); 2200 2201 framingCtx->FramingRgb->u_height = height_out; 2202 framingCtx->FramingRgb->u_width = width_out; 2203 framingCtx->FramingRgb->u_stride = framingCtx->FramingRgb->u_width*2; 2204 framingCtx->FramingRgb->u_topleft = 0; 2205 2206 framingCtx->FramingRgb->pac_data = 2207 (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(framingCtx->FramingRgb->u_height*framingCtx->\ 2208 FramingRgb->u_width*2*sizeof(M4VIFI_UInt8), M4VS, 2209 (M4OSA_Char *)"Framing Output pac_data RGB"); 2210 2211 if(framingCtx->FramingRgb->pac_data == M4OSA_NULL) 2212 { 2213 M4OSA_TRACE1_0("Allocation error in \ 2214 M4xVSS_internalConvertARGB888toYUV420_FrammingEffect"); 2215 free(framingCtx->FramingRgb); 2216 free(rgbPlane.pac_data); 2217 return M4ERR_ALLOC; 2218 } 2219 2220 M4OSA_TRACE1_0("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect: Resizing Needed "); 2221 M4OSA_TRACE1_2("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect:\ 2222 rgbPlane.u_height & rgbPlane.u_width %d %d",rgbPlane.u_height,rgbPlane.u_width); 2223 2224 //err = M4VIFI_ResizeBilinearRGB888toRGB888(M4OSA_NULL, &rgbPlane,framingCtx->FramingRgb); 2225 err = M4VIFI_ResizeBilinearRGB565toRGB565(M4OSA_NULL, &rgbPlane,framingCtx->FramingRgb); 2226 2227 if(err != M4NO_ERROR) 2228 { 2229 M4OSA_TRACE1_1("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect :\ 2230 when resizing RGB plane: 0x%x\n", err); 2231 return err; 2232 } 2233 2234 if(rgbPlane.pac_data != M4OSA_NULL) 2235 { 2236 free(rgbPlane.pac_data); 2237 rgbPlane.pac_data = M4OSA_NULL; 2238 } 2239 } 2240 else 2241 { 2242 2243 M4OSA_TRACE1_0("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect:\ 2244 Resizing Not Needed "); 2245 2246 width = rgbPlane.u_width; 2247 height = rgbPlane.u_height; 2248 framingCtx->FramingRgb->u_height = height; 2249 framingCtx->FramingRgb->u_width = width; 2250 framingCtx->FramingRgb->u_stride = framingCtx->FramingRgb->u_width*2; 2251 framingCtx->FramingRgb->u_topleft = 0; 2252 framingCtx->FramingRgb->pac_data = rgbPlane.pac_data; 2253 } 2254 2255 2256 if(pEffect->xVSS.bResize) 2257 { 2258 /** 2259 * Force topleft to 0 for pure framing effect */ 2260 framingCtx->topleft_x = 0; 2261 framingCtx->topleft_y = 0; 2262 } 2263 2264 2265 /** 2266 * Convert RGB output to YUV 420 to be able to merge it with output video in framing 2267 effect */ 2268 framingCtx->FramingYuv = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(3*sizeof(M4VIFI_ImagePlane), M4VS, 2269 (M4OSA_Char *)"Framing Output plane YUV"); 2270 if(framingCtx->FramingYuv == M4OSA_NULL) 2271 { 2272 M4OSA_TRACE1_0("Allocation error in M4xVSS_internalConvertARGB888toYUV420_FrammingEffect"); 2273 free(framingCtx->FramingRgb->pac_data); 2274 return M4ERR_ALLOC; 2275 } 2276 2277 // Alloc for Y, U and V planes 2278 framingCtx->FramingYuv[0].u_width = ((width+1)>>1)<<1; 2279 framingCtx->FramingYuv[0].u_height = ((height+1)>>1)<<1; 2280 framingCtx->FramingYuv[0].u_topleft = 0; 2281 framingCtx->FramingYuv[0].u_stride = ((width+1)>>1)<<1; 2282 framingCtx->FramingYuv[0].pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc 2283 ((framingCtx->FramingYuv[0].u_width*framingCtx->FramingYuv[0].u_height), M4VS, 2284 (M4OSA_Char *)"Alloc for the output Y"); 2285 if(framingCtx->FramingYuv[0].pac_data == M4OSA_NULL) 2286 { 2287 M4OSA_TRACE1_0("Allocation error in M4xVSS_internalConvertARGB888toYUV420_FrammingEffect"); 2288 free(framingCtx->FramingYuv); 2289 free(framingCtx->FramingRgb->pac_data); 2290 return M4ERR_ALLOC; 2291 } 2292 framingCtx->FramingYuv[1].u_width = (((width+1)>>1)<<1)>>1; 2293 framingCtx->FramingYuv[1].u_height = (((height+1)>>1)<<1)>>1; 2294 framingCtx->FramingYuv[1].u_topleft = 0; 2295 framingCtx->FramingYuv[1].u_stride = (((width+1)>>1)<<1)>>1; 2296 2297 2298 framingCtx->FramingYuv[1].pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc( 2299 framingCtx->FramingYuv[1].u_width * framingCtx->FramingYuv[1].u_height, M4VS, 2300 (M4OSA_Char *)"Alloc for the output U"); 2301 if (framingCtx->FramingYuv[1].pac_data == M4OSA_NULL) { 2302 free(framingCtx->FramingYuv[0].pac_data); 2303 free(framingCtx->FramingYuv); 2304 free(framingCtx->FramingRgb->pac_data); 2305 return M4ERR_ALLOC; 2306 } 2307 2308 framingCtx->FramingYuv[2].u_width = (((width+1)>>1)<<1)>>1; 2309 framingCtx->FramingYuv[2].u_height = (((height+1)>>1)<<1)>>1; 2310 framingCtx->FramingYuv[2].u_topleft = 0; 2311 framingCtx->FramingYuv[2].u_stride = (((width+1)>>1)<<1)>>1; 2312 2313 2314 framingCtx->FramingYuv[2].pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc( 2315 framingCtx->FramingYuv[2].u_width * framingCtx->FramingYuv[0].u_height, M4VS, 2316 (M4OSA_Char *)"Alloc for the output V"); 2317 if (framingCtx->FramingYuv[2].pac_data == M4OSA_NULL) { 2318 free(framingCtx->FramingYuv[1].pac_data); 2319 free(framingCtx->FramingYuv[0].pac_data); 2320 free(framingCtx->FramingYuv); 2321 free(framingCtx->FramingRgb->pac_data); 2322 return M4ERR_ALLOC; 2323 } 2324 2325 M4OSA_TRACE3_0("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect:\ 2326 convert RGB to YUV "); 2327 2328 //err = M4VIFI_RGB888toYUV420(M4OSA_NULL, framingCtx->FramingRgb, framingCtx->FramingYuv); 2329 err = M4VIFI_RGB565toYUV420(M4OSA_NULL, framingCtx->FramingRgb, framingCtx->FramingYuv); 2330 2331 if (err != M4NO_ERROR) 2332 { 2333 M4OSA_TRACE1_1("SPS png: error when converting from RGB to YUV: 0x%x\n", err); 2334 } 2335 M4OSA_TRACE3_0("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect: Leaving "); 2336 return err; 2337 } 2338 2339 /** 2340 ****************************************************************************** 2341 * prototype M4OSA_ERR M4xVSS_internalGenerateEditedFile(M4OSA_Context pContext) 2342 * 2343 * @brief This function prepares VSS for editing 2344 * @note It also set special xVSS effect as external effects for the VSS 2345 * @param pContext (IN) The integrator own context 2346 * 2347 * @return M4NO_ERROR: No error 2348 * @return M4ERR_PARAMETER: At least one of the function parameters is null 2349 * @return M4ERR_ALLOC: Allocation error (no more memory) 2350 ****************************************************************************** 2351 */ 2352 M4OSA_ERR M4xVSS_internalGenerateEditedFile(M4OSA_Context pContext) 2353 { 2354 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 2355 M4VSS3GPP_EditContext pVssCtxt; 2356 M4OSA_UInt32 i,j; 2357 M4OSA_ERR err; 2358 2359 /** 2360 * Create a VSS 3GPP edition instance */ 2361 err = M4VSS3GPP_editInit( &pVssCtxt, xVSS_context->pFileReadPtr, xVSS_context->pFileWritePtr); 2362 if (err != M4NO_ERROR) 2363 { 2364 M4OSA_TRACE1_1("M4xVSS_internalGenerateEditedFile: M4VSS3GPP_editInit returned 0x%x\n", 2365 err); 2366 M4VSS3GPP_editCleanUp(pVssCtxt); 2367 /** 2368 * Set the VSS context to NULL */ 2369 xVSS_context->pCurrentEditContext = M4OSA_NULL; 2370 return err; 2371 } 2372 2373 M4VSS3GPP_InternalEditContext* pVSSContext = 2374 (M4VSS3GPP_InternalEditContext*)pVssCtxt; 2375 pVSSContext->xVSS.outputVideoFormat = 2376 xVSS_context->pSettings->xVSS.outputVideoFormat; 2377 pVSSContext->xVSS.outputVideoSize = 2378 xVSS_context->pSettings->xVSS.outputVideoSize ; 2379 pVSSContext->xVSS.outputAudioFormat = 2380 xVSS_context->pSettings->xVSS.outputAudioFormat; 2381 pVSSContext->xVSS.outputAudioSamplFreq = 2382 xVSS_context->pSettings->xVSS.outputAudioSamplFreq; 2383 pVSSContext->xVSS.outputVideoBitrate = 2384 xVSS_context->pSettings->xVSS.outputVideoBitrate ; 2385 pVSSContext->xVSS.outputAudioBitrate = 2386 xVSS_context->pSettings->xVSS.outputAudioBitrate ; 2387 pVSSContext->xVSS.bAudioMono = 2388 xVSS_context->pSettings->xVSS.bAudioMono; 2389 pVSSContext->xVSS.outputVideoProfile = 2390 xVSS_context->pSettings->xVSS.outputVideoProfile; 2391 pVSSContext->xVSS.outputVideoLevel = 2392 xVSS_context->pSettings->xVSS.outputVideoLevel; 2393 /* In case of MMS use case, we fill directly into the VSS context the targeted bitrate */ 2394 if(xVSS_context->targetedBitrate != 0) 2395 { 2396 M4VSS3GPP_InternalEditContext* pVSSContext = (M4VSS3GPP_InternalEditContext*)pVssCtxt; 2397 2398 pVSSContext->bIsMMS = M4OSA_TRUE; 2399 pVSSContext->uiMMSVideoBitrate = xVSS_context->targetedBitrate; 2400 pVSSContext->MMSvideoFramerate = xVSS_context->pSettings->videoFrameRate; 2401 } 2402 2403 /*Warning: since the adding of the UTF conversion, pSettings has been changed in the next 2404 part in pCurrentEditSettings (there is a specific current editing structure for the saving, 2405 as for the preview)*/ 2406 2407 /** 2408 * Set the external video effect functions, for saving mode (to be moved to 2409 M4xVSS_saveStart() ?)*/ 2410 for (i=0; i<xVSS_context->pCurrentEditSettings->uiClipNumber; i++) 2411 { 2412 for (j=0; j<xVSS_context->pCurrentEditSettings->nbEffects; j++) 2413 { 2414 if (M4xVSS_kVideoEffectType_BlackAndWhite == 2415 xVSS_context->pCurrentEditSettings->Effects[j].VideoEffectType) 2416 { 2417 xVSS_context->pCurrentEditSettings->Effects[j].ExtVideoEffectFct = 2418 M4VSS3GPP_externalVideoEffectColor; 2419 //xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = 2420 // (M4OSA_Void*)M4xVSS_kVideoEffectType_BlackAndWhite; 2421 /*commented FB*/ 2422 /** 2423 * We do not need to set the color context, it is already set 2424 during sendCommand function */ 2425 } 2426 if (M4xVSS_kVideoEffectType_Pink == 2427 xVSS_context->pCurrentEditSettings->Effects[j].VideoEffectType) 2428 { 2429 xVSS_context->pCurrentEditSettings->Effects[j].ExtVideoEffectFct = 2430 M4VSS3GPP_externalVideoEffectColor; 2431 //xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = 2432 // (M4OSA_Void*)M4xVSS_kVideoEffectType_Pink; /**< we don't 2433 // use any function context */ 2434 /*commented FB*/ 2435 /** 2436 * We do not need to set the color context, 2437 it is already set during sendCommand function */ 2438 } 2439 if (M4xVSS_kVideoEffectType_Green == 2440 xVSS_context->pCurrentEditSettings->Effects[j].VideoEffectType) 2441 { 2442 xVSS_context->pCurrentEditSettings->Effects[j].ExtVideoEffectFct = 2443 M4VSS3GPP_externalVideoEffectColor; 2444 //xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = 2445 // (M4OSA_Void*)M4xVSS_kVideoEffectType_Green; 2446 /**< we don't use any function context */ 2447 /*commented FB*/ 2448 /** 2449 * We do not need to set the color context, it is already set during 2450 sendCommand function */ 2451 } 2452 if (M4xVSS_kVideoEffectType_Sepia == 2453 xVSS_context->pCurrentEditSettings->Effects[j].VideoEffectType) 2454 { 2455 xVSS_context->pCurrentEditSettings->Effects[j].ExtVideoEffectFct = 2456 M4VSS3GPP_externalVideoEffectColor; 2457 //xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = 2458 // (M4OSA_Void*)M4xVSS_kVideoEffectType_Sepia; 2459 /**< we don't use any function context */ 2460 /*commented FB*/ 2461 /** 2462 * We do not need to set the color context, it is already set during 2463 sendCommand function */ 2464 } 2465 if (M4xVSS_kVideoEffectType_Fifties == 2466 xVSS_context->pCurrentEditSettings->Effects[j].VideoEffectType) 2467 { 2468 xVSS_context->pCurrentEditSettings->Effects[j].ExtVideoEffectFct = 2469 M4VSS3GPP_externalVideoEffectFifties; 2470 /** 2471 * We do not need to set the framing context, it is already set during 2472 sendCommand function */ 2473 } 2474 if (M4xVSS_kVideoEffectType_Negative == 2475 xVSS_context->pCurrentEditSettings->Effects[j].VideoEffectType) 2476 { 2477 xVSS_context->pCurrentEditSettings->Effects[j].ExtVideoEffectFct = 2478 M4VSS3GPP_externalVideoEffectColor; 2479 //xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = 2480 // (M4OSA_Void*)M4xVSS_kVideoEffectType_Negative; 2481 /**< we don't use any function context */ 2482 /*commented FB*/ 2483 /** 2484 * We do not need to set the color context, it is already set during 2485 sendCommand function */ 2486 } 2487 if (M4xVSS_kVideoEffectType_Framing == 2488 xVSS_context->pCurrentEditSettings->Effects[j].VideoEffectType) 2489 { 2490 xVSS_context->pCurrentEditSettings->Effects[j].ExtVideoEffectFct = 2491 M4VSS3GPP_externalVideoEffectFraming; 2492 /** 2493 * We do not need to set the framing context, it is already set during 2494 sendCommand function */ 2495 } 2496 if (M4xVSS_kVideoEffectType_ZoomIn == 2497 xVSS_context->pSettings->Effects[j].VideoEffectType) 2498 { 2499 xVSS_context->pCurrentEditSettings->Effects[j].ExtVideoEffectFct = 2500 M4VSS3GPP_externalVideoEffectZoom; 2501 xVSS_context->pCurrentEditSettings->Effects[j].pExtVideoEffectFctCtxt = 2502 (M4OSA_Void*)M4xVSS_kVideoEffectType_ZoomIn; /**< we don't use any 2503 function context */ 2504 } 2505 if (M4xVSS_kVideoEffectType_ZoomOut == 2506 xVSS_context->pCurrentEditSettings->Effects[j].VideoEffectType) 2507 { 2508 xVSS_context->pCurrentEditSettings->Effects[j].ExtVideoEffectFct = 2509 M4VSS3GPP_externalVideoEffectZoom; 2510 xVSS_context->pCurrentEditSettings->Effects[j].pExtVideoEffectFctCtxt = 2511 (M4OSA_Void*)M4xVSS_kVideoEffectType_ZoomOut; /**< we don't use any 2512 function context */ 2513 } 2514 if (M4xVSS_kVideoEffectType_ColorRGB16 == 2515 xVSS_context->pCurrentEditSettings->Effects[j].VideoEffectType) 2516 { 2517 xVSS_context->pCurrentEditSettings->Effects[j].ExtVideoEffectFct = 2518 M4VSS3GPP_externalVideoEffectColor; 2519 //xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = 2520 // (M4OSA_Void*)M4xVSS_kVideoEffectType_ColorRGB16; 2521 /**< we don't use any function context */ 2522 /** 2523 * We do not need to set the color context, it is already set during 2524 sendCommand function */ 2525 } 2526 if (M4xVSS_kVideoEffectType_Gradient == 2527 xVSS_context->pCurrentEditSettings->Effects[j].VideoEffectType) 2528 { 2529 xVSS_context->pCurrentEditSettings->Effects[j].ExtVideoEffectFct = 2530 M4VSS3GPP_externalVideoEffectColor; 2531 //xVSS_context->pSettings->Effects[j].pExtVideoEffectFctCtxt = 2532 // (M4OSA_Void*)M4xVSS_kVideoEffectType_ColorRGB16; 2533 /**< we don't use any function context */ 2534 /** 2535 * We do not need to set the color context, it is already set during 2536 sendCommand function */ 2537 } 2538 2539 } 2540 } 2541 2542 /** 2543 * Open the VSS 3GPP */ 2544 err = M4VSS3GPP_editOpen(pVssCtxt, xVSS_context->pCurrentEditSettings); 2545 if (err != M4NO_ERROR) 2546 { 2547 M4OSA_TRACE1_1("M4xVSS_internalGenerateEditedFile:\ 2548 M4VSS3GPP_editOpen returned 0x%x\n",err); 2549 M4VSS3GPP_editCleanUp(pVssCtxt); 2550 /** 2551 * Set the VSS context to NULL */ 2552 xVSS_context->pCurrentEditContext = M4OSA_NULL; 2553 return err; 2554 } 2555 2556 /** 2557 * Save VSS context to be able to close / free VSS later */ 2558 xVSS_context->pCurrentEditContext = pVssCtxt; 2559 2560 return M4NO_ERROR; 2561 } 2562 2563 /** 2564 ****************************************************************************** 2565 * prototype M4OSA_ERR M4xVSS_internalCloseEditedFile(M4OSA_Context pContext) 2566 * 2567 * @brief This function cleans up VSS 2568 * @note 2569 * @param pContext (IN) The integrator own context 2570 * 2571 * @return M4NO_ERROR: No error 2572 * @return M4ERR_PARAMETER: At least one of the function parameters is null 2573 ****************************************************************************** 2574 */ 2575 M4OSA_ERR M4xVSS_internalCloseEditedFile(M4OSA_Context pContext) 2576 { 2577 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 2578 M4VSS3GPP_EditContext pVssCtxt = xVSS_context->pCurrentEditContext; 2579 M4OSA_ERR err; 2580 2581 if(xVSS_context->pCurrentEditContext != M4OSA_NULL) 2582 { 2583 /** 2584 * Close the VSS 3GPP */ 2585 err = M4VSS3GPP_editClose(pVssCtxt); 2586 if (err != M4NO_ERROR) 2587 { 2588 M4OSA_TRACE1_1("M4xVSS_internalCloseEditedFile:\ 2589 M4VSS3GPP_editClose returned 0x%x\n",err); 2590 M4VSS3GPP_editCleanUp(pVssCtxt); 2591 /** 2592 * Set the VSS context to NULL */ 2593 xVSS_context->pCurrentEditContext = M4OSA_NULL; 2594 return err; 2595 } 2596 2597 /** 2598 * Free this VSS3GPP edition instance */ 2599 err = M4VSS3GPP_editCleanUp(pVssCtxt); 2600 /** 2601 * Set the VSS context to NULL */ 2602 xVSS_context->pCurrentEditContext = M4OSA_NULL; 2603 if (err != M4NO_ERROR) 2604 { 2605 M4OSA_TRACE1_1("M4xVSS_internalCloseEditedFile: \ 2606 M4VSS3GPP_editCleanUp returned 0x%x\n",err); 2607 return err; 2608 } 2609 } 2610 2611 return M4NO_ERROR; 2612 } 2613 2614 /** 2615 ****************************************************************************** 2616 * prototype M4OSA_ERR M4xVSS_internalGenerateAudioMixFile(M4OSA_Context pContext) 2617 * 2618 * @brief This function prepares VSS for audio mixing 2619 * @note It takes its parameters from the BGM settings in the xVSS internal context 2620 * @param pContext (IN) The integrator own context 2621 * 2622 * @return M4NO_ERROR: No error 2623 * @return M4ERR_PARAMETER: At least one of the function parameters is null 2624 * @return M4ERR_ALLOC: Allocation error (no more memory) 2625 ****************************************************************************** 2626 */ 2627 /*** 2628 * FB: the function has been modified since the structure used for the saving is now the 2629 * pCurrentEditSettings and not the pSettings 2630 * This change has been added for the UTF support 2631 * All the "xVSS_context->pSettings" has been replaced by "xVSS_context->pCurrentEditSettings" 2632 ***/ 2633 M4OSA_ERR M4xVSS_internalGenerateAudioMixFile(M4OSA_Context pContext) 2634 { 2635 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 2636 M4VSS3GPP_AudioMixingSettings* pAudioMixSettings; 2637 M4VSS3GPP_AudioMixingContext pAudioMixingCtxt; 2638 M4OSA_ERR err; 2639 M4VIDEOEDITING_ClipProperties fileProperties; 2640 2641 /** 2642 * Allocate audio mixing settings structure and fill it with BGM parameters */ 2643 pAudioMixSettings = (M4VSS3GPP_AudioMixingSettings*)M4OSA_32bitAlignedMalloc 2644 (sizeof(M4VSS3GPP_AudioMixingSettings), M4VS, (M4OSA_Char *)"pAudioMixSettings"); 2645 if(pAudioMixSettings == M4OSA_NULL) 2646 { 2647 M4OSA_TRACE1_0("Allocation error in M4xVSS_internalGenerateAudioMixFile"); 2648 return M4ERR_ALLOC; 2649 } 2650 2651 if(xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->FileType == 2652 M4VIDEOEDITING_kFileType_3GPP) 2653 { 2654 err = M4xVSS_internalGetProperties((M4OSA_Context)xVSS_context, 2655 (M4OSA_Char*)xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->pFile, 2656 &fileProperties); 2657 if(err != M4NO_ERROR) 2658 { 2659 M4OSA_TRACE1_1("M4xVSS_internalGenerateAudioMixFile:\ 2660 impossible to retrieve audio BGM properties ->\ 2661 reencoding audio background music", err); 2662 fileProperties.AudioStreamType = 2663 xVSS_context->pCurrentEditSettings->xVSS.outputAudioFormat+1; 2664 /* To force BGM encoding */ 2665 } 2666 } 2667 2668 pAudioMixSettings->bRemoveOriginal = M4OSA_FALSE; 2669 pAudioMixSettings->AddedAudioFileType = 2670 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->FileType; 2671 pAudioMixSettings->pAddedAudioTrackFile = 2672 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->pFile; 2673 pAudioMixSettings->uiAddVolume = 2674 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->uiAddVolume; 2675 2676 pAudioMixSettings->outputAudioFormat = xVSS_context->pSettings->xVSS.outputAudioFormat; 2677 pAudioMixSettings->outputASF = xVSS_context->pSettings->xVSS.outputAudioSamplFreq; 2678 pAudioMixSettings->outputAudioBitrate = xVSS_context->pSettings->xVSS.outputAudioBitrate; 2679 pAudioMixSettings->uiSamplingFrequency = 2680 xVSS_context->pSettings->xVSS.pBGMtrack->uiSamplingFrequency; 2681 pAudioMixSettings->uiNumChannels = xVSS_context->pSettings->xVSS.pBGMtrack->uiNumChannels; 2682 2683 pAudioMixSettings->b_DuckingNeedeed = 2684 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->b_DuckingNeedeed; 2685 pAudioMixSettings->fBTVolLevel = 2686 (M4OSA_Float )xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->uiAddVolume/100; 2687 pAudioMixSettings->InDucking_threshold = 2688 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->InDucking_threshold; 2689 pAudioMixSettings->InDucking_lowVolume = 2690 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->lowVolume/100; 2691 pAudioMixSettings->fPTVolLevel = 2692 (M4OSA_Float)xVSS_context->pSettings->PTVolLevel/100; 2693 pAudioMixSettings->bLoop = xVSS_context->pSettings->xVSS.pBGMtrack->bLoop; 2694 2695 if(xVSS_context->pSettings->xVSS.bAudioMono) 2696 { 2697 pAudioMixSettings->outputNBChannels = 1; 2698 } 2699 else 2700 { 2701 pAudioMixSettings->outputNBChannels = 2; 2702 } 2703 2704 /** 2705 * Fill audio mix settings with BGM parameters */ 2706 pAudioMixSettings->uiBeginLoop = 2707 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->uiBeginLoop; 2708 pAudioMixSettings->uiEndLoop = 2709 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->uiEndLoop; 2710 pAudioMixSettings->uiAddCts = 2711 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->uiAddCts; 2712 2713 /** 2714 * Output file of the audio mixer will be final file (audio mixing is the last step) */ 2715 pAudioMixSettings->pOutputClipFile = xVSS_context->pOutputFile; 2716 pAudioMixSettings->pTemporaryFile = xVSS_context->pTemporaryFile; 2717 2718 /** 2719 * Input file of the audio mixer is a temporary file containing all audio/video editions */ 2720 pAudioMixSettings->pOriginalClipFile = xVSS_context->pCurrentEditSettings->pOutputFile; 2721 2722 /** 2723 * Save audio mixing settings pointer to be able to free it in 2724 M4xVSS_internalCloseAudioMixedFile function */ 2725 xVSS_context->pAudioMixSettings = pAudioMixSettings; 2726 2727 /** 2728 * Create a VSS 3GPP audio mixing instance */ 2729 err = M4VSS3GPP_audioMixingInit(&pAudioMixingCtxt, pAudioMixSettings, 2730 xVSS_context->pFileReadPtr, xVSS_context->pFileWritePtr); 2731 2732 /** 2733 * Save audio mixing context to be able to call audio mixing step function in 2734 M4xVSS_step function */ 2735 xVSS_context->pAudioMixContext = pAudioMixingCtxt; 2736 2737 if (err != M4NO_ERROR) 2738 { 2739 M4OSA_TRACE1_1("M4xVSS_internalGenerateAudioMixFile:\ 2740 M4VSS3GPP_audioMixingInit returned 0x%x\n",err); 2741 //M4VSS3GPP_audioMixingCleanUp(pAudioMixingCtxt); 2742 return err; 2743 } 2744 2745 return M4NO_ERROR; 2746 } 2747 2748 /** 2749 ****************************************************************************** 2750 * prototype M4OSA_ERR M4xVSS_internalCloseAudioMixedFile(M4OSA_Context pContext) 2751 * 2752 * @brief This function cleans up VSS for audio mixing 2753 * @note 2754 * @param pContext (IN) The integrator own context 2755 * 2756 * @return M4NO_ERROR: No error 2757 * @return M4ERR_PARAMETER: At least one of the function parameters is null 2758 ****************************************************************************** 2759 */ 2760 M4OSA_ERR M4xVSS_internalCloseAudioMixedFile(M4OSA_Context pContext) 2761 { 2762 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 2763 M4OSA_ERR err; 2764 2765 /** 2766 * Free this VSS3GPP audio mixing instance */ 2767 if(xVSS_context->pAudioMixContext != M4OSA_NULL) 2768 { 2769 err = M4VSS3GPP_audioMixingCleanUp(xVSS_context->pAudioMixContext); 2770 if (err != M4NO_ERROR) 2771 { 2772 M4OSA_TRACE1_1("M4xVSS_internalCloseAudioMixedFile:\ 2773 M4VSS3GPP_audioMixingCleanUp returned 0x%x\n",err); 2774 return err; 2775 } 2776 } 2777 2778 /** 2779 * Free VSS audio mixing settings */ 2780 if(xVSS_context->pAudioMixSettings != M4OSA_NULL) 2781 { 2782 free(xVSS_context->pAudioMixSettings); 2783 xVSS_context->pAudioMixSettings = M4OSA_NULL; 2784 } 2785 2786 return M4NO_ERROR; 2787 } 2788 2789 /** 2790 ****************************************************************************** 2791 * prototype M4OSA_ERR M4xVSS_internalFreePreview(M4OSA_Context pContext) 2792 * 2793 * @brief This function cleans up preview edition structure used to generate 2794 * preview.3gp file given to the VPS 2795 * @note It also free the preview structure given to the VPS 2796 * @param pContext (IN) The integrator own context 2797 * 2798 * @return M4NO_ERROR: No error 2799 * @return M4ERR_PARAMETER: At least one of the function parameters is null 2800 ****************************************************************************** 2801 */ 2802 M4OSA_ERR M4xVSS_internalFreePreview(M4OSA_Context pContext) 2803 { 2804 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 2805 M4OSA_UInt8 i; 2806 2807 /** 2808 * Free clip/transition settings */ 2809 for(i=0; i<xVSS_context->pCurrentEditSettings->uiClipNumber; i++) 2810 { 2811 M4xVSS_FreeClipSettings(xVSS_context->pCurrentEditSettings->pClipList[i]); 2812 2813 free((xVSS_context->pCurrentEditSettings->pClipList[i])); 2814 xVSS_context->pCurrentEditSettings->pClipList[i] = M4OSA_NULL; 2815 2816 /** 2817 * Because there is 1 less transition than clip number */ 2818 if(i != xVSS_context->pCurrentEditSettings->uiClipNumber-1) 2819 { 2820 free((xVSS_context->pCurrentEditSettings->pTransitionList[i])); 2821 xVSS_context->pCurrentEditSettings->pTransitionList[i] = M4OSA_NULL; 2822 } 2823 } 2824 2825 /** 2826 * Free clip/transition list */ 2827 if(xVSS_context->pCurrentEditSettings->pClipList != M4OSA_NULL) 2828 { 2829 free((xVSS_context->pCurrentEditSettings->pClipList)); 2830 xVSS_context->pCurrentEditSettings->pClipList = M4OSA_NULL; 2831 } 2832 if(xVSS_context->pCurrentEditSettings->pTransitionList != M4OSA_NULL) 2833 { 2834 free((xVSS_context->pCurrentEditSettings->pTransitionList)); 2835 xVSS_context->pCurrentEditSettings->pTransitionList = M4OSA_NULL; 2836 } 2837 2838 /** 2839 * Free output preview file path */ 2840 if(xVSS_context->pCurrentEditSettings->pOutputFile != M4OSA_NULL) 2841 { 2842 free(xVSS_context->pCurrentEditSettings->pOutputFile); 2843 xVSS_context->pCurrentEditSettings->pOutputFile = M4OSA_NULL; 2844 } 2845 2846 /** 2847 * Free temporary preview file path */ 2848 if(xVSS_context->pCurrentEditSettings->pTemporaryFile != M4OSA_NULL) 2849 { 2850 remove((const char *)xVSS_context->pCurrentEditSettings->pTemporaryFile); 2851 free(xVSS_context->pCurrentEditSettings->pTemporaryFile); 2852 xVSS_context->pCurrentEditSettings->pTemporaryFile = M4OSA_NULL; 2853 } 2854 2855 /** 2856 * Free "local" BGM settings */ 2857 if(xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack != M4OSA_NULL) 2858 { 2859 if(xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->pFile != M4OSA_NULL) 2860 { 2861 free(xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->pFile); 2862 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->pFile = M4OSA_NULL; 2863 } 2864 free(xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack); 2865 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack = M4OSA_NULL; 2866 } 2867 2868 /** 2869 * Free current edit settings structure */ 2870 if(xVSS_context->pCurrentEditSettings != M4OSA_NULL) 2871 { 2872 free(xVSS_context->pCurrentEditSettings); 2873 xVSS_context->pCurrentEditSettings = M4OSA_NULL; 2874 } 2875 2876 /** 2877 * Free preview effects given to application */ 2878 if(M4OSA_NULL != xVSS_context->pPreviewSettings->Effects) 2879 { 2880 free(xVSS_context->pPreviewSettings->Effects); 2881 xVSS_context->pPreviewSettings->Effects = M4OSA_NULL; 2882 xVSS_context->pPreviewSettings->nbEffects = 0; 2883 } 2884 2885 return M4NO_ERROR; 2886 } 2887 2888 2889 /** 2890 ****************************************************************************** 2891 * prototype M4OSA_ERR M4xVSS_internalFreeSaving(M4OSA_Context pContext) 2892 * 2893 * @brief This function cleans up saving edition structure used to generate 2894 * output.3gp file given to the VPS 2895 * @note 2896 * @param pContext (IN) The integrator own context 2897 * 2898 * @return M4NO_ERROR: No error 2899 * @return M4ERR_PARAMETER: At least one of the function parameters is null 2900 ****************************************************************************** 2901 */ 2902 M4OSA_ERR M4xVSS_internalFreeSaving(M4OSA_Context pContext) 2903 { 2904 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 2905 M4OSA_UInt8 i; 2906 2907 if(xVSS_context->pCurrentEditSettings != M4OSA_NULL) 2908 { 2909 /** 2910 * Free clip/transition settings */ 2911 for(i=0; i<xVSS_context->pCurrentEditSettings->uiClipNumber; i++) 2912 { 2913 M4xVSS_FreeClipSettings(xVSS_context->pCurrentEditSettings->pClipList[i]); 2914 2915 free((xVSS_context->pCurrentEditSettings->pClipList[i])); 2916 xVSS_context->pCurrentEditSettings->pClipList[i] = M4OSA_NULL; 2917 2918 /** 2919 * Because there is 1 less transition than clip number */ 2920 if(i != xVSS_context->pCurrentEditSettings->uiClipNumber-1) 2921 { 2922 free(\ 2923 (xVSS_context->pCurrentEditSettings->pTransitionList[i])); 2924 xVSS_context->pCurrentEditSettings->pTransitionList[i] = M4OSA_NULL; 2925 } 2926 } 2927 2928 /** 2929 * Free clip/transition list */ 2930 if(xVSS_context->pCurrentEditSettings->pClipList != M4OSA_NULL) 2931 { 2932 free((xVSS_context->pCurrentEditSettings->pClipList)); 2933 xVSS_context->pCurrentEditSettings->pClipList = M4OSA_NULL; 2934 } 2935 if(xVSS_context->pCurrentEditSettings->pTransitionList != M4OSA_NULL) 2936 { 2937 free((xVSS_context->pCurrentEditSettings->pTransitionList)); 2938 xVSS_context->pCurrentEditSettings->pTransitionList = M4OSA_NULL; 2939 } 2940 2941 if(xVSS_context->pCurrentEditSettings->Effects != M4OSA_NULL) 2942 { 2943 free((xVSS_context->pCurrentEditSettings->Effects)); 2944 xVSS_context->pCurrentEditSettings->Effects = M4OSA_NULL; 2945 xVSS_context->pCurrentEditSettings->nbEffects = 0; 2946 } 2947 2948 /** 2949 * Free output saving file path */ 2950 if(xVSS_context->pCurrentEditSettings->pOutputFile != M4OSA_NULL) 2951 { 2952 if(xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack != M4OSA_NULL) 2953 { 2954 remove((const char *)xVSS_context->pCurrentEditSettings->pOutputFile); 2955 free(xVSS_context->pCurrentEditSettings->pOutputFile); 2956 } 2957 if(xVSS_context->pOutputFile != M4OSA_NULL) 2958 { 2959 free(xVSS_context->pOutputFile); 2960 xVSS_context->pOutputFile = M4OSA_NULL; 2961 } 2962 xVSS_context->pSettings->pOutputFile = M4OSA_NULL; 2963 xVSS_context->pCurrentEditSettings->pOutputFile = M4OSA_NULL; 2964 } 2965 2966 /** 2967 * Free temporary saving file path */ 2968 if(xVSS_context->pCurrentEditSettings->pTemporaryFile != M4OSA_NULL) 2969 { 2970 remove((const char *)xVSS_context->pCurrentEditSettings->pTemporaryFile); 2971 free(xVSS_context->pCurrentEditSettings->pTemporaryFile); 2972 xVSS_context->pCurrentEditSettings->pTemporaryFile = M4OSA_NULL; 2973 } 2974 2975 /** 2976 * Free "local" BGM settings */ 2977 if(xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack != M4OSA_NULL) 2978 { 2979 if(xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->pFile != M4OSA_NULL) 2980 { 2981 free(xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->pFile); 2982 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack->pFile = M4OSA_NULL; 2983 } 2984 free(xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack); 2985 xVSS_context->pCurrentEditSettings->xVSS.pBGMtrack = M4OSA_NULL; 2986 } 2987 2988 /** 2989 * Free current edit settings structure */ 2990 free(xVSS_context->pCurrentEditSettings); 2991 xVSS_context->pCurrentEditSettings = M4OSA_NULL; 2992 } 2993 2994 return M4NO_ERROR; 2995 } 2996 2997 2998 /** 2999 ****************************************************************************** 3000 * prototype M4OSA_ERR M4xVSS_freeSettings(M4OSA_Context pContext) 3001 * 3002 * @brief This function cleans up an M4VSS3GPP_EditSettings structure 3003 * @note 3004 * @param pSettings (IN) Pointer on M4VSS3GPP_EditSettings structure to free 3005 * 3006 * @return M4NO_ERROR: No error 3007 * @return M4ERR_PARAMETER: At least one of the function parameters is null 3008 ****************************************************************************** 3009 */ 3010 M4OSA_ERR M4xVSS_freeSettings(M4VSS3GPP_EditSettings* pSettings) 3011 { 3012 M4OSA_UInt8 i,j; 3013 3014 /** 3015 * For each clip ... */ 3016 for(i=0; i<pSettings->uiClipNumber; i++) 3017 { 3018 /** 3019 * ... free clip settings */ 3020 if(pSettings->pClipList[i] != M4OSA_NULL) 3021 { 3022 M4xVSS_FreeClipSettings(pSettings->pClipList[i]); 3023 3024 free((pSettings->pClipList[i])); 3025 pSettings->pClipList[i] = M4OSA_NULL; 3026 } 3027 3028 /** 3029 * ... free transition settings */ 3030 if(i < pSettings->uiClipNumber-1) /* Because there is 1 less transition than clip number */ 3031 { 3032 if(pSettings->pTransitionList[i] != M4OSA_NULL) 3033 { 3034 switch (pSettings->pTransitionList[i]->VideoTransitionType) 3035 { 3036 case M4xVSS_kVideoTransitionType_AlphaMagic: 3037 3038 /** 3039 * In case of Alpha Magic transition, 3040 some extra parameters need to be freed */ 3041 if(pSettings->pTransitionList[i]->pExtVideoTransitionFctCtxt\ 3042 != M4OSA_NULL) 3043 { 3044 free((((M4xVSS_internal_AlphaMagicSettings*)\ 3045 pSettings->pTransitionList[i]->pExtVideoTransitionFctCtxt)->\ 3046 pPlane->pac_data)); 3047 ((M4xVSS_internal_AlphaMagicSettings*)pSettings->pTransitionList[i\ 3048 ]->pExtVideoTransitionFctCtxt)->pPlane->pac_data = M4OSA_NULL; 3049 3050 free((((M4xVSS_internal_AlphaMagicSettings*)\ 3051 pSettings->pTransitionList[i]->\ 3052 pExtVideoTransitionFctCtxt)->pPlane)); 3053 ((M4xVSS_internal_AlphaMagicSettings*)pSettings->pTransitionList[i]\ 3054 ->pExtVideoTransitionFctCtxt)->pPlane = M4OSA_NULL; 3055 3056 free((pSettings->pTransitionList[i]->\ 3057 pExtVideoTransitionFctCtxt)); 3058 pSettings->pTransitionList[i]->pExtVideoTransitionFctCtxt = M4OSA_NULL; 3059 3060 for(j=i+1;j<pSettings->uiClipNumber-1;j++) 3061 { 3062 if(pSettings->pTransitionList[j] != M4OSA_NULL) 3063 { 3064 if(pSettings->pTransitionList[j]->VideoTransitionType == 3065 M4xVSS_kVideoTransitionType_AlphaMagic) 3066 { 3067 M4OSA_UInt32 pCmpResult=0; 3068 pCmpResult = strcmp((const char *)pSettings->pTransitionList[i]->\ 3069 xVSS.transitionSpecific.pAlphaMagicSettings->\ 3070 pAlphaFilePath, 3071 (const char *)pSettings->pTransitionList[j]->\ 3072 xVSS.transitionSpecific.pAlphaMagicSettings->\ 3073 pAlphaFilePath); 3074 if(pCmpResult == 0) 3075 { 3076 /* Free extra internal alpha magic structure and put 3077 it to NULL to avoid refreeing it */ 3078 free((pSettings->\ 3079 pTransitionList[j]->pExtVideoTransitionFctCtxt)); 3080 pSettings->pTransitionList[j]->\ 3081 pExtVideoTransitionFctCtxt = M4OSA_NULL; 3082 } 3083 } 3084 } 3085 } 3086 } 3087 3088 if(pSettings->pTransitionList[i]->\ 3089 xVSS.transitionSpecific.pAlphaMagicSettings != M4OSA_NULL) 3090 { 3091 if(pSettings->pTransitionList[i]->\ 3092 xVSS.transitionSpecific.pAlphaMagicSettings->\ 3093 pAlphaFilePath != M4OSA_NULL) 3094 { 3095 free(pSettings->\ 3096 pTransitionList[i]->\ 3097 xVSS.transitionSpecific.pAlphaMagicSettings->\ 3098 pAlphaFilePath); 3099 pSettings->pTransitionList[i]->\ 3100 xVSS.transitionSpecific.pAlphaMagicSettings->\ 3101 pAlphaFilePath = M4OSA_NULL; 3102 } 3103 free(pSettings->pTransitionList[i]->\ 3104 xVSS.transitionSpecific.pAlphaMagicSettings); 3105 pSettings->pTransitionList[i]->\ 3106 xVSS.transitionSpecific.pAlphaMagicSettings = M4OSA_NULL; 3107 3108 } 3109 3110 break; 3111 3112 3113 case M4xVSS_kVideoTransitionType_SlideTransition: 3114 if (M4OSA_NULL != pSettings->pTransitionList[i]->\ 3115 xVSS.transitionSpecific.pSlideTransitionSettings) 3116 { 3117 free(pSettings->pTransitionList[i]->\ 3118 xVSS.transitionSpecific.pSlideTransitionSettings); 3119 pSettings->pTransitionList[i]->\ 3120 xVSS.transitionSpecific.pSlideTransitionSettings = M4OSA_NULL; 3121 } 3122 if(pSettings->pTransitionList[i]->pExtVideoTransitionFctCtxt != M4OSA_NULL) 3123 { 3124 free((pSettings->pTransitionList[i]->\ 3125 pExtVideoTransitionFctCtxt)); 3126 pSettings->pTransitionList[i]->pExtVideoTransitionFctCtxt = M4OSA_NULL; 3127 } 3128 break; 3129 default: 3130 break; 3131 3132 } 3133 /** 3134 * Free transition settings structure */ 3135 free((pSettings->pTransitionList[i])); 3136 pSettings->pTransitionList[i] = M4OSA_NULL; 3137 } 3138 } 3139 } 3140 3141 /** 3142 * Free clip list */ 3143 if(pSettings->pClipList != M4OSA_NULL) 3144 { 3145 free((pSettings->pClipList)); 3146 pSettings->pClipList = M4OSA_NULL; 3147 } 3148 3149 /** 3150 * Free transition list */ 3151 if(pSettings->pTransitionList != M4OSA_NULL) 3152 { 3153 free((pSettings->pTransitionList)); 3154 pSettings->pTransitionList = M4OSA_NULL; 3155 } 3156 3157 /** 3158 * RC: Free effects list */ 3159 if(pSettings->Effects != M4OSA_NULL) 3160 { 3161 for(i=0; i<pSettings->nbEffects; i++) 3162 { 3163 /** 3164 * For each clip, free framing structure if needed */ 3165 if(pSettings->Effects[i].VideoEffectType == M4xVSS_kVideoEffectType_Framing 3166 || pSettings->Effects[i].VideoEffectType == M4xVSS_kVideoEffectType_Text) 3167 { 3168 #ifdef DECODE_GIF_ON_SAVING 3169 M4xVSS_FramingContext* framingCtx = pSettings->Effects[i].pExtVideoEffectFctCtxt; 3170 #else 3171 M4xVSS_FramingStruct* framingCtx = pSettings->Effects[i].pExtVideoEffectFctCtxt; 3172 M4xVSS_FramingStruct* framingCtx_save; 3173 M4xVSS_Framing3102Struct* framingCtx_first = framingCtx; 3174 #endif 3175 3176 #ifdef DECODE_GIF_ON_SAVING 3177 if(framingCtx != M4OSA_NULL) /* Bugfix 1.2.0: crash, trying to free non existant 3178 pointer */ 3179 { 3180 if(framingCtx->aFramingCtx != M4OSA_NULL) 3181 { 3182 { 3183 if(framingCtx->aFramingCtx->FramingRgb != M4OSA_NULL) 3184 { 3185 free(framingCtx->aFramingCtx->\ 3186 FramingRgb->pac_data); 3187 framingCtx->aFramingCtx->FramingRgb->pac_data = M4OSA_NULL; 3188 free(framingCtx->aFramingCtx->FramingRgb); 3189 framingCtx->aFramingCtx->FramingRgb = M4OSA_NULL; 3190 } 3191 } 3192 if(framingCtx->aFramingCtx->FramingYuv != M4OSA_NULL) 3193 { 3194 free(framingCtx->aFramingCtx->\ 3195 FramingYuv[0].pac_data); 3196 framingCtx->aFramingCtx->FramingYuv[0].pac_data = M4OSA_NULL; 3197 free(framingCtx->aFramingCtx->\ 3198 FramingYuv[1].pac_data); 3199 framingCtx->aFramingCtx->FramingYuv[1].pac_data = M4OSA_NULL; 3200 free(framingCtx->aFramingCtx->\ 3201 FramingYuv[2].pac_data); 3202 framingCtx->aFramingCtx->FramingYuv[2].pac_data = M4OSA_NULL; 3203 free(framingCtx->aFramingCtx->FramingYuv); 3204 framingCtx->aFramingCtx->FramingYuv = M4OSA_NULL; 3205 } 3206 free(framingCtx->aFramingCtx); 3207 framingCtx->aFramingCtx = M4OSA_NULL; 3208 } 3209 if(framingCtx->aFramingCtx_last != M4OSA_NULL) 3210 { 3211 if(framingCtx->aFramingCtx_last->FramingRgb != M4OSA_NULL) 3212 { 3213 free(framingCtx->aFramingCtx_last->\ 3214 FramingRgb->pac_data); 3215 framingCtx->aFramingCtx_last->FramingRgb->pac_data = M4OSA_NULL; 3216 free(framingCtx->aFramingCtx_last->\ 3217 FramingRgb); 3218 framingCtx->aFramingCtx_last->FramingRgb = M4OSA_NULL; 3219 } 3220 if(framingCtx->aFramingCtx_last->FramingYuv != M4OSA_NULL) 3221 { 3222 free(framingCtx->aFramingCtx_last->\ 3223 FramingYuv[0].pac_data); 3224 framingCtx->aFramingCtx_last->FramingYuv[0].pac_data = M4OSA_NULL; 3225 free(framingCtx->aFramingCtx_last->FramingYuv); 3226 framingCtx->aFramingCtx_last->FramingYuv = M4OSA_NULL; 3227 } 3228 free(framingCtx->aFramingCtx_last); 3229 framingCtx->aFramingCtx_last = M4OSA_NULL; 3230 } 3231 if(framingCtx->pEffectFilePath != M4OSA_NULL) 3232 { 3233 free(framingCtx->pEffectFilePath); 3234 framingCtx->pEffectFilePath = M4OSA_NULL; 3235 } 3236 /*In case there are still allocated*/ 3237 if(framingCtx->pSPSContext != M4OSA_NULL) 3238 { 3239 // M4SPS_destroy(framingCtx->pSPSContext); 3240 framingCtx->pSPSContext = M4OSA_NULL; 3241 } 3242 /*Alpha blending structure*/ 3243 if(framingCtx->alphaBlendingStruct != M4OSA_NULL) 3244 { 3245 free(framingCtx->alphaBlendingStruct); 3246 framingCtx->alphaBlendingStruct = M4OSA_NULL; 3247 } 3248 3249 free(framingCtx); 3250 framingCtx = M4OSA_NULL; 3251 } 3252 #else 3253 do 3254 { 3255 if(framingCtx != M4OSA_NULL) /* Bugfix 1.2.0: crash, trying to free non 3256 existant pointer */ 3257 { 3258 if(framingCtx->FramingRgb != M4OSA_NULL) 3259 { 3260 free(framingCtx->FramingRgb->pac_data); 3261 framingCtx->FramingRgb->pac_data = M4OSA_NULL; 3262 free(framingCtx->FramingRgb); 3263 framingCtx->FramingRgb = M4OSA_NULL; 3264 } 3265 if(framingCtx->FramingYuv != M4OSA_NULL) 3266 { 3267 free(framingCtx->FramingYuv[0].pac_data); 3268 framingCtx->FramingYuv[0].pac_data = M4OSA_NULL; 3269 free(framingCtx->FramingYuv); 3270 framingCtx->FramingYuv = M4OSA_NULL; 3271 } 3272 framingCtx_save = framingCtx->pNext; 3273 free(framingCtx); 3274 framingCtx = M4OSA_NULL; 3275 framingCtx = framingCtx_save; 3276 } 3277 else 3278 { 3279 /*FB: bug fix P4ME00003002*/ 3280 break; 3281 } 3282 } while(framingCtx_first != framingCtx); 3283 #endif 3284 } 3285 else if( M4xVSS_kVideoEffectType_Fifties == pSettings->Effects[i].VideoEffectType) 3286 { 3287 /* Free Fifties context */ 3288 M4xVSS_FiftiesStruct* FiftiesCtx = pSettings->Effects[i].pExtVideoEffectFctCtxt; 3289 3290 if(FiftiesCtx != M4OSA_NULL) 3291 { 3292 free(FiftiesCtx); 3293 FiftiesCtx = M4OSA_NULL; 3294 } 3295 3296 } 3297 else if( M4xVSS_kVideoEffectType_ColorRGB16 == pSettings->Effects[i].VideoEffectType 3298 || M4xVSS_kVideoEffectType_BlackAndWhite == pSettings->Effects[i].VideoEffectType 3299 || M4xVSS_kVideoEffectType_Pink == pSettings->Effects[i].VideoEffectType 3300 || M4xVSS_kVideoEffectType_Green == pSettings->Effects[i].VideoEffectType 3301 || M4xVSS_kVideoEffectType_Sepia == pSettings->Effects[i].VideoEffectType 3302 || M4xVSS_kVideoEffectType_Negative== pSettings->Effects[i].VideoEffectType 3303 || M4xVSS_kVideoEffectType_Gradient== pSettings->Effects[i].VideoEffectType) 3304 { 3305 /* Free Color context */ 3306 M4xVSS_ColorStruct* ColorCtx = pSettings->Effects[i].pExtVideoEffectFctCtxt; 3307 3308 if(ColorCtx != M4OSA_NULL) 3309 { 3310 free(ColorCtx); 3311 ColorCtx = M4OSA_NULL; 3312 } 3313 } 3314 3315 /* Free simple fields */ 3316 if(pSettings->Effects[i].xVSS.pFramingFilePath != M4OSA_NULL) 3317 { 3318 free(pSettings->Effects[i].xVSS.pFramingFilePath); 3319 pSettings->Effects[i].xVSS.pFramingFilePath = M4OSA_NULL; 3320 } 3321 if(pSettings->Effects[i].xVSS.pFramingBuffer != M4OSA_NULL) 3322 { 3323 free(pSettings->Effects[i].xVSS.pFramingBuffer); 3324 pSettings->Effects[i].xVSS.pFramingBuffer = M4OSA_NULL; 3325 } 3326 if(pSettings->Effects[i].xVSS.pTextBuffer != M4OSA_NULL) 3327 { 3328 free(pSettings->Effects[i].xVSS.pTextBuffer); 3329 pSettings->Effects[i].xVSS.pTextBuffer = M4OSA_NULL; 3330 } 3331 } 3332 free(pSettings->Effects); 3333 pSettings->Effects = M4OSA_NULL; 3334 } 3335 3336 return M4NO_ERROR; 3337 } 3338 3339 M4OSA_ERR M4xVSS_freeCommand(M4OSA_Context pContext) 3340 { 3341 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 3342 // M4OSA_UInt8 i,j; 3343 3344 /* Free "local" BGM settings */ 3345 if(xVSS_context->pSettings->xVSS.pBGMtrack != M4OSA_NULL) 3346 { 3347 if(xVSS_context->pSettings->xVSS.pBGMtrack->pFile != M4OSA_NULL) 3348 { 3349 free(xVSS_context->pSettings->xVSS.pBGMtrack->pFile); 3350 xVSS_context->pSettings->xVSS.pBGMtrack->pFile = M4OSA_NULL; 3351 } 3352 free(xVSS_context->pSettings->xVSS.pBGMtrack); 3353 xVSS_context->pSettings->xVSS.pBGMtrack = M4OSA_NULL; 3354 } 3355 3356 M4xVSS_freeSettings(xVSS_context->pSettings); 3357 3358 if(xVSS_context->pPTo3GPPparamsList != M4OSA_NULL) 3359 { 3360 M4xVSS_Pto3GPP_params* pParams = xVSS_context->pPTo3GPPparamsList; 3361 M4xVSS_Pto3GPP_params* pParams_sauv; 3362 3363 while(pParams != M4OSA_NULL) 3364 { 3365 if(pParams->pFileIn != M4OSA_NULL) 3366 { 3367 free(pParams->pFileIn); 3368 pParams->pFileIn = M4OSA_NULL; 3369 } 3370 if(pParams->pFileOut != M4OSA_NULL) 3371 { 3372 /* Delete temporary file */ 3373 remove((const char *)pParams->pFileOut); 3374 free(pParams->pFileOut); 3375 pParams->pFileOut = M4OSA_NULL; 3376 } 3377 if(pParams->pFileTemp != M4OSA_NULL) 3378 { 3379 /* Delete temporary file */ 3380 #ifdef M4xVSS_RESERVED_MOOV_DISK_SPACE 3381 remove((const char *)pParams->pFileTemp); 3382 free(pParams->pFileTemp); 3383 #endif/*M4xVSS_RESERVED_MOOV_DISK_SPACE*/ 3384 pParams->pFileTemp = M4OSA_NULL; 3385 } 3386 pParams_sauv = pParams; 3387 pParams = pParams->pNext; 3388 free(pParams_sauv); 3389 pParams_sauv = M4OSA_NULL; 3390 } 3391 } 3392 3393 if(xVSS_context->pMCSparamsList != M4OSA_NULL) 3394 { 3395 M4xVSS_MCS_params* pParams = xVSS_context->pMCSparamsList; 3396 M4xVSS_MCS_params* pParams_sauv; 3397 3398 while(pParams != M4OSA_NULL) 3399 { 3400 if(pParams->pFileIn != M4OSA_NULL) 3401 { 3402 free(pParams->pFileIn); 3403 pParams->pFileIn = M4OSA_NULL; 3404 } 3405 if(pParams->pFileOut != M4OSA_NULL) 3406 { 3407 /* Delete temporary file */ 3408 remove((const char *)pParams->pFileOut); 3409 free(pParams->pFileOut); 3410 pParams->pFileOut = M4OSA_NULL; 3411 } 3412 if(pParams->pFileTemp != M4OSA_NULL) 3413 { 3414 /* Delete temporary file */ 3415 #ifdef M4xVSS_RESERVED_MOOV_DISK_SPACE 3416 remove((const char *)pParams->pFileTemp); 3417 free(pParams->pFileTemp); 3418 #endif/*M4xVSS_RESERVED_MOOV_DISK_SPACE*/ 3419 pParams->pFileTemp = M4OSA_NULL; 3420 } 3421 pParams_sauv = pParams; 3422 pParams = pParams->pNext; 3423 free(pParams_sauv); 3424 pParams_sauv = M4OSA_NULL; 3425 } 3426 } 3427 3428 if(xVSS_context->pcmPreviewFile != M4OSA_NULL) 3429 { 3430 free(xVSS_context->pcmPreviewFile); 3431 xVSS_context->pcmPreviewFile = M4OSA_NULL; 3432 } 3433 if(xVSS_context->pSettings->pOutputFile != M4OSA_NULL 3434 && xVSS_context->pOutputFile != M4OSA_NULL) 3435 { 3436 free(xVSS_context->pSettings->pOutputFile); 3437 xVSS_context->pSettings->pOutputFile = M4OSA_NULL; 3438 xVSS_context->pOutputFile = M4OSA_NULL; 3439 } 3440 3441 /* Reinit all context variables */ 3442 xVSS_context->previousClipNumber = 0; 3443 xVSS_context->editingStep = M4xVSS_kMicroStateEditing; 3444 xVSS_context->analyseStep = M4xVSS_kMicroStateAnalysePto3GPP; 3445 xVSS_context->pPTo3GPPparamsList = M4OSA_NULL; 3446 xVSS_context->pPTo3GPPcurrentParams = M4OSA_NULL; 3447 xVSS_context->pMCSparamsList = M4OSA_NULL; 3448 xVSS_context->pMCScurrentParams = M4OSA_NULL; 3449 xVSS_context->tempFileIndex = 0; 3450 xVSS_context->targetedTimescale = 0; 3451 3452 return M4NO_ERROR; 3453 } 3454 3455 /** 3456 ****************************************************************************** 3457 * prototype M4OSA_ERR M4xVSS_internalGetProperties(M4OSA_Context pContext, 3458 * M4OSA_Char* pFile, 3459 * M4VIDEOEDITING_ClipProperties *pFileProperties) 3460 * 3461 * @brief This function retrieve properties of an input 3GP file using MCS 3462 * @note 3463 * @param pContext (IN) The integrator own context 3464 * @param pFile (IN) 3GP file to analyse 3465 * @param pFileProperties (IN/OUT) Pointer on a structure that will contain 3466 * the 3GP file properties 3467 * 3468 * @return M4NO_ERROR: No error 3469 * @return M4ERR_PARAMETER: At least one of the function parameters is null 3470 ****************************************************************************** 3471 */ 3472 M4OSA_ERR M4xVSS_internalGetProperties(M4OSA_Context pContext, M4OSA_Char* pFile, 3473 M4VIDEOEDITING_ClipProperties *pFileProperties) 3474 { 3475 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 3476 M4OSA_ERR err; 3477 M4MCS_Context mcs_context; 3478 3479 err = M4MCS_init(&mcs_context, xVSS_context->pFileReadPtr, xVSS_context->pFileWritePtr); 3480 if(err != M4NO_ERROR) 3481 { 3482 M4OSA_TRACE1_1("M4xVSS_internalGetProperties: Error in M4MCS_init: 0x%x", err); 3483 return err; 3484 } 3485 3486 /*open the MCS in the "normal opening" mode to retrieve the exact duration*/ 3487 err = M4MCS_open_normalMode(mcs_context, pFile, M4VIDEOEDITING_kFileType_3GPP, 3488 M4OSA_NULL, M4OSA_NULL); 3489 if (err != M4NO_ERROR) 3490 { 3491 M4OSA_TRACE1_1("M4xVSS_internalGetProperties: Error in M4MCS_open: 0x%x", err); 3492 M4MCS_abort(mcs_context); 3493 return err; 3494 } 3495 3496 err = M4MCS_getInputFileProperties(mcs_context, pFileProperties); 3497 if(err != M4NO_ERROR) 3498 { 3499 M4OSA_TRACE1_1("Error in M4MCS_getInputFileProperties: 0x%x", err); 3500 M4MCS_abort(mcs_context); 3501 return err; 3502 } 3503 3504 err = M4MCS_abort(mcs_context); 3505 if (err != M4NO_ERROR) 3506 { 3507 M4OSA_TRACE1_1("M4xVSS_internalGetProperties: Error in M4MCS_abort: 0x%x", err); 3508 return err; 3509 } 3510 3511 return M4NO_ERROR; 3512 } 3513 3514 3515 /** 3516 ****************************************************************************** 3517 * prototype M4OSA_ERR M4xVSS_internalGetTargetedTimeScale(M4OSA_Context pContext, 3518 * M4OSA_UInt32* pTargetedTimeScale) 3519 * 3520 * @brief This function retrieve targeted time scale 3521 * @note 3522 * @param pContext (IN) The integrator own context 3523 * @param pTargetedTimeScale (OUT) Targeted time scale 3524 * 3525 * @return M4NO_ERROR: No error 3526 * @return M4ERR_PARAMETER: At least one of the function parameters is null 3527 ****************************************************************************** 3528 */ 3529 M4OSA_ERR M4xVSS_internalGetTargetedTimeScale(M4OSA_Context pContext, 3530 M4VSS3GPP_EditSettings* pSettings, 3531 M4OSA_UInt32* pTargetedTimeScale) 3532 { 3533 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 3534 M4OSA_ERR err; 3535 M4OSA_UInt32 totalDuration = 0; 3536 M4OSA_UInt8 i = 0; 3537 M4OSA_UInt32 tempTimeScale = 0, tempDuration = 0; 3538 3539 for(i=0;i<pSettings->uiClipNumber;i++) 3540 { 3541 /*search timescale only in mpeg4 case*/ 3542 if(pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_3GPP 3543 || pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_MP4 3544 || pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_M4V) 3545 { 3546 M4VIDEOEDITING_ClipProperties fileProperties; 3547 3548 /*UTF conversion support*/ 3549 M4OSA_Char* pDecodedPath = M4OSA_NULL; 3550 3551 /** 3552 * UTF conversion: convert into the customer format, before being used*/ 3553 pDecodedPath = pSettings->pClipList[i]->pFile; 3554 3555 if(xVSS_context->UTFConversionContext.pConvToUTF8Fct != M4OSA_NULL 3556 && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL) 3557 { 3558 M4OSA_UInt32 length = 0; 3559 err = M4xVSS_internalConvertFromUTF8(xVSS_context, 3560 (M4OSA_Void*) pSettings->pClipList[i]->pFile, 3561 (M4OSA_Void*) xVSS_context->UTFConversionContext.pTempOutConversionBuffer, 3562 &length); 3563 if(err != M4NO_ERROR) 3564 { 3565 M4OSA_TRACE1_1("M4xVSS_Init:\ 3566 M4xVSS_internalConvertToUTF8 returns err: 0x%x",err); 3567 return err; 3568 } 3569 pDecodedPath = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; 3570 } 3571 3572 /*End of the conversion: use the decoded path*/ 3573 err = M4xVSS_internalGetProperties(xVSS_context, pDecodedPath, &fileProperties); 3574 3575 /*get input file properties*/ 3576 /*err = M4xVSS_internalGetProperties(xVSS_context, pSettings->\ 3577 pClipList[i]->pFile, &fileProperties);*/ 3578 if(M4NO_ERROR != err) 3579 { 3580 M4OSA_TRACE1_1("M4xVSS_internalGetTargetedTimeScale:\ 3581 M4xVSS_internalGetProperties returned: 0x%x", err); 3582 return err; 3583 } 3584 if(fileProperties.VideoStreamType == M4VIDEOEDITING_kMPEG4) 3585 { 3586 if(pSettings->pClipList[i]->uiEndCutTime > 0) 3587 { 3588 if(tempDuration < (pSettings->pClipList[i]->uiEndCutTime \ 3589 - pSettings->pClipList[i]->uiBeginCutTime)) 3590 { 3591 tempTimeScale = fileProperties.uiVideoTimeScale; 3592 tempDuration = (pSettings->pClipList[i]->uiEndCutTime\ 3593 - pSettings->pClipList[i]->uiBeginCutTime); 3594 } 3595 } 3596 else 3597 { 3598 if(tempDuration < (fileProperties.uiClipDuration\ 3599 - pSettings->pClipList[i]->uiBeginCutTime)) 3600 { 3601 tempTimeScale = fileProperties.uiVideoTimeScale; 3602 tempDuration = (fileProperties.uiClipDuration\ 3603 - pSettings->pClipList[i]->uiBeginCutTime); 3604 } 3605 } 3606 } 3607 } 3608 if(pSettings->pClipList[i]->FileType == M4VIDEOEDITING_kFileType_ARGB8888) 3609 { 3610 /*the timescale is 30 for PTO3GP*/ 3611 *pTargetedTimeScale = 30; 3612 return M4NO_ERROR; 3613 3614 } 3615 } 3616 3617 if(tempTimeScale >= 30)/*Define a minimum time scale, otherwise if the timescale is not 3618 enough, there will be an infinite loop in the shell encoder*/ 3619 { 3620 *pTargetedTimeScale = tempTimeScale; 3621 } 3622 else 3623 { 3624 *pTargetedTimeScale = 30; 3625 } 3626 3627 return M4NO_ERROR; 3628 } 3629 3630 3631 /** 3632 ****************************************************************************** 3633 * prototype M4VSS3GPP_externalVideoEffectColor(M4OSA_Void *pFunctionContext, 3634 * M4VIFI_ImagePlane *PlaneIn, 3635 * M4VIFI_ImagePlane *PlaneOut, 3636 * M4VSS3GPP_ExternalProgress *pProgress, 3637 * M4OSA_UInt32 uiEffectKind) 3638 * 3639 * @brief This function apply a color effect on an input YUV420 planar frame 3640 * @note 3641 * @param pFunctionContext(IN) Contains which color to apply (not very clean ...) 3642 * @param PlaneIn (IN) Input YUV420 planar 3643 * @param PlaneOut (IN/OUT) Output YUV420 planar 3644 * @param pProgress (IN/OUT) Progress indication (0-100) 3645 * @param uiEffectKind (IN) Unused 3646 * 3647 * @return M4VIFI_OK: No error 3648 ****************************************************************************** 3649 */ 3650 M4OSA_ERR M4VSS3GPP_externalVideoEffectColor(M4OSA_Void *pFunctionContext, 3651 M4VIFI_ImagePlane *PlaneIn, 3652 M4VIFI_ImagePlane *PlaneOut, 3653 M4VSS3GPP_ExternalProgress *pProgress, 3654 M4OSA_UInt32 uiEffectKind) 3655 { 3656 M4VIFI_Int32 plane_number; 3657 M4VIFI_UInt32 i,j; 3658 M4VIFI_UInt8 *p_buf_src, *p_buf_dest; 3659 M4xVSS_ColorStruct* ColorContext = (M4xVSS_ColorStruct*)pFunctionContext; 3660 3661 for (plane_number = 0; plane_number < 3; plane_number++) 3662 { 3663 p_buf_src = &(PlaneIn[plane_number].pac_data[PlaneIn[plane_number].u_topleft]); 3664 p_buf_dest = &(PlaneOut[plane_number].pac_data[PlaneOut[plane_number].u_topleft]); 3665 for (i = 0; i < PlaneOut[plane_number].u_height; i++) 3666 { 3667 /** 3668 * Chrominance */ 3669 if(plane_number==1 || plane_number==2) 3670 { 3671 //switch ((M4OSA_UInt32)pFunctionContext) 3672 // commented because a structure for the effects context exist 3673 switch (ColorContext->colorEffectType) 3674 { 3675 case M4xVSS_kVideoEffectType_BlackAndWhite: 3676 memset((void *)p_buf_dest,128, 3677 PlaneIn[plane_number].u_width); 3678 break; 3679 case M4xVSS_kVideoEffectType_Pink: 3680 memset((void *)p_buf_dest,255, 3681 PlaneIn[plane_number].u_width); 3682 break; 3683 case M4xVSS_kVideoEffectType_Green: 3684 memset((void *)p_buf_dest,0, 3685 PlaneIn[plane_number].u_width); 3686 break; 3687 case M4xVSS_kVideoEffectType_Sepia: 3688 if(plane_number==1) 3689 { 3690 memset((void *)p_buf_dest,117, 3691 PlaneIn[plane_number].u_width); 3692 } 3693 else 3694 { 3695 memset((void *)p_buf_dest,139, 3696 PlaneIn[plane_number].u_width); 3697 } 3698 break; 3699 case M4xVSS_kVideoEffectType_Negative: 3700 memcpy((void *)p_buf_dest, 3701 (void *)p_buf_src ,PlaneOut[plane_number].u_width); 3702 break; 3703 3704 case M4xVSS_kVideoEffectType_ColorRGB16: 3705 { 3706 M4OSA_UInt16 r = 0,g = 0,b = 0,y = 0,u = 0,v = 0; 3707 3708 /*first get the r, g, b*/ 3709 b = (ColorContext->rgb16ColorData & 0x001f); 3710 g = (ColorContext->rgb16ColorData & 0x07e0)>>5; 3711 r = (ColorContext->rgb16ColorData & 0xf800)>>11; 3712 3713 /*keep y, but replace u and v*/ 3714 if(plane_number==1) 3715 { 3716 /*then convert to u*/ 3717 u = U16(r, g, b); 3718 memset((void *)p_buf_dest,(M4OSA_UInt8)u, 3719 PlaneIn[plane_number].u_width); 3720 } 3721 if(plane_number==2) 3722 { 3723 /*then convert to v*/ 3724 v = V16(r, g, b); 3725 memset((void *)p_buf_dest, (M4OSA_UInt8)v, 3726 PlaneIn[plane_number].u_width); 3727 } 3728 } 3729 break; 3730 case M4xVSS_kVideoEffectType_Gradient: 3731 { 3732 M4OSA_UInt16 r = 0,g = 0,b = 0,y = 0,u = 0,v = 0; 3733 3734 /*first get the r, g, b*/ 3735 b = (ColorContext->rgb16ColorData & 0x001f); 3736 g = (ColorContext->rgb16ColorData & 0x07e0)>>5; 3737 r = (ColorContext->rgb16ColorData & 0xf800)>>11; 3738 3739 /*for color gradation*/ 3740 b = (M4OSA_UInt16)( b - ((b*i)/PlaneIn[plane_number].u_height)); 3741 g = (M4OSA_UInt16)(g - ((g*i)/PlaneIn[plane_number].u_height)); 3742 r = (M4OSA_UInt16)(r - ((r*i)/PlaneIn[plane_number].u_height)); 3743 3744 /*keep y, but replace u and v*/ 3745 if(plane_number==1) 3746 { 3747 /*then convert to u*/ 3748 u = U16(r, g, b); 3749 memset((void *)p_buf_dest,(M4OSA_UInt8)u, 3750 PlaneIn[plane_number].u_width); 3751 } 3752 if(plane_number==2) 3753 { 3754 /*then convert to v*/ 3755 v = V16(r, g, b); 3756 memset((void *)p_buf_dest,(M4OSA_UInt8)v, 3757 PlaneIn[plane_number].u_width); 3758 } 3759 } 3760 break; 3761 default: 3762 break; 3763 } 3764 } 3765 /** 3766 * Luminance */ 3767 else 3768 { 3769 //switch ((M4OSA_UInt32)pFunctionContext) 3770 // commented because a structure for the effects context exist 3771 switch (ColorContext->colorEffectType) 3772 { 3773 case M4xVSS_kVideoEffectType_Negative: 3774 for(j=0;j<PlaneOut[plane_number].u_width;j++) 3775 { 3776 p_buf_dest[j] = 255 - p_buf_src[j]; 3777 } 3778 break; 3779 default: 3780 memcpy((void *)p_buf_dest, 3781 (void *)p_buf_src ,PlaneOut[plane_number].u_width); 3782 break; 3783 } 3784 } 3785 p_buf_src += PlaneIn[plane_number].u_stride; 3786 p_buf_dest += PlaneOut[plane_number].u_stride; 3787 } 3788 } 3789 3790 return M4VIFI_OK; 3791 } 3792 3793 /** 3794 ****************************************************************************** 3795 * prototype M4VSS3GPP_externalVideoEffectFraming(M4OSA_Void *pFunctionContext, 3796 * M4VIFI_ImagePlane *PlaneIn, 3797 * M4VIFI_ImagePlane *PlaneOut, 3798 * M4VSS3GPP_ExternalProgress *pProgress, 3799 * M4OSA_UInt32 uiEffectKind) 3800 * 3801 * @brief This function add a fixed or animated image on an input YUV420 planar frame 3802 * @note 3803 * @param pFunctionContext(IN) Contains which color to apply (not very clean ...) 3804 * @param PlaneIn (IN) Input YUV420 planar 3805 * @param PlaneOut (IN/OUT) Output YUV420 planar 3806 * @param pProgress (IN/OUT) Progress indication (0-100) 3807 * @param uiEffectKind (IN) Unused 3808 * 3809 * @return M4VIFI_OK: No error 3810 ****************************************************************************** 3811 */ 3812 M4OSA_ERR M4VSS3GPP_externalVideoEffectFraming( M4OSA_Void *userData, 3813 M4VIFI_ImagePlane PlaneIn[3], 3814 M4VIFI_ImagePlane *PlaneOut, 3815 M4VSS3GPP_ExternalProgress *pProgress, 3816 M4OSA_UInt32 uiEffectKind ) 3817 { 3818 M4VIFI_UInt32 x,y; 3819 3820 M4VIFI_UInt8 *p_in_Y = PlaneIn[0].pac_data; 3821 M4VIFI_UInt8 *p_in_U = PlaneIn[1].pac_data; 3822 M4VIFI_UInt8 *p_in_V = PlaneIn[2].pac_data; 3823 3824 M4xVSS_FramingStruct* Framing = M4OSA_NULL; 3825 M4xVSS_FramingStruct* currentFraming = M4OSA_NULL; 3826 M4VIFI_UInt8 *FramingRGB = M4OSA_NULL; 3827 3828 M4VIFI_UInt8 *p_out0; 3829 M4VIFI_UInt8 *p_out1; 3830 M4VIFI_UInt8 *p_out2; 3831 3832 M4VIFI_UInt32 topleft[2]; 3833 3834 M4OSA_UInt8 transparent1 = (M4OSA_UInt8)((TRANSPARENT_COLOR & 0xFF00)>>8); 3835 M4OSA_UInt8 transparent2 = (M4OSA_UInt8)TRANSPARENT_COLOR; 3836 3837 #ifndef DECODE_GIF_ON_SAVING 3838 Framing = (M4xVSS_FramingStruct *)userData; 3839 currentFraming = (M4xVSS_FramingStruct *)Framing->pCurrent; 3840 FramingRGB = Framing->FramingRgb->pac_data; 3841 #endif /*DECODE_GIF_ON_SAVING*/ 3842 3843 /*FB*/ 3844 #ifdef DECODE_GIF_ON_SAVING 3845 M4OSA_ERR err; 3846 Framing = (M4xVSS_FramingStruct *)((M4xVSS_FramingContext*)userData)->aFramingCtx; 3847 currentFraming = (M4xVSS_FramingStruct *)Framing; 3848 FramingRGB = Framing->FramingRgb->pac_data; 3849 #endif /*DECODE_GIF_ON_SAVING*/ 3850 /*end FB*/ 3851 3852 /** 3853 * Initialize input / output plane pointers */ 3854 p_in_Y += PlaneIn[0].u_topleft; 3855 p_in_U += PlaneIn[1].u_topleft; 3856 p_in_V += PlaneIn[2].u_topleft; 3857 3858 p_out0 = PlaneOut[0].pac_data; 3859 p_out1 = PlaneOut[1].pac_data; 3860 p_out2 = PlaneOut[2].pac_data; 3861 3862 /** 3863 * Depending on time, initialize Framing frame to use */ 3864 if(Framing->previousClipTime == -1) 3865 { 3866 Framing->previousClipTime = pProgress->uiOutputTime; 3867 } 3868 3869 /** 3870 * If the current clip time has reach the duration of one frame of the framing picture 3871 * we need to step to next framing picture */ 3872 3873 Framing->previousClipTime = pProgress->uiOutputTime; 3874 FramingRGB = currentFraming->FramingRgb->pac_data; 3875 topleft[0] = currentFraming->topleft_x; 3876 topleft[1] = currentFraming->topleft_y; 3877 3878 for( x=0 ;x < PlaneIn[0].u_height ; x++) 3879 { 3880 for( y=0 ;y < PlaneIn[0].u_width ; y++) 3881 { 3882 /** 3883 * To handle framing with input size != output size 3884 * Framing is applyed if coordinates matches between framing/topleft and input plane */ 3885 if( y < (topleft[0] + currentFraming->FramingYuv[0].u_width) && 3886 y >= topleft[0] && 3887 x < (topleft[1] + currentFraming->FramingYuv[0].u_height) && 3888 x >= topleft[1]) 3889 { 3890 /*Alpha blending support*/ 3891 M4OSA_Float alphaBlending = 1; 3892 M4xVSS_internalEffectsAlphaBlending* alphaBlendingStruct =\ 3893 (M4xVSS_internalEffectsAlphaBlending*)\ 3894 ((M4xVSS_FramingContext*)userData)->alphaBlendingStruct; 3895 3896 if(alphaBlendingStruct != M4OSA_NULL) 3897 { 3898 if(pProgress->uiProgress \ 3899 < (M4OSA_UInt32)(alphaBlendingStruct->m_fadeInTime*10)) 3900 { 3901 if(alphaBlendingStruct->m_fadeInTime == 0) { 3902 alphaBlending = alphaBlendingStruct->m_start / 100; 3903 } else { 3904 alphaBlending = ((M4OSA_Float)(alphaBlendingStruct->m_middle\ 3905 - alphaBlendingStruct->m_start)\ 3906 *pProgress->uiProgress/(alphaBlendingStruct->m_fadeInTime*10)); 3907 alphaBlending += alphaBlendingStruct->m_start; 3908 alphaBlending /= 100; 3909 } 3910 } 3911 else if(pProgress->uiProgress >= (M4OSA_UInt32)(alphaBlendingStruct->\ 3912 m_fadeInTime*10) && pProgress->uiProgress < 1000\ 3913 - (M4OSA_UInt32)(alphaBlendingStruct->m_fadeOutTime*10)) 3914 { 3915 alphaBlending = (M4OSA_Float)\ 3916 ((M4OSA_Float)alphaBlendingStruct->m_middle/100); 3917 } 3918 else if(pProgress->uiProgress >= 1000 - (M4OSA_UInt32)\ 3919 (alphaBlendingStruct->m_fadeOutTime*10)) 3920 { 3921 if(alphaBlendingStruct->m_fadeOutTime == 0) { 3922 alphaBlending = alphaBlendingStruct->m_end / 100; 3923 } else { 3924 alphaBlending = ((M4OSA_Float)(alphaBlendingStruct->m_middle \ 3925 - alphaBlendingStruct->m_end))*(1000 - pProgress->uiProgress)\ 3926 /(alphaBlendingStruct->m_fadeOutTime*10); 3927 alphaBlending += alphaBlendingStruct->m_end; 3928 alphaBlending /= 100; 3929 } 3930 } 3931 } 3932 /**/ 3933 3934 if((*(FramingRGB)==transparent1) && (*(FramingRGB+1)==transparent2)) 3935 { 3936 *( p_out0+y+x*PlaneOut[0].u_stride)=(*(p_in_Y+y+x*PlaneIn[0].u_stride)); 3937 *( p_out1+(y>>1)+(x>>1)*PlaneOut[1].u_stride)= 3938 (*(p_in_U+(y>>1)+(x>>1)*PlaneIn[1].u_stride)); 3939 *( p_out2+(y>>1)+(x>>1)*PlaneOut[2].u_stride)= 3940 (*(p_in_V+(y>>1)+(x>>1)*PlaneIn[2].u_stride)); 3941 } 3942 else 3943 { 3944 *( p_out0+y+x*PlaneOut[0].u_stride)= 3945 (*(currentFraming->FramingYuv[0].pac_data+(y-topleft[0])\ 3946 +(x-topleft[1])*currentFraming->FramingYuv[0].u_stride))*alphaBlending; 3947 *( p_out0+y+x*PlaneOut[0].u_stride)+= 3948 (*(p_in_Y+y+x*PlaneIn[0].u_stride))*(1-alphaBlending); 3949 *( p_out1+(y>>1)+(x>>1)*PlaneOut[1].u_stride)= 3950 (*(currentFraming->FramingYuv[1].pac_data+((y-topleft[0])>>1)\ 3951 +((x-topleft[1])>>1)*currentFraming->FramingYuv[1].u_stride))\ 3952 *alphaBlending; 3953 *( p_out1+(y>>1)+(x>>1)*PlaneOut[1].u_stride)+= 3954 (*(p_in_U+(y>>1)+(x>>1)*PlaneIn[1].u_stride))*(1-alphaBlending); 3955 *( p_out2+(y>>1)+(x>>1)*PlaneOut[2].u_stride)= 3956 (*(currentFraming->FramingYuv[2].pac_data+((y-topleft[0])>>1)\ 3957 +((x-topleft[1])>>1)*currentFraming->FramingYuv[2].u_stride))\ 3958 *alphaBlending; 3959 *( p_out2+(y>>1)+(x>>1)*PlaneOut[2].u_stride)+= 3960 (*(p_in_V+(y>>1)+(x>>1)*PlaneIn[2].u_stride))*(1-alphaBlending); 3961 } 3962 if( PlaneIn[0].u_width < (topleft[0] + currentFraming->FramingYuv[0].u_width) && 3963 y == PlaneIn[0].u_width-1) 3964 { 3965 FramingRGB = FramingRGB + 2 \ 3966 * (topleft[0] + currentFraming->FramingYuv[0].u_width \ 3967 - PlaneIn[0].u_width + 1); 3968 } 3969 else 3970 { 3971 FramingRGB = FramingRGB + 2; 3972 } 3973 } 3974 /** 3975 * Just copy input plane to output plane */ 3976 else 3977 { 3978 *( p_out0+y+x*PlaneOut[0].u_stride)=*(p_in_Y+y+x*PlaneIn[0].u_stride); 3979 *( p_out1+(y>>1)+(x>>1)*PlaneOut[1].u_stride)= 3980 *(p_in_U+(y>>1)+(x>>1)*PlaneIn[1].u_stride); 3981 *( p_out2+(y>>1)+(x>>1)*PlaneOut[2].u_stride)= 3982 *(p_in_V+(y>>1)+(x>>1)*PlaneIn[2].u_stride); 3983 } 3984 } 3985 } 3986 3987 3988 return M4VIFI_OK; 3989 } 3990 3991 3992 /** 3993 ****************************************************************************** 3994 * prototype M4VSS3GPP_externalVideoEffectFifties(M4OSA_Void *pFunctionContext, 3995 * M4VIFI_ImagePlane *PlaneIn, 3996 * M4VIFI_ImagePlane *PlaneOut, 3997 * M4VSS3GPP_ExternalProgress *pProgress, 3998 * M4OSA_UInt32 uiEffectKind) 3999 * 4000 * @brief This function make a video look as if it was taken in the fifties 4001 * @note 4002 * @param pUserData (IN) Context 4003 * @param pPlaneIn (IN) Input YUV420 planar 4004 * @param pPlaneOut (IN/OUT) Output YUV420 planar 4005 * @param pProgress (IN/OUT) Progress indication (0-100) 4006 * @param uiEffectKind (IN) Unused 4007 * 4008 * @return M4VIFI_OK: No error 4009 * @return M4ERR_PARAMETER: pFiftiesData, pPlaneOut or pProgress are NULL (DEBUG only) 4010 ****************************************************************************** 4011 */ 4012 M4OSA_ERR M4VSS3GPP_externalVideoEffectFifties( M4OSA_Void *pUserData, 4013 M4VIFI_ImagePlane *pPlaneIn, 4014 M4VIFI_ImagePlane *pPlaneOut, 4015 M4VSS3GPP_ExternalProgress *pProgress, 4016 M4OSA_UInt32 uiEffectKind ) 4017 { 4018 M4VIFI_UInt32 x, y, xShift; 4019 M4VIFI_UInt8 *pInY = pPlaneIn[0].pac_data; 4020 M4VIFI_UInt8 *pOutY, *pInYbegin; 4021 M4VIFI_UInt8 *pInCr,* pOutCr; 4022 M4VIFI_Int32 plane_number; 4023 4024 /* Internal context*/ 4025 M4xVSS_FiftiesStruct* p_FiftiesData = (M4xVSS_FiftiesStruct *)pUserData; 4026 4027 /* Check the inputs (debug only) */ 4028 M4OSA_DEBUG_IF2((p_FiftiesData == M4OSA_NULL),M4ERR_PARAMETER, 4029 "xVSS: p_FiftiesData is M4OSA_NULL in M4VSS3GPP_externalVideoEffectFifties"); 4030 M4OSA_DEBUG_IF2((pPlaneOut == M4OSA_NULL),M4ERR_PARAMETER, 4031 "xVSS: p_PlaneOut is M4OSA_NULL in M4VSS3GPP_externalVideoEffectFifties"); 4032 M4OSA_DEBUG_IF2((pProgress == M4OSA_NULL),M4ERR_PARAMETER, 4033 "xVSS: p_Progress is M4OSA_NULL in M4VSS3GPP_externalVideoEffectFifties"); 4034 4035 /* Initialize input / output plane pointers */ 4036 pInY += pPlaneIn[0].u_topleft; 4037 pOutY = pPlaneOut[0].pac_data; 4038 pInYbegin = pInY; 4039 4040 /* Initialize the random */ 4041 if(p_FiftiesData->previousClipTime < 0) 4042 { 4043 M4OSA_randInit(); 4044 M4OSA_rand((M4OSA_Int32 *)&(p_FiftiesData->shiftRandomValue), (pPlaneIn[0].u_height) >> 4); 4045 M4OSA_rand((M4OSA_Int32 *)&(p_FiftiesData->stripeRandomValue), (pPlaneIn[0].u_width)<< 2); 4046 p_FiftiesData->previousClipTime = pProgress->uiOutputTime; 4047 } 4048 4049 /* Choose random values if we have reached the duration of a partial effect */ 4050 else if( (pProgress->uiOutputTime - p_FiftiesData->previousClipTime)\ 4051 > p_FiftiesData->fiftiesEffectDuration) 4052 { 4053 M4OSA_rand((M4OSA_Int32 *)&(p_FiftiesData->shiftRandomValue), (pPlaneIn[0].u_height) >> 4); 4054 M4OSA_rand((M4OSA_Int32 *)&(p_FiftiesData->stripeRandomValue), (pPlaneIn[0].u_width)<< 2); 4055 p_FiftiesData->previousClipTime = pProgress->uiOutputTime; 4056 } 4057 4058 /* Put in Sepia the chrominance */ 4059 for (plane_number = 1; plane_number < 3; plane_number++) 4060 { 4061 pInCr = pPlaneIn[plane_number].pac_data + pPlaneIn[plane_number].u_topleft; 4062 pOutCr = pPlaneOut[plane_number].pac_data + pPlaneOut[plane_number].u_topleft; 4063 4064 for (x = 0; x < pPlaneOut[plane_number].u_height; x++) 4065 { 4066 if (1 == plane_number) 4067 memset((void *)pOutCr, 117,pPlaneIn[plane_number].u_width); /* U value */ 4068 else 4069 memset((void *)pOutCr, 139,pPlaneIn[plane_number].u_width); /* V value */ 4070 4071 pInCr += pPlaneIn[plane_number].u_stride; 4072 pOutCr += pPlaneOut[plane_number].u_stride; 4073 } 4074 } 4075 4076 /* Compute the new pixels values */ 4077 for( x = 0 ; x < pPlaneIn[0].u_height ; x++) 4078 { 4079 M4VIFI_UInt8 *p_outYtmp, *p_inYtmp; 4080 4081 /* Compute the xShift (random value) */ 4082 if (0 == (p_FiftiesData->shiftRandomValue % 5 )) 4083 xShift = (x + p_FiftiesData->shiftRandomValue ) % (pPlaneIn[0].u_height - 1); 4084 else 4085 xShift = (x + (pPlaneIn[0].u_height - p_FiftiesData->shiftRandomValue) ) \ 4086 % (pPlaneIn[0].u_height - 1); 4087 4088 /* Initialize the pointers */ 4089 p_outYtmp = pOutY + 1; /* yShift of 1 pixel */ 4090 p_inYtmp = pInYbegin + (xShift * pPlaneIn[0].u_stride); /* Apply the xShift */ 4091 4092 for( y = 0 ; y < pPlaneIn[0].u_width ; y++) 4093 { 4094 /* Set Y value */ 4095 if (xShift > (pPlaneIn[0].u_height - 4)) 4096 *p_outYtmp = 40; /* Add some horizontal black lines between the 4097 two parts of the image */ 4098 else if ( y == p_FiftiesData->stripeRandomValue) 4099 *p_outYtmp = 90; /* Add a random vertical line for the bulk */ 4100 else 4101 *p_outYtmp = *p_inYtmp; 4102 4103 4104 /* Go to the next pixel */ 4105 p_outYtmp++; 4106 p_inYtmp++; 4107 4108 /* Restart at the beginning of the line for the last pixel*/ 4109 if (y == (pPlaneIn[0].u_width - 2)) 4110 p_outYtmp = pOutY; 4111 } 4112 4113 /* Go to the next line */ 4114 pOutY += pPlaneOut[0].u_stride; 4115 } 4116 4117 return M4VIFI_OK; 4118 } 4119 4120 /** 4121 ****************************************************************************** 4122 * M4OSA_ERR M4VSS3GPP_externalVideoEffectZoom( ) 4123 * @brief Zoom in/out video effect functions. 4124 * @note The external video function is used only if VideoEffectType is set to 4125 * M4VSS3GPP_kVideoEffectType_ZoomIn or M4VSS3GPP_kVideoEffectType_ZoomOut. 4126 * 4127 * @param pFunctionContext (IN) The function context, previously set by the integrator 4128 * @param pInputPlanes (IN) Input YUV420 image: pointer to an array of three valid 4129 * image planes (Y, U and V) 4130 * @param pOutputPlanes (IN/OUT) Output (filtered) YUV420 image: pointer to an array of 4131 * three valid image planes (Y, U and V) 4132 * @param pProgress (IN) Set of information about the video transition progress. 4133 * @return M4NO_ERROR: No error 4134 * @return M4ERR_PARAMETER: At least one parameter is M4OSA_NULL (debug only) 4135 ****************************************************************************** 4136 */ 4137 4138 M4OSA_ERR M4VSS3GPP_externalVideoEffectZoom( 4139 M4OSA_Void *pFunctionContext, 4140 M4VIFI_ImagePlane *pInputPlanes, 4141 M4VIFI_ImagePlane *pOutputPlanes, 4142 M4VSS3GPP_ExternalProgress *pProgress, 4143 M4OSA_UInt32 uiEffectKind 4144 ) 4145 { 4146 M4OSA_UInt32 boxWidth; 4147 M4OSA_UInt32 boxHeight; 4148 M4OSA_UInt32 boxPosX; 4149 M4OSA_UInt32 boxPosY; 4150 M4OSA_UInt32 ratio = 0; 4151 /* * 1.189207 between ratio */ 4152 /* zoom between x1 and x16 */ 4153 M4OSA_UInt32 ratiotab[17] ={1024,1218,1448,1722,2048,2435,2896,3444,4096,4871,5793,\ 4154 6889,8192,9742,11585,13777,16384}; 4155 M4OSA_UInt32 ik; 4156 4157 M4VIFI_ImagePlane boxPlane[3]; 4158 4159 if(M4xVSS_kVideoEffectType_ZoomOut == (M4OSA_UInt32)pFunctionContext) 4160 { 4161 //ratio = 16 - (15 * pProgress->uiProgress)/1000; 4162 ratio = 16 - pProgress->uiProgress / 66 ; 4163 } 4164 else if(M4xVSS_kVideoEffectType_ZoomIn == (M4OSA_UInt32)pFunctionContext) 4165 { 4166 //ratio = 1 + (15 * pProgress->uiProgress)/1000; 4167 ratio = 1 + pProgress->uiProgress / 66 ; 4168 } 4169 4170 for(ik=0;ik<3;ik++){ 4171 4172 boxPlane[ik].u_stride = pInputPlanes[ik].u_stride; 4173 boxPlane[ik].pac_data = pInputPlanes[ik].pac_data; 4174 4175 boxHeight = ( pInputPlanes[ik].u_height << 10 ) / ratiotab[ratio]; 4176 boxWidth = ( pInputPlanes[ik].u_width << 10 ) / ratiotab[ratio]; 4177 boxPlane[ik].u_height = (boxHeight)&(~1); 4178 boxPlane[ik].u_width = (boxWidth)&(~1); 4179 4180 boxPosY = (pInputPlanes[ik].u_height >> 1) - (boxPlane[ik].u_height >> 1); 4181 boxPosX = (pInputPlanes[ik].u_width >> 1) - (boxPlane[ik].u_width >> 1); 4182 boxPlane[ik].u_topleft = boxPosY * boxPlane[ik].u_stride + boxPosX; 4183 } 4184 4185 M4VIFI_ResizeBilinearYUV420toYUV420(M4OSA_NULL, (M4VIFI_ImagePlane*)&boxPlane, pOutputPlanes); 4186 4187 /** 4188 * Return */ 4189 return(M4NO_ERROR); 4190 } 4191 4192 /** 4193 ****************************************************************************** 4194 * prototype M4xVSS_AlphaMagic( M4OSA_Void *userData, 4195 * M4VIFI_ImagePlane PlaneIn1[3], 4196 * M4VIFI_ImagePlane PlaneIn2[3], 4197 * M4VIFI_ImagePlane *PlaneOut, 4198 * M4VSS3GPP_ExternalProgress *pProgress, 4199 * M4OSA_UInt32 uiTransitionKind) 4200 * 4201 * @brief This function apply a color effect on an input YUV420 planar frame 4202 * @note 4203 * @param userData (IN) Contains a pointer on a settings structure 4204 * @param PlaneIn1 (IN) Input YUV420 planar from video 1 4205 * @param PlaneIn2 (IN) Input YUV420 planar from video 2 4206 * @param PlaneOut (IN/OUT) Output YUV420 planar 4207 * @param pProgress (IN/OUT) Progress indication (0-100) 4208 * @param uiTransitionKind(IN) Unused 4209 * 4210 * @return M4VIFI_OK: No error 4211 ****************************************************************************** 4212 */ 4213 M4OSA_ERR M4xVSS_AlphaMagic( M4OSA_Void *userData, M4VIFI_ImagePlane PlaneIn1[3], 4214 M4VIFI_ImagePlane PlaneIn2[3], M4VIFI_ImagePlane *PlaneOut, 4215 M4VSS3GPP_ExternalProgress *pProgress, M4OSA_UInt32 uiTransitionKind) 4216 { 4217 4218 M4OSA_ERR err; 4219 4220 M4xVSS_internal_AlphaMagicSettings* alphaContext; 4221 M4VIFI_Int32 alphaProgressLevel; 4222 4223 M4VIFI_ImagePlane* planeswap; 4224 M4VIFI_UInt32 x,y; 4225 4226 M4VIFI_UInt8 *p_out0; 4227 M4VIFI_UInt8 *p_out1; 4228 M4VIFI_UInt8 *p_out2; 4229 M4VIFI_UInt8 *alphaMask; 4230 /* "Old image" */ 4231 M4VIFI_UInt8 *p_in1_Y; 4232 M4VIFI_UInt8 *p_in1_U; 4233 M4VIFI_UInt8 *p_in1_V; 4234 /* "New image" */ 4235 M4VIFI_UInt8 *p_in2_Y; 4236 M4VIFI_UInt8 *p_in2_U; 4237 M4VIFI_UInt8 *p_in2_V; 4238 4239 err = M4NO_ERROR; 4240 4241 alphaContext = (M4xVSS_internal_AlphaMagicSettings*)userData; 4242 4243 alphaProgressLevel = (pProgress->uiProgress * 128)/1000; 4244 4245 if( alphaContext->isreverse != M4OSA_FALSE) 4246 { 4247 alphaProgressLevel = 128 - alphaProgressLevel; 4248 planeswap = PlaneIn1; 4249 PlaneIn1 = PlaneIn2; 4250 PlaneIn2 = planeswap; 4251 } 4252 4253 p_out0 = PlaneOut[0].pac_data; 4254 p_out1 = PlaneOut[1].pac_data; 4255 p_out2 = PlaneOut[2].pac_data; 4256 4257 alphaMask = alphaContext->pPlane->pac_data; 4258 4259 /* "Old image" */ 4260 p_in1_Y = PlaneIn1[0].pac_data; 4261 p_in1_U = PlaneIn1[1].pac_data; 4262 p_in1_V = PlaneIn1[2].pac_data; 4263 /* "New image" */ 4264 p_in2_Y = PlaneIn2[0].pac_data; 4265 p_in2_U = PlaneIn2[1].pac_data; 4266 p_in2_V = PlaneIn2[2].pac_data; 4267 4268 /** 4269 * For each column ... */ 4270 for( y=0; y<PlaneOut->u_height; y++ ) 4271 { 4272 /** 4273 * ... and each row of the alpha mask */ 4274 for( x=0; x<PlaneOut->u_width; x++ ) 4275 { 4276 /** 4277 * If the value of the current pixel of the alpha mask is > to the current time 4278 * ( current time is normalized on [0-255] ) */ 4279 if( alphaProgressLevel < alphaMask[x+y*PlaneOut->u_width] ) 4280 { 4281 /* We keep "old image" in output plane */ 4282 *( p_out0+x+y*PlaneOut[0].u_stride)=*(p_in1_Y+x+y*PlaneIn1[0].u_stride); 4283 *( p_out1+(x>>1)+(y>>1)*PlaneOut[1].u_stride)= 4284 *(p_in1_U+(x>>1)+(y>>1)*PlaneIn1[1].u_stride); 4285 *( p_out2+(x>>1)+(y>>1)*PlaneOut[2].u_stride)= 4286 *(p_in1_V+(x>>1)+(y>>1)*PlaneIn1[2].u_stride); 4287 } 4288 else 4289 { 4290 /* We take "new image" in output plane */ 4291 *( p_out0+x+y*PlaneOut[0].u_stride)=*(p_in2_Y+x+y*PlaneIn2[0].u_stride); 4292 *( p_out1+(x>>1)+(y>>1)*PlaneOut[1].u_stride)= 4293 *(p_in2_U+(x>>1)+(y>>1)*PlaneIn2[1].u_stride); 4294 *( p_out2+(x>>1)+(y>>1)*PlaneOut[2].u_stride)= 4295 *(p_in2_V+(x>>1)+(y>>1)*PlaneIn2[2].u_stride); 4296 } 4297 } 4298 } 4299 4300 return(err); 4301 } 4302 4303 /** 4304 ****************************************************************************** 4305 * prototype M4xVSS_AlphaMagicBlending( M4OSA_Void *userData, 4306 * M4VIFI_ImagePlane PlaneIn1[3], 4307 * M4VIFI_ImagePlane PlaneIn2[3], 4308 * M4VIFI_ImagePlane *PlaneOut, 4309 * M4VSS3GPP_ExternalProgress *pProgress, 4310 * M4OSA_UInt32 uiTransitionKind) 4311 * 4312 * @brief This function apply a color effect on an input YUV420 planar frame 4313 * @note 4314 * @param userData (IN) Contains a pointer on a settings structure 4315 * @param PlaneIn1 (IN) Input YUV420 planar from video 1 4316 * @param PlaneIn2 (IN) Input YUV420 planar from video 2 4317 * @param PlaneOut (IN/OUT) Output YUV420 planar 4318 * @param pProgress (IN/OUT) Progress indication (0-100) 4319 * @param uiTransitionKind(IN) Unused 4320 * 4321 * @return M4VIFI_OK: No error 4322 ****************************************************************************** 4323 */ 4324 M4OSA_ERR M4xVSS_AlphaMagicBlending( M4OSA_Void *userData, M4VIFI_ImagePlane PlaneIn1[3], 4325 M4VIFI_ImagePlane PlaneIn2[3], M4VIFI_ImagePlane *PlaneOut, 4326 M4VSS3GPP_ExternalProgress *pProgress, 4327 M4OSA_UInt32 uiTransitionKind) 4328 { 4329 M4OSA_ERR err; 4330 4331 M4xVSS_internal_AlphaMagicSettings* alphaContext; 4332 M4VIFI_Int32 alphaProgressLevel; 4333 M4VIFI_Int32 alphaBlendLevelMin; 4334 M4VIFI_Int32 alphaBlendLevelMax; 4335 M4VIFI_Int32 alphaBlendRange; 4336 4337 M4VIFI_ImagePlane* planeswap; 4338 M4VIFI_UInt32 x,y; 4339 M4VIFI_Int32 alphaMaskValue; 4340 4341 M4VIFI_UInt8 *p_out0; 4342 M4VIFI_UInt8 *p_out1; 4343 M4VIFI_UInt8 *p_out2; 4344 M4VIFI_UInt8 *alphaMask; 4345 /* "Old image" */ 4346 M4VIFI_UInt8 *p_in1_Y; 4347 M4VIFI_UInt8 *p_in1_U; 4348 M4VIFI_UInt8 *p_in1_V; 4349 /* "New image" */ 4350 M4VIFI_UInt8 *p_in2_Y; 4351 M4VIFI_UInt8 *p_in2_U; 4352 M4VIFI_UInt8 *p_in2_V; 4353 4354 4355 err = M4NO_ERROR; 4356 4357 alphaContext = (M4xVSS_internal_AlphaMagicSettings*)userData; 4358 4359 alphaProgressLevel = (pProgress->uiProgress * 128)/1000; 4360 4361 if( alphaContext->isreverse != M4OSA_FALSE) 4362 { 4363 alphaProgressLevel = 128 - alphaProgressLevel; 4364 planeswap = PlaneIn1; 4365 PlaneIn1 = PlaneIn2; 4366 PlaneIn2 = planeswap; 4367 } 4368 4369 alphaBlendLevelMin = alphaProgressLevel-alphaContext->blendingthreshold; 4370 4371 alphaBlendLevelMax = alphaProgressLevel+alphaContext->blendingthreshold; 4372 4373 alphaBlendRange = (alphaContext->blendingthreshold)*2; 4374 4375 p_out0 = PlaneOut[0].pac_data; 4376 p_out1 = PlaneOut[1].pac_data; 4377 p_out2 = PlaneOut[2].pac_data; 4378 4379 alphaMask = alphaContext->pPlane->pac_data; 4380 4381 /* "Old image" */ 4382 p_in1_Y = PlaneIn1[0].pac_data; 4383 p_in1_U = PlaneIn1[1].pac_data; 4384 p_in1_V = PlaneIn1[2].pac_data; 4385 /* "New image" */ 4386 p_in2_Y = PlaneIn2[0].pac_data; 4387 p_in2_U = PlaneIn2[1].pac_data; 4388 p_in2_V = PlaneIn2[2].pac_data; 4389 4390 /* apply Alpha Magic on each pixel */ 4391 for( y=0; y<PlaneOut->u_height; y++ ) 4392 { 4393 for( x=0; x<PlaneOut->u_width; x++ ) 4394 { 4395 alphaMaskValue = alphaMask[x+y*PlaneOut->u_width]; 4396 if( alphaBlendLevelMax < alphaMaskValue ) 4397 { 4398 /* We keep "old image" in output plane */ 4399 *( p_out0+x+y*PlaneOut[0].u_stride)=*(p_in1_Y+x+y*PlaneIn1[0].u_stride); 4400 *( p_out1+(x>>1)+(y>>1)*PlaneOut[1].u_stride)= 4401 *(p_in1_U+(x>>1)+(y>>1)*PlaneIn1[1].u_stride); 4402 *( p_out2+(x>>1)+(y>>1)*PlaneOut[2].u_stride)= 4403 *(p_in1_V+(x>>1)+(y>>1)*PlaneIn1[2].u_stride); 4404 } 4405 else if( (alphaBlendLevelMin < alphaMaskValue)&& 4406 (alphaMaskValue <= alphaBlendLevelMax ) ) 4407 { 4408 /* We blend "old and new image" in output plane */ 4409 *( p_out0+x+y*PlaneOut[0].u_stride)=(M4VIFI_UInt8) 4410 (( (alphaMaskValue-alphaBlendLevelMin)*( *(p_in1_Y+x+y*PlaneIn1[0].u_stride)) 4411 +(alphaBlendLevelMax-alphaMaskValue)\ 4412 *( *(p_in2_Y+x+y*PlaneIn2[0].u_stride)) )/alphaBlendRange ); 4413 4414 *( p_out1+(x>>1)+(y>>1)*PlaneOut[1].u_stride)=(M4VIFI_UInt8)\ 4415 (( (alphaMaskValue-alphaBlendLevelMin)*( *(p_in1_U+(x>>1)+(y>>1)\ 4416 *PlaneIn1[1].u_stride)) 4417 +(alphaBlendLevelMax-alphaMaskValue)*( *(p_in2_U+(x>>1)+(y>>1)\ 4418 *PlaneIn2[1].u_stride)) )/alphaBlendRange ); 4419 4420 *( p_out2+(x>>1)+(y>>1)*PlaneOut[2].u_stride)= 4421 (M4VIFI_UInt8)(( (alphaMaskValue-alphaBlendLevelMin)\ 4422 *( *(p_in1_V+(x>>1)+(y>>1)*PlaneIn1[2].u_stride)) 4423 +(alphaBlendLevelMax-alphaMaskValue)*( *(p_in2_V+(x>>1)+(y>>1)\ 4424 *PlaneIn2[2].u_stride)) )/alphaBlendRange ); 4425 4426 } 4427 else 4428 { 4429 /* We take "new image" in output plane */ 4430 *( p_out0+x+y*PlaneOut[0].u_stride)=*(p_in2_Y+x+y*PlaneIn2[0].u_stride); 4431 *( p_out1+(x>>1)+(y>>1)*PlaneOut[1].u_stride)= 4432 *(p_in2_U+(x>>1)+(y>>1)*PlaneIn2[1].u_stride); 4433 *( p_out2+(x>>1)+(y>>1)*PlaneOut[2].u_stride)= 4434 *(p_in2_V+(x>>1)+(y>>1)*PlaneIn2[2].u_stride); 4435 } 4436 } 4437 } 4438 4439 return(err); 4440 } 4441 4442 #define M4XXX_SampleAddress(plane, x, y) ( (plane).pac_data + (plane).u_topleft + (y)\ 4443 * (plane).u_stride + (x) ) 4444 4445 static void M4XXX_CopyPlane(M4VIFI_ImagePlane* dest, M4VIFI_ImagePlane* source) 4446 { 4447 M4OSA_UInt32 height, width, sourceStride, destStride, y; 4448 M4OSA_MemAddr8 sourceWalk, destWalk; 4449 4450 /* cache the vars used in the loop so as to avoid them being repeatedly fetched and 4451 recomputed from memory. */ 4452 height = dest->u_height; 4453 width = dest->u_width; 4454 4455 sourceWalk = (M4OSA_MemAddr8)M4XXX_SampleAddress(*source, 0, 0); 4456 sourceStride = source->u_stride; 4457 4458 destWalk = (M4OSA_MemAddr8)M4XXX_SampleAddress(*dest, 0, 0); 4459 destStride = dest->u_stride; 4460 4461 for (y=0; y<height; y++) 4462 { 4463 memcpy((void *)destWalk, (void *)sourceWalk, width); 4464 destWalk += destStride; 4465 sourceWalk += sourceStride; 4466 } 4467 } 4468 4469 static M4OSA_ERR M4xVSS_VerticalSlideTransition(M4VIFI_ImagePlane* topPlane, 4470 M4VIFI_ImagePlane* bottomPlane, 4471 M4VIFI_ImagePlane *PlaneOut, 4472 M4OSA_UInt32 shiftUV) 4473 { 4474 M4OSA_UInt32 i; 4475 4476 /* Do three loops, one for each plane type, in order to avoid having too many buffers 4477 "hot" at the same time (better for cache). */ 4478 for (i=0; i<3; i++) 4479 { 4480 M4OSA_UInt32 topPartHeight, bottomPartHeight, width, sourceStride, destStride, y; 4481 M4OSA_MemAddr8 sourceWalk, destWalk; 4482 4483 /* cache the vars used in the loop so as to avoid them being repeatedly fetched and 4484 recomputed from memory. */ 4485 if (0 == i) /* Y plane */ 4486 { 4487 bottomPartHeight = 2*shiftUV; 4488 } 4489 else /* U and V planes */ 4490 { 4491 bottomPartHeight = shiftUV; 4492 } 4493 topPartHeight = PlaneOut[i].u_height - bottomPartHeight; 4494 width = PlaneOut[i].u_width; 4495 4496 sourceWalk = (M4OSA_MemAddr8)M4XXX_SampleAddress(topPlane[i], 0, bottomPartHeight); 4497 sourceStride = topPlane[i].u_stride; 4498 4499 destWalk = (M4OSA_MemAddr8)M4XXX_SampleAddress(PlaneOut[i], 0, 0); 4500 destStride = PlaneOut[i].u_stride; 4501 4502 /* First the part from the top source clip frame. */ 4503 for (y=0; y<topPartHeight; y++) 4504 { 4505 memcpy((void *)destWalk, (void *)sourceWalk, width); 4506 destWalk += destStride; 4507 sourceWalk += sourceStride; 4508 } 4509 4510 /* and now change the vars to copy the part from the bottom source clip frame. */ 4511 sourceWalk = (M4OSA_MemAddr8)M4XXX_SampleAddress(bottomPlane[i], 0, 0); 4512 sourceStride = bottomPlane[i].u_stride; 4513 4514 /* destWalk is already at M4XXX_SampleAddress(PlaneOut[i], 0, topPartHeight) */ 4515 4516 for (y=0; y<bottomPartHeight; y++) 4517 { 4518 memcpy((void *)destWalk, (void *)sourceWalk, width); 4519 destWalk += destStride; 4520 sourceWalk += sourceStride; 4521 } 4522 } 4523 return M4NO_ERROR; 4524 } 4525 4526 static M4OSA_ERR M4xVSS_HorizontalSlideTransition(M4VIFI_ImagePlane* leftPlane, 4527 M4VIFI_ImagePlane* rightPlane, 4528 M4VIFI_ImagePlane *PlaneOut, 4529 M4OSA_UInt32 shiftUV) 4530 { 4531 M4OSA_UInt32 i, y; 4532 /* If we shifted by exactly 0, or by the width of the target image, then we would get the left 4533 frame or the right frame, respectively. These cases aren't handled too well by the general 4534 handling, since they result in 0-size memcopies, so might as well particularize them. */ 4535 4536 if (0 == shiftUV) /* output left frame */ 4537 { 4538 for (i = 0; i<3; i++) /* for each YUV plane */ 4539 { 4540 M4XXX_CopyPlane(&(PlaneOut[i]), &(leftPlane[i])); 4541 } 4542 4543 return M4NO_ERROR; 4544 } 4545 4546 if (PlaneOut[1].u_width == shiftUV) /* output right frame */ 4547 { 4548 for (i = 0; i<3; i++) /* for each YUV plane */ 4549 { 4550 M4XXX_CopyPlane(&(PlaneOut[i]), &(rightPlane[i])); 4551 } 4552 4553 return M4NO_ERROR; 4554 } 4555 4556 4557 /* Do three loops, one for each plane type, in order to avoid having too many buffers 4558 "hot" at the same time (better for cache). */ 4559 for (i=0; i<3; i++) 4560 { 4561 M4OSA_UInt32 height, leftPartWidth, rightPartWidth; 4562 M4OSA_UInt32 leftStride, rightStride, destStride; 4563 M4OSA_MemAddr8 leftWalk, rightWalk, destWalkLeft, destWalkRight; 4564 4565 /* cache the vars used in the loop so as to avoid them being repeatedly fetched 4566 and recomputed from memory. */ 4567 height = PlaneOut[i].u_height; 4568 4569 if (0 == i) /* Y plane */ 4570 { 4571 rightPartWidth = 2*shiftUV; 4572 } 4573 else /* U and V planes */ 4574 { 4575 rightPartWidth = shiftUV; 4576 } 4577 leftPartWidth = PlaneOut[i].u_width - rightPartWidth; 4578 4579 leftWalk = (M4OSA_MemAddr8)M4XXX_SampleAddress(leftPlane[i], rightPartWidth, 0); 4580 leftStride = leftPlane[i].u_stride; 4581 4582 rightWalk = (M4OSA_MemAddr8)M4XXX_SampleAddress(rightPlane[i], 0, 0); 4583 rightStride = rightPlane[i].u_stride; 4584 4585 destWalkLeft = (M4OSA_MemAddr8)M4XXX_SampleAddress(PlaneOut[i], 0, 0); 4586 destWalkRight = (M4OSA_MemAddr8)M4XXX_SampleAddress(PlaneOut[i], leftPartWidth, 0); 4587 destStride = PlaneOut[i].u_stride; 4588 4589 for (y=0; y<height; y++) 4590 { 4591 memcpy((void *)destWalkLeft, (void *)leftWalk, leftPartWidth); 4592 leftWalk += leftStride; 4593 4594 memcpy((void *)destWalkRight, (void *)rightWalk, rightPartWidth); 4595 rightWalk += rightStride; 4596 4597 destWalkLeft += destStride; 4598 destWalkRight += destStride; 4599 } 4600 } 4601 4602 return M4NO_ERROR; 4603 } 4604 4605 4606 M4OSA_ERR M4xVSS_SlideTransition( M4OSA_Void *userData, M4VIFI_ImagePlane PlaneIn1[3], 4607 M4VIFI_ImagePlane PlaneIn2[3], M4VIFI_ImagePlane *PlaneOut, 4608 M4VSS3GPP_ExternalProgress *pProgress, 4609 M4OSA_UInt32 uiTransitionKind) 4610 { 4611 M4xVSS_internal_SlideTransitionSettings* settings = 4612 (M4xVSS_internal_SlideTransitionSettings*)userData; 4613 M4OSA_UInt32 shiftUV; 4614 4615 M4OSA_TRACE1_0("inside M4xVSS_SlideTransition"); 4616 if ((M4xVSS_SlideTransition_RightOutLeftIn == settings->direction) 4617 || (M4xVSS_SlideTransition_LeftOutRightIn == settings->direction) ) 4618 { 4619 /* horizontal slide */ 4620 shiftUV = ((PlaneOut[1]).u_width * pProgress->uiProgress)/1000; 4621 M4OSA_TRACE1_2("M4xVSS_SlideTransition upper: shiftUV = %d,progress = %d", 4622 shiftUV,pProgress->uiProgress ); 4623 if (M4xVSS_SlideTransition_RightOutLeftIn == settings->direction) 4624 { 4625 /* Put the previous clip frame right, the next clip frame left, and reverse shiftUV 4626 (since it's a shift from the left frame) so that we start out on the right 4627 (i.e. not left) frame, it 4628 being from the previous clip. */ 4629 return M4xVSS_HorizontalSlideTransition(PlaneIn2, PlaneIn1, PlaneOut, 4630 (PlaneOut[1]).u_width - shiftUV); 4631 } 4632 else /* Left out, right in*/ 4633 { 4634 return M4xVSS_HorizontalSlideTransition(PlaneIn1, PlaneIn2, PlaneOut, shiftUV); 4635 } 4636 } 4637 else 4638 { 4639 /* vertical slide */ 4640 shiftUV = ((PlaneOut[1]).u_height * pProgress->uiProgress)/1000; 4641 M4OSA_TRACE1_2("M4xVSS_SlideTransition bottom: shiftUV = %d,progress = %d",shiftUV, 4642 pProgress->uiProgress ); 4643 if (M4xVSS_SlideTransition_TopOutBottomIn == settings->direction) 4644 { 4645 /* Put the previous clip frame top, the next clip frame bottom. */ 4646 return M4xVSS_VerticalSlideTransition(PlaneIn1, PlaneIn2, PlaneOut, shiftUV); 4647 } 4648 else /* Bottom out, top in */ 4649 { 4650 return M4xVSS_VerticalSlideTransition(PlaneIn2, PlaneIn1, PlaneOut, 4651 (PlaneOut[1]).u_height - shiftUV); 4652 } 4653 } 4654 4655 /* Note: it might be worthwhile to do some parameter checking, see if dimensions match, etc., 4656 at least in debug mode. */ 4657 } 4658 4659 4660 /** 4661 ****************************************************************************** 4662 * prototype M4xVSS_FadeBlackTransition(M4OSA_Void *pFunctionContext, 4663 * M4VIFI_ImagePlane *PlaneIn, 4664 * M4VIFI_ImagePlane *PlaneOut, 4665 * M4VSS3GPP_ExternalProgress *pProgress, 4666 * M4OSA_UInt32 uiEffectKind) 4667 * 4668 * @brief This function apply a fade to black and then a fade from black 4669 * @note 4670 * @param pFunctionContext(IN) Contains which color to apply (not very clean ...) 4671 * @param PlaneIn (IN) Input YUV420 planar 4672 * @param PlaneOut (IN/OUT) Output YUV420 planar 4673 * @param pProgress (IN/OUT) Progress indication (0-100) 4674 * @param uiEffectKind (IN) Unused 4675 * 4676 * @return M4VIFI_OK: No error 4677 ****************************************************************************** 4678 */ 4679 M4OSA_ERR M4xVSS_FadeBlackTransition(M4OSA_Void *userData, M4VIFI_ImagePlane PlaneIn1[3], 4680 M4VIFI_ImagePlane PlaneIn2[3], 4681 M4VIFI_ImagePlane *PlaneOut, 4682 M4VSS3GPP_ExternalProgress *pProgress, 4683 M4OSA_UInt32 uiTransitionKind) 4684 { 4685 M4OSA_Int32 tmp = 0; 4686 M4OSA_ERR err = M4NO_ERROR; 4687 4688 4689 if((pProgress->uiProgress) < 500) 4690 { 4691 /** 4692 * Compute where we are in the effect (scale is 0->1024) */ 4693 tmp = (M4OSA_Int32)((1.0 - ((M4OSA_Float)(pProgress->uiProgress*2)/1000)) * 1024 ); 4694 4695 /** 4696 * Apply the darkening effect */ 4697 err = M4VFL_modifyLumaWithScale( (M4ViComImagePlane*)PlaneIn1, 4698 (M4ViComImagePlane*)PlaneOut, tmp, M4OSA_NULL); 4699 if (M4NO_ERROR != err) 4700 { 4701 M4OSA_TRACE1_1("M4xVSS_FadeBlackTransition: M4VFL_modifyLumaWithScale returns\ 4702 error 0x%x, returning M4VSS3GPP_ERR_LUMA_FILTER_ERROR", err); 4703 return M4VSS3GPP_ERR_LUMA_FILTER_ERROR; 4704 } 4705 } 4706 else 4707 { 4708 /** 4709 * Compute where we are in the effect (scale is 0->1024). */ 4710 tmp = (M4OSA_Int32)( (((M4OSA_Float)(((pProgress->uiProgress-500)*2))/1000)) * 1024 ); 4711 4712 /** 4713 * Apply the darkening effect */ 4714 err = M4VFL_modifyLumaWithScale((M4ViComImagePlane*)PlaneIn2, 4715 (M4ViComImagePlane*)PlaneOut, tmp, M4OSA_NULL); 4716 if (M4NO_ERROR != err) 4717 { 4718 M4OSA_TRACE1_1("M4xVSS_FadeBlackTransition:\ 4719 M4VFL_modifyLumaWithScale returns error 0x%x,\ 4720 returning M4VSS3GPP_ERR_LUMA_FILTER_ERROR", err); 4721 return M4VSS3GPP_ERR_LUMA_FILTER_ERROR; 4722 } 4723 } 4724 4725 4726 return M4VIFI_OK; 4727 } 4728 4729 4730 /** 4731 ****************************************************************************** 4732 * prototype M4OSA_ERR M4xVSS_internalConvertToUTF8(M4OSA_Context pContext, 4733 * M4OSA_Void* pBufferIn, 4734 * M4OSA_Void* pBufferOut, 4735 * M4OSA_UInt32* convertedSize) 4736 * 4737 * @brief This function convert from the customer format to UTF8 4738 * @note 4739 * @param pContext (IN) The integrator own context 4740 * @param pBufferIn (IN) Buffer to convert 4741 * @param pBufferOut (OUT) Converted buffer 4742 * @param convertedSize (OUT) Size of the converted buffer 4743 * 4744 * @return M4NO_ERROR: No error 4745 * @return M4ERR_PARAMETER: At least one of the function parameters is null 4746 ****************************************************************************** 4747 */ 4748 M4OSA_ERR M4xVSS_internalConvertToUTF8(M4OSA_Context pContext, M4OSA_Void* pBufferIn, 4749 M4OSA_Void* pBufferOut, M4OSA_UInt32* convertedSize) 4750 { 4751 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 4752 M4OSA_ERR err; 4753 4754 pBufferOut = pBufferIn; 4755 if(xVSS_context->UTFConversionContext.pConvToUTF8Fct != M4OSA_NULL 4756 && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL) 4757 { 4758 M4OSA_UInt32 ConvertedSize = xVSS_context->UTFConversionContext.m_TempOutConversionSize; 4759 4760 memset((void *)xVSS_context->UTFConversionContext.pTempOutConversionBuffer,0 4761 ,(M4OSA_UInt32)xVSS_context->UTFConversionContext.m_TempOutConversionSize); 4762 4763 err = xVSS_context->UTFConversionContext.pConvToUTF8Fct((M4OSA_Void*)pBufferIn, 4764 (M4OSA_UInt8*)xVSS_context->UTFConversionContext.pTempOutConversionBuffer, 4765 (M4OSA_UInt32*)&ConvertedSize); 4766 if(err == M4xVSSWAR_BUFFER_OUT_TOO_SMALL) 4767 { 4768 M4OSA_TRACE2_1("M4xVSS_internalConvertToUTF8: pConvToUTF8Fct return 0x%x",err); 4769 4770 /*free too small buffer*/ 4771 free(xVSS_context->\ 4772 UTFConversionContext.pTempOutConversionBuffer); 4773 4774 /*re-allocate the buffer*/ 4775 xVSS_context->UTFConversionContext.pTempOutConversionBuffer = 4776 (M4OSA_Void*)M4OSA_32bitAlignedMalloc(ConvertedSize*sizeof(M4OSA_UInt8), M4VA, 4777 (M4OSA_Char *)"M4xVSS_internalConvertToUTF8: UTF conversion buffer"); 4778 if(M4OSA_NULL == xVSS_context->UTFConversionContext.pTempOutConversionBuffer) 4779 { 4780 M4OSA_TRACE1_0("Allocation error in M4xVSS_internalConvertToUTF8"); 4781 return M4ERR_ALLOC; 4782 } 4783 xVSS_context->UTFConversionContext.m_TempOutConversionSize = ConvertedSize; 4784 4785 memset((void *)xVSS_context->\ 4786 UTFConversionContext.pTempOutConversionBuffer,0,(M4OSA_UInt32)xVSS_context->\ 4787 UTFConversionContext.m_TempOutConversionSize); 4788 4789 err = xVSS_context->UTFConversionContext.pConvToUTF8Fct((M4OSA_Void*)pBufferIn, 4790 (M4OSA_Void*)xVSS_context->UTFConversionContext.pTempOutConversionBuffer, 4791 (M4OSA_UInt32*)&ConvertedSize); 4792 if(err != M4NO_ERROR) 4793 { 4794 M4OSA_TRACE1_1("M4xVSS_internalConvertToUTF8: pConvToUTF8Fct return 0x%x",err); 4795 return err; 4796 } 4797 } 4798 else if(err != M4NO_ERROR) 4799 { 4800 M4OSA_TRACE1_1("M4xVSS_internalConvertToUTF8: pConvToUTF8Fct return 0x%x",err); 4801 return err; 4802 } 4803 /*decoded path*/ 4804 pBufferOut = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; 4805 (*convertedSize) = ConvertedSize; 4806 } 4807 return M4NO_ERROR; 4808 } 4809 4810 4811 /** 4812 ****************************************************************************** 4813 * prototype M4OSA_ERR M4xVSS_internalConvertFromUTF8(M4OSA_Context pContext) 4814 * 4815 * @brief This function convert from UTF8 to the customer format 4816 * @note 4817 * @param pContext (IN) The integrator own context 4818 * @param pBufferIn (IN) Buffer to convert 4819 * @param pBufferOut (OUT) Converted buffer 4820 * @param convertedSize (OUT) Size of the converted buffer 4821 * 4822 * @return M4NO_ERROR: No error 4823 * @return M4ERR_PARAMETER: At least one of the function parameters is null 4824 ****************************************************************************** 4825 */ 4826 M4OSA_ERR M4xVSS_internalConvertFromUTF8(M4OSA_Context pContext, M4OSA_Void* pBufferIn, 4827 M4OSA_Void* pBufferOut, M4OSA_UInt32* convertedSize) 4828 { 4829 M4xVSS_Context* xVSS_context = (M4xVSS_Context*)pContext; 4830 M4OSA_ERR err; 4831 4832 pBufferOut = pBufferIn; 4833 if(xVSS_context->UTFConversionContext.pConvFromUTF8Fct != M4OSA_NULL 4834 && xVSS_context->UTFConversionContext.pTempOutConversionBuffer != M4OSA_NULL) 4835 { 4836 M4OSA_UInt32 ConvertedSize = xVSS_context->UTFConversionContext.m_TempOutConversionSize; 4837 4838 memset((void *)xVSS_context->\ 4839 UTFConversionContext.pTempOutConversionBuffer,0,(M4OSA_UInt32)xVSS_context->\ 4840 UTFConversionContext.m_TempOutConversionSize); 4841 4842 err = xVSS_context->UTFConversionContext.pConvFromUTF8Fct\ 4843 ((M4OSA_Void*)pBufferIn,(M4OSA_UInt8*)xVSS_context->\ 4844 UTFConversionContext.pTempOutConversionBuffer, (M4OSA_UInt32*)&ConvertedSize); 4845 if(err == M4xVSSWAR_BUFFER_OUT_TOO_SMALL) 4846 { 4847 M4OSA_TRACE2_1("M4xVSS_internalConvertFromUTF8: pConvFromUTF8Fct return 0x%x",err); 4848 4849 /*free too small buffer*/ 4850 free(xVSS_context->\ 4851 UTFConversionContext.pTempOutConversionBuffer); 4852 4853 /*re-allocate the buffer*/ 4854 xVSS_context->UTFConversionContext.pTempOutConversionBuffer = 4855 (M4OSA_Void*)M4OSA_32bitAlignedMalloc(ConvertedSize*sizeof(M4OSA_UInt8), M4VA, 4856 (M4OSA_Char *)"M4xVSS_internalConvertFromUTF8: UTF conversion buffer"); 4857 if(M4OSA_NULL == xVSS_context->UTFConversionContext.pTempOutConversionBuffer) 4858 { 4859 M4OSA_TRACE1_0("Allocation error in M4xVSS_internalConvertFromUTF8"); 4860 return M4ERR_ALLOC; 4861 } 4862 xVSS_context->UTFConversionContext.m_TempOutConversionSize = ConvertedSize; 4863 4864 memset((void *)xVSS_context->\ 4865 UTFConversionContext.pTempOutConversionBuffer,0,(M4OSA_UInt32)xVSS_context->\ 4866 UTFConversionContext.m_TempOutConversionSize); 4867 4868 err = xVSS_context->UTFConversionContext.pConvFromUTF8Fct((M4OSA_Void*)pBufferIn, 4869 (M4OSA_Void*)xVSS_context->UTFConversionContext.pTempOutConversionBuffer, 4870 (M4OSA_UInt32*)&ConvertedSize); 4871 if(err != M4NO_ERROR) 4872 { 4873 M4OSA_TRACE1_1("M4xVSS_internalConvertFromUTF8: pConvFromUTF8Fct return 0x%x",err); 4874 return err; 4875 } 4876 } 4877 else if(err != M4NO_ERROR) 4878 { 4879 M4OSA_TRACE1_1("M4xVSS_internalConvertFromUTF8: pConvFromUTF8Fct return 0x%x",err); 4880 return err; 4881 } 4882 /*decoded path*/ 4883 pBufferOut = xVSS_context->UTFConversionContext.pTempOutConversionBuffer; 4884 (*convertedSize) = ConvertedSize; 4885 } 4886 4887 4888 return M4NO_ERROR; 4889 } 4890