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 M4VSS3GPP_EditVideo.c 19 * @brief Video Studio Service 3GPP edit API implementation. 20 * @note 21 ****************************************************************************** 22 */ 23 #undef M4OSA_TRACE_LEVEL 24 #define M4OSA_TRACE_LEVEL 1 25 26 /****************/ 27 /*** Includes ***/ 28 /****************/ 29 30 #include "NXPSW_CompilerSwitches.h" 31 /** 32 * Our header */ 33 #include "M4VSS3GPP_API.h" 34 #include "M4VSS3GPP_InternalTypes.h" 35 #include "M4VSS3GPP_InternalFunctions.h" 36 #include "M4VSS3GPP_InternalConfig.h" 37 #include "M4VSS3GPP_ErrorCodes.h" 38 39 // StageFright encoders require %16 resolution 40 #include "M4ENCODER_common.h" 41 /** 42 * OSAL headers */ 43 #include "M4OSA_Memory.h" /**< OSAL memory management */ 44 #include "M4OSA_Debug.h" /**< OSAL debug management */ 45 46 /** 47 * component includes */ 48 #include "M4VFL_transition.h" /**< video effects */ 49 50 /*for transition behaviour*/ 51 #include <math.h> 52 #include "M4AIR_API.h" 53 #include "M4VSS3GPP_Extended_API.h" 54 /** Determine absolute value of a. */ 55 #define M4xVSS_ABS(a) ( ( (a) < (0) ) ? (-(a)) : (a) ) 56 #define Y_PLANE_BORDER_VALUE 0x00 57 #define U_PLANE_BORDER_VALUE 0x80 58 #define V_PLANE_BORDER_VALUE 0x80 59 60 /************************************************************************/ 61 /* Static local functions */ 62 /************************************************************************/ 63 64 static M4OSA_ERR M4VSS3GPP_intCheckVideoMode( 65 M4VSS3GPP_InternalEditContext *pC ); 66 static M4OSA_Void 67 M4VSS3GPP_intCheckVideoEffects( M4VSS3GPP_InternalEditContext *pC, 68 M4OSA_UInt8 uiClipNumber ); 69 static M4OSA_ERR M4VSS3GPP_intApplyVideoEffect( 70 M4VSS3GPP_InternalEditContext *pC, M4VIFI_ImagePlane *pPlaneIn, 71 M4VIFI_ImagePlane *pPlaneOut, M4OSA_Bool bSkipFramingEffect); 72 73 static M4OSA_ERR 74 M4VSS3GPP_intVideoTransition( M4VSS3GPP_InternalEditContext *pC, 75 M4VIFI_ImagePlane *pPlaneOut ); 76 77 static M4OSA_Void 78 M4VSS3GPP_intUpdateTimeInfo( M4VSS3GPP_InternalEditContext *pC, 79 M4SYS_AccessUnit *pAU ); 80 static M4OSA_Void M4VSS3GPP_intSetH263TimeCounter( M4OSA_MemAddr8 pAuDataBuffer, 81 M4OSA_UInt8 uiCts ); 82 static M4OSA_Void M4VSS3GPP_intSetMPEG4Gov( M4OSA_MemAddr8 pAuDataBuffer, 83 M4OSA_UInt32 uiCtsSec ); 84 static M4OSA_Void M4VSS3GPP_intGetMPEG4Gov( M4OSA_MemAddr8 pAuDataBuffer, 85 M4OSA_UInt32 *pCtsSec ); 86 static M4OSA_ERR M4VSS3GPP_intAllocateYUV420( M4VIFI_ImagePlane *pPlanes, 87 M4OSA_UInt32 uiWidth, M4OSA_UInt32 uiHeight ); 88 static M4OSA_ERR M4VSS3GPP_internalConvertAndResizeARGB8888toYUV420( 89 M4OSA_Void* pFileIn, M4OSA_FileReadPointer* pFileReadPtr, 90 M4VIFI_ImagePlane* pImagePlanes, 91 M4OSA_UInt32 width,M4OSA_UInt32 height); 92 static M4OSA_ERR M4VSS3GPP_intApplyRenderingMode( 93 M4VSS3GPP_InternalEditContext *pC, 94 M4xVSS_MediaRendering renderingMode, 95 M4VIFI_ImagePlane* pInplane, 96 M4VIFI_ImagePlane* pOutplane); 97 98 static M4OSA_ERR M4VSS3GPP_intSetYuv420PlaneFromARGB888 ( 99 M4VSS3GPP_InternalEditContext *pC, 100 M4VSS3GPP_ClipContext* pClipCtxt); 101 static M4OSA_ERR M4VSS3GPP_intRenderFrameWithEffect( 102 M4VSS3GPP_InternalEditContext *pC, 103 M4VSS3GPP_ClipContext* pClipCtxt, 104 M4_MediaTime ts, 105 M4OSA_Bool bIsClip1, 106 M4VIFI_ImagePlane *pResizePlane, 107 M4VIFI_ImagePlane *pPlaneNoResize, 108 M4VIFI_ImagePlane *pPlaneOut); 109 110 static M4OSA_ERR M4VSS3GPP_intRotateVideo(M4VIFI_ImagePlane* pPlaneIn, 111 M4OSA_UInt32 rotationDegree); 112 113 static M4OSA_ERR M4VSS3GPP_intSetYUV420Plane(M4VIFI_ImagePlane* planeIn, 114 M4OSA_UInt32 width, M4OSA_UInt32 height); 115 116 static M4OSA_ERR M4VSS3GPP_intApplyVideoOverlay ( 117 M4VSS3GPP_InternalEditContext *pC, 118 M4VIFI_ImagePlane *pPlaneIn, 119 M4VIFI_ImagePlane *pPlaneOut); 120 121 /** 122 ****************************************************************************** 123 * M4OSA_ERR M4VSS3GPP_intEditStepVideo() 124 * @brief One step of video processing 125 * @param pC (IN/OUT) Internal edit context 126 ****************************************************************************** 127 */ 128 M4OSA_ERR M4VSS3GPP_intEditStepVideo( M4VSS3GPP_InternalEditContext *pC ) 129 { 130 M4OSA_ERR err; 131 M4OSA_Int32 iCts, iNextCts; 132 M4ENCODER_FrameMode FrameMode; 133 M4OSA_Bool bSkipFrame; 134 M4OSA_UInt16 offset; 135 136 /** 137 * Check if we reached end cut. Decorrelate input and output encoding 138 * timestamp to handle encoder prefetch 139 */ 140 if ( ((M4OSA_Int32)(pC->ewc.dInputVidCts) - pC->pC1->iVoffset 141 + pC->iInOutTimeOffset) >= pC->pC1->iEndTime ) 142 { 143 /* Re-adjust video to precise cut time */ 144 pC->iInOutTimeOffset = ((M4OSA_Int32)(pC->ewc.dInputVidCts)) 145 - pC->pC1->iVoffset + pC->iInOutTimeOffset - pC->pC1->iEndTime; 146 if ( pC->iInOutTimeOffset < 0 ) { 147 pC->iInOutTimeOffset = 0; 148 } 149 150 /** 151 * Video is done for this clip */ 152 err = M4VSS3GPP_intReachedEndOfVideo(pC); 153 154 /* RC: to know when a file has been processed */ 155 if (M4NO_ERROR != err && err != M4VSS3GPP_WAR_SWITCH_CLIP) 156 { 157 M4OSA_TRACE1_1( 158 "M4VSS3GPP_intEditStepVideo: M4VSS3GPP_intReachedEndOfVideo returns 0x%x", 159 err); 160 } 161 162 return err; 163 } 164 165 /* Don't change the states if we are in decodeUpTo() */ 166 if ( (M4VSS3GPP_kClipStatus_DECODE_UP_TO != pC->pC1->Vstatus) 167 && (( pC->pC2 == M4OSA_NULL) 168 || (M4VSS3GPP_kClipStatus_DECODE_UP_TO != pC->pC2->Vstatus)) ) 169 { 170 /** 171 * Check Video Mode, depending on the current output CTS */ 172 err = M4VSS3GPP_intCheckVideoMode( 173 pC); /**< This function change the pC->Vstate variable! */ 174 175 if (M4NO_ERROR != err) 176 { 177 M4OSA_TRACE1_1( 178 "M4VSS3GPP_intEditStepVideo: M4VSS3GPP_intCheckVideoMode returns 0x%x!", 179 err); 180 return err; 181 } 182 } 183 184 185 switch( pC->Vstate ) 186 { 187 /* _________________ */ 188 /*| |*/ 189 /*| READ_WRITE MODE |*/ 190 /*|_________________|*/ 191 192 case M4VSS3GPP_kEditVideoState_READ_WRITE: 193 case M4VSS3GPP_kEditVideoState_AFTER_CUT: 194 { 195 M4OSA_TRACE3_0("M4VSS3GPP_intEditStepVideo READ_WRITE"); 196 197 bSkipFrame = M4OSA_FALSE; 198 199 /** 200 * If we were decoding the clip, we must jump to be sure 201 * to get to the good position. */ 202 if( M4VSS3GPP_kClipStatus_READ != pC->pC1->Vstatus ) 203 { 204 /** 205 * Jump to target video time (tc = to-T) */ 206 // Decorrelate input and output encoding timestamp to handle encoder prefetch 207 iCts = (M4OSA_Int32)(pC->ewc.dInputVidCts) - pC->pC1->iVoffset; 208 err = pC->pC1->ShellAPI.m_pReader->m_pFctJump( 209 pC->pC1->pReaderContext, 210 (M4_StreamHandler *)pC->pC1->pVideoStream, &iCts); 211 212 if( M4NO_ERROR != err ) 213 { 214 M4OSA_TRACE1_1( 215 "M4VSS3GPP_intEditStepVideo:\ 216 READ_WRITE: m_pReader->m_pFctJump(V1) returns 0x%x!", 217 err); 218 return err; 219 } 220 221 err = pC->pC1->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu( 222 pC->pC1->pReaderContext, 223 (M4_StreamHandler *)pC->pC1->pVideoStream, 224 &pC->pC1->VideoAU); 225 226 if( ( M4NO_ERROR != err) && (M4WAR_NO_MORE_AU != err) ) 227 { 228 M4OSA_TRACE1_1( 229 "M4VSS3GPP_intEditStepVideo:\ 230 READ_WRITE: m_pReader->m_pFctGetNextAu returns 0x%x!", 231 err); 232 return err; 233 } 234 235 M4OSA_TRACE2_3("A .... read : cts = %.0f + %ld [ 0x%x ]", 236 pC->pC1->VideoAU.m_CTS, pC->pC1->iVoffset, 237 pC->pC1->VideoAU.m_size); 238 239 /* This frame has been already written in BEGIN CUT step -> skip it */ 240 if( pC->pC1->VideoAU.m_CTS == iCts 241 && pC->pC1->iVideoRenderCts >= iCts ) 242 { 243 bSkipFrame = M4OSA_TRUE; 244 } 245 } 246 247 /* This frame has been already written in BEGIN CUT step -> skip it */ 248 if( ( pC->Vstate == M4VSS3GPP_kEditVideoState_AFTER_CUT) 249 && (pC->pC1->VideoAU.m_CTS 250 + pC->pC1->iVoffset <= pC->ewc.WriterVideoAU.CTS) ) 251 { 252 bSkipFrame = M4OSA_TRUE; 253 } 254 255 /** 256 * Remember the clip reading state */ 257 pC->pC1->Vstatus = M4VSS3GPP_kClipStatus_READ; 258 // Decorrelate input and output encoding timestamp to handle encoder prefetch 259 // Rounding is to compensate reader imprecision (m_CTS is actually an integer) 260 iCts = ((M4OSA_Int32)pC->ewc.dInputVidCts) - pC->pC1->iVoffset - 1; 261 iNextCts = iCts + ((M4OSA_Int32)pC->dOutputFrameDuration) + 1; 262 /* Avoid to write a last frame of duration 0 */ 263 if( iNextCts > pC->pC1->iEndTime ) 264 iNextCts = pC->pC1->iEndTime; 265 266 /** 267 * If the AU is good to be written, write it, else just skip it */ 268 if( ( M4OSA_FALSE == bSkipFrame) 269 && (( pC->pC1->VideoAU.m_CTS >= iCts) 270 && (pC->pC1->VideoAU.m_CTS < iNextCts) 271 && (pC->pC1->VideoAU.m_size > 0)) ) 272 { 273 /** 274 * Get the output AU to write into */ 275 err = pC->ShellAPI.pWriterDataFcts->pStartAU( 276 pC->ewc.p3gpWriterContext, 277 M4VSS3GPP_WRITER_VIDEO_STREAM_ID, 278 &pC->ewc.WriterVideoAU); 279 280 if( M4NO_ERROR != err ) 281 { 282 M4OSA_TRACE1_1( 283 "M4VSS3GPP_intEditStepVideo: READ_WRITE:\ 284 pWriterDataFcts->pStartAU(Video) returns 0x%x!", 285 err); 286 return err; 287 } 288 289 /** 290 * Copy the input AU to the output AU */ 291 pC->ewc.WriterVideoAU.attribute = pC->pC1->VideoAU.m_attribute; 292 // Decorrelate input and output encoding timestamp to handle encoder prefetch 293 pC->ewc.WriterVideoAU.CTS = (M4OSA_Time)pC->pC1->VideoAU.m_CTS + 294 (M4OSA_Time)pC->pC1->iVoffset; 295 pC->ewc.dInputVidCts += pC->dOutputFrameDuration; 296 offset = 0; 297 /* for h.264 stream do not read the 1st 4 bytes as they are header 298 indicators */ 299 if( pC->pC1->pVideoStream->m_basicProperties.m_streamType 300 == M4DA_StreamTypeVideoMpeg4Avc ) 301 offset = 4; 302 303 pC->ewc.WriterVideoAU.size = pC->pC1->VideoAU.m_size - offset; 304 if( pC->ewc.WriterVideoAU.size > pC->ewc.uiVideoMaxAuSize ) 305 { 306 M4OSA_TRACE1_2( 307 "M4VSS3GPP_intEditStepVideo: READ_WRITE: AU size greater than\ 308 MaxAuSize (%d>%d)! returning M4VSS3GPP_ERR_INPUT_VIDEO_AU_TOO_LARGE", 309 pC->ewc.WriterVideoAU.size, pC->ewc.uiVideoMaxAuSize); 310 return M4VSS3GPP_ERR_INPUT_VIDEO_AU_TOO_LARGE; 311 } 312 313 memcpy((void *)pC->ewc.WriterVideoAU.dataAddress, 314 (void *)(pC->pC1->VideoAU.m_dataAddress + offset), 315 (pC->ewc.WriterVideoAU.size)); 316 317 /** 318 * Update time info for the Counter Time System to be equal to the bit 319 -stream time*/ 320 M4VSS3GPP_intUpdateTimeInfo(pC, &pC->ewc.WriterVideoAU); 321 M4OSA_TRACE2_2("B ---- write : cts = %lu [ 0x%x ]", 322 pC->ewc.WriterVideoAU.CTS, pC->ewc.WriterVideoAU.size); 323 324 /** 325 * Write the AU */ 326 err = pC->ShellAPI.pWriterDataFcts->pProcessAU( 327 pC->ewc.p3gpWriterContext, 328 M4VSS3GPP_WRITER_VIDEO_STREAM_ID, 329 &pC->ewc.WriterVideoAU); 330 331 if( M4NO_ERROR != err ) 332 { 333 /* the warning M4WAR_WRITER_STOP_REQ is returned when the targeted output 334 file size is reached 335 The editing is then finished, the warning M4VSS3GPP_WAR_EDITING_DONE 336 is returned*/ 337 if( M4WAR_WRITER_STOP_REQ == err ) 338 { 339 M4OSA_TRACE1_0( 340 "M4VSS3GPP_intEditStepVideo: File was cut to avoid oversize"); 341 return M4VSS3GPP_WAR_EDITING_DONE; 342 } 343 else 344 { 345 M4OSA_TRACE1_1( 346 "M4VSS3GPP_intEditStepVideo: READ_WRITE:\ 347 pWriterDataFcts->pProcessAU(Video) returns 0x%x!", 348 err); 349 return err; 350 } 351 } 352 353 /** 354 * Read next AU for next step */ 355 err = pC->pC1->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu( 356 pC->pC1->pReaderContext, 357 (M4_StreamHandler *)pC->pC1->pVideoStream, 358 &pC->pC1->VideoAU); 359 360 if( ( M4NO_ERROR != err) && (M4WAR_NO_MORE_AU != err) ) 361 { 362 M4OSA_TRACE1_1( 363 "M4VSS3GPP_intEditStepVideo: READ_WRITE:\ 364 m_pReaderDataIt->m_pFctGetNextAu returns 0x%x!", 365 err); 366 return err; 367 } 368 369 M4OSA_TRACE2_3("C .... read : cts = %.0f + %ld [ 0x%x ]", 370 pC->pC1->VideoAU.m_CTS, pC->pC1->iVoffset, 371 pC->pC1->VideoAU.m_size); 372 } 373 else 374 { 375 /** 376 * Decide wether to read or to increment time increment */ 377 if( ( pC->pC1->VideoAU.m_size == 0) 378 || (pC->pC1->VideoAU.m_CTS >= iNextCts) ) 379 { 380 /*Increment time by the encoding period (NO_MORE_AU or reader in advance */ 381 // Decorrelate input and output encoding timestamp to handle encoder prefetch 382 pC->ewc.dInputVidCts += pC->dOutputFrameDuration; 383 384 /* Switch (from AFTER_CUT) to normal mode because time is 385 no more frozen */ 386 pC->Vstate = M4VSS3GPP_kEditVideoState_READ_WRITE; 387 } 388 else 389 { 390 /* In other cases (reader late), just let the reader catch up 391 pC->ewc.dVTo */ 392 err = pC->pC1->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu( 393 pC->pC1->pReaderContext, 394 (M4_StreamHandler *)pC->pC1->pVideoStream, 395 &pC->pC1->VideoAU); 396 397 if( ( M4NO_ERROR != err) && (M4WAR_NO_MORE_AU != err) ) 398 { 399 M4OSA_TRACE1_1( 400 "M4VSS3GPP_intEditStepVideo: READ_WRITE:\ 401 m_pReaderDataIt->m_pFctGetNextAu returns 0x%x!", 402 err); 403 return err; 404 } 405 406 M4OSA_TRACE2_3("D .... read : cts = %.0f + %ld [ 0x%x ]", 407 pC->pC1->VideoAU.m_CTS, pC->pC1->iVoffset, 408 pC->pC1->VideoAU.m_size); 409 } 410 } 411 } 412 break; 413 414 /* ____________________ */ 415 /*| |*/ 416 /*| DECODE_ENCODE MODE |*/ 417 /*| BEGIN_CUT MODE |*/ 418 /*|____________________|*/ 419 420 case M4VSS3GPP_kEditVideoState_DECODE_ENCODE: 421 case M4VSS3GPP_kEditVideoState_BEGIN_CUT: 422 { 423 M4OSA_TRACE3_0( 424 "M4VSS3GPP_intEditStepVideo DECODE_ENCODE / BEGIN_CUT"); 425 426 if ((pC->pC1->pSettings->FileType == 427 M4VIDEOEDITING_kFileType_ARGB8888) && 428 (M4OSA_FALSE == 429 pC->pC1->pSettings->ClipProperties.bSetImageData)) { 430 431 err = M4VSS3GPP_intSetYuv420PlaneFromARGB888(pC, pC->pC1); 432 if( M4NO_ERROR != err ) { 433 M4OSA_TRACE1_1( 434 "M4VSS3GPP_intEditStepVideo: DECODE_ENCODE:\ 435 M4VSS3GPP_intSetYuv420PlaneFromARGB888 err=%x", err); 436 return err; 437 } 438 } 439 /** 440 * Decode the video up to the target time 441 (will jump to the previous RAP if needed ) */ 442 // Decorrelate input and output encoding timestamp to handle encoder prefetch 443 err = M4VSS3GPP_intClipDecodeVideoUpToCts(pC->pC1, (M4OSA_Int32)pC->ewc.dInputVidCts); 444 if( M4NO_ERROR != err ) 445 { 446 M4OSA_TRACE1_1( 447 "M4VSS3GPP_intEditStepVideo: DECODE_ENCODE:\ 448 M4VSS3GPP_intDecodeVideoUpToCts returns err=0x%x", 449 err); 450 return err; 451 } 452 453 /* If the decoding is not completed, do one more step with time frozen */ 454 if( M4VSS3GPP_kClipStatus_DECODE_UP_TO == pC->pC1->Vstatus ) 455 { 456 return M4NO_ERROR; 457 } 458 459 /** 460 * Reset the video pre-processing error before calling the encoder */ 461 pC->ewc.VppError = M4NO_ERROR; 462 463 M4OSA_TRACE2_0("E ++++ encode AU"); 464 465 /** 466 * Encode the frame(rendering,filtering and writing will be done 467 in encoder callbacks)*/ 468 if( pC->Vstate == M4VSS3GPP_kEditVideoState_BEGIN_CUT ) 469 FrameMode = M4ENCODER_kIFrame; 470 else 471 FrameMode = M4ENCODER_kNormalFrame; 472 473 // Decorrelate input and output encoding timestamp to handle encoder prefetch 474 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctEncode(pC->ewc.pEncContext, M4OSA_NULL, 475 pC->ewc.dInputVidCts, FrameMode); 476 /** 477 * Check if we had a VPP error... */ 478 if( M4NO_ERROR != pC->ewc.VppError ) 479 { 480 M4OSA_TRACE1_1( 481 "M4VSS3GPP_intEditStepVideo: DECODE_ENCODE:\ 482 pVideoEncoderGlobalFcts->pFctEncode, returning VppErr=0x%x", 483 pC->ewc.VppError); 484 #ifdef M4VSS_SUPPORT_OMX_CODECS 485 486 if( M4WAR_VIDEORENDERER_NO_NEW_FRAME != pC->ewc.VppError ) 487 { 488 #endif //M4VSS_SUPPORT_OMX_CODECS 489 490 return pC->ewc.VppError; 491 #ifdef M4VSS_SUPPORT_OMX_CODECS 492 493 } 494 495 #endif //M4VSS_SUPPORT_OMX_CODECS 496 } 497 else if( M4NO_ERROR != err ) /**< ...or an encoder error */ 498 { 499 if( ((M4OSA_UInt32)M4ERR_ALLOC) == err ) 500 { 501 M4OSA_TRACE1_0( 502 "M4VSS3GPP_intEditStepVideo: DECODE_ENCODE:\ 503 returning M4VSS3GPP_ERR_ENCODER_ACCES_UNIT_ERROR"); 504 return M4VSS3GPP_ERR_ENCODER_ACCES_UNIT_ERROR; 505 } 506 /* the warning M4WAR_WRITER_STOP_REQ is returned when the targeted output 507 file size is reached 508 The editing is then finished, the warning M4VSS3GPP_WAR_EDITING_DONE 509 is returned*/ 510 else if( M4WAR_WRITER_STOP_REQ == err ) 511 { 512 M4OSA_TRACE1_0( 513 "M4VSS3GPP_intEditStepVideo: File was cut to avoid oversize"); 514 return M4VSS3GPP_WAR_EDITING_DONE; 515 } 516 else 517 { 518 M4OSA_TRACE1_1( 519 "M4VSS3GPP_intEditStepVideo: DECODE_ENCODE:\ 520 pVideoEncoderGlobalFcts->pFctEncode returns 0x%x", 521 err); 522 return err; 523 } 524 } 525 526 /** 527 * Increment time by the encoding period (for begin cut, do not increment to not 528 loose P-frames) */ 529 if( M4VSS3GPP_kEditVideoState_DECODE_ENCODE == pC->Vstate ) 530 { 531 // Decorrelate input and output encoding timestamp to handle encoder prefetch 532 pC->ewc.dInputVidCts += pC->dOutputFrameDuration; 533 } 534 } 535 break; 536 537 /* _________________ */ 538 /*| |*/ 539 /*| TRANSITION MODE |*/ 540 /*|_________________|*/ 541 542 case M4VSS3GPP_kEditVideoState_TRANSITION: 543 { 544 M4OSA_TRACE3_0("M4VSS3GPP_intEditStepVideo TRANSITION"); 545 546 /* Don't decode more than needed */ 547 if( !(( M4VSS3GPP_kClipStatus_DECODE_UP_TO != pC->pC1->Vstatus) 548 && (M4VSS3GPP_kClipStatus_DECODE_UP_TO == pC->pC2->Vstatus)) ) 549 { 550 /** 551 * Decode the clip1 video up to the target time 552 (will jump to the previous RAP if needed */ 553 if ((pC->pC1->pSettings->FileType == 554 M4VIDEOEDITING_kFileType_ARGB8888) && 555 (M4OSA_FALSE == 556 pC->pC1->pSettings->ClipProperties.bSetImageData)) { 557 558 err = M4VSS3GPP_intSetYuv420PlaneFromARGB888(pC, pC->pC1); 559 if( M4NO_ERROR != err ) { 560 M4OSA_TRACE1_1( 561 "M4VSS3GPP_intEditStepVideo: TRANSITION:\ 562 M4VSS3GPP_intSetYuv420PlaneFromARGB888 err=%x", err); 563 return err; 564 } 565 } 566 // Decorrelate input and output encoding timestamp to handle encoder prefetch 567 err = M4VSS3GPP_intClipDecodeVideoUpToCts(pC->pC1, 568 (M4OSA_Int32)pC->ewc.dInputVidCts); 569 if( M4NO_ERROR != err ) 570 { 571 M4OSA_TRACE1_1( 572 "M4VSS3GPP_intEditStepVideo: TRANSITION:\ 573 M4VSS3GPP_intDecodeVideoUpToCts(C1) returns err=0x%x", 574 err); 575 return err; 576 } 577 578 /* If the decoding is not completed, do one more step with time frozen */ 579 if( M4VSS3GPP_kClipStatus_DECODE_UP_TO == pC->pC1->Vstatus ) 580 { 581 return M4NO_ERROR; 582 } 583 } 584 585 /* Don't decode more than needed */ 586 if( !(( M4VSS3GPP_kClipStatus_DECODE_UP_TO != pC->pC2->Vstatus) 587 && (M4VSS3GPP_kClipStatus_DECODE_UP_TO == pC->pC1->Vstatus)) ) 588 { 589 /** 590 * Decode the clip2 video up to the target time 591 (will jump to the previous RAP if needed) */ 592 if ((pC->pC2->pSettings->FileType == 593 M4VIDEOEDITING_kFileType_ARGB8888) && 594 (M4OSA_FALSE == 595 pC->pC2->pSettings->ClipProperties.bSetImageData)) { 596 597 err = M4VSS3GPP_intSetYuv420PlaneFromARGB888(pC, pC->pC2); 598 if( M4NO_ERROR != err ) { 599 M4OSA_TRACE1_1( 600 "M4VSS3GPP_intEditStepVideo: TRANSITION:\ 601 M4VSS3GPP_intSetYuv420PlaneFromARGB888 err=%x", err); 602 return err; 603 } 604 } 605 606 // Decorrelate input and output encoding timestamp to handle encoder prefetch 607 err = M4VSS3GPP_intClipDecodeVideoUpToCts(pC->pC2, 608 (M4OSA_Int32)pC->ewc.dInputVidCts); 609 if( M4NO_ERROR != err ) 610 { 611 M4OSA_TRACE1_1( 612 "M4VSS3GPP_intEditStepVideo: TRANSITION:\ 613 M4VSS3GPP_intDecodeVideoUpToCts(C2) returns err=0x%x", 614 err); 615 return err; 616 } 617 618 /* If the decoding is not completed, do one more step with time frozen */ 619 if( M4VSS3GPP_kClipStatus_DECODE_UP_TO == pC->pC2->Vstatus ) 620 { 621 return M4NO_ERROR; 622 } 623 } 624 625 /** 626 * Reset the video pre-processing error before calling the encoder */ 627 pC->ewc.VppError = M4NO_ERROR; 628 629 M4OSA_TRACE2_0("F **** blend AUs"); 630 631 /** 632 * Encode the frame (rendering, filtering and writing will be done 633 in encoder callbacks */ 634 // Decorrelate input and output encoding timestamp to handle encoder prefetch 635 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctEncode(pC->ewc.pEncContext, M4OSA_NULL, 636 pC->ewc.dInputVidCts, M4ENCODER_kNormalFrame); 637 638 /** 639 * If encode returns a process frame error, it is likely to be a VPP error */ 640 if( M4NO_ERROR != pC->ewc.VppError ) 641 { 642 M4OSA_TRACE1_1( 643 "M4VSS3GPP_intEditStepVideo: TRANSITION:\ 644 pVideoEncoderGlobalFcts->pFctEncode, returning VppErr=0x%x", 645 pC->ewc.VppError); 646 #ifdef M4VSS_SUPPORT_OMX_CODECS 647 648 if( M4WAR_VIDEORENDERER_NO_NEW_FRAME != pC->ewc.VppError ) 649 { 650 651 #endif //M4VSS_SUPPORT_OMX_CODECS 652 653 return pC->ewc.VppError; 654 #ifdef M4VSS_SUPPORT_OMX_CODECS 655 656 } 657 658 #endif //M4VSS_SUPPORT_OMX_CODECS 659 } 660 else if( M4NO_ERROR != err ) /**< ...or an encoder error */ 661 { 662 if( ((M4OSA_UInt32)M4ERR_ALLOC) == err ) 663 { 664 M4OSA_TRACE1_0( 665 "M4VSS3GPP_intEditStepVideo: TRANSITION:\ 666 returning M4VSS3GPP_ERR_ENCODER_ACCES_UNIT_ERROR"); 667 return M4VSS3GPP_ERR_ENCODER_ACCES_UNIT_ERROR; 668 } 669 670 /* the warning M4WAR_WRITER_STOP_REQ is returned when the targeted output 671 file size is reached 672 The editing is then finished, the warning M4VSS3GPP_WAR_EDITING_DONE is 673 returned*/ 674 else if( M4WAR_WRITER_STOP_REQ == err ) 675 { 676 M4OSA_TRACE1_0( 677 "M4VSS3GPP_intEditStepVideo: File was cut to avoid oversize"); 678 return M4VSS3GPP_WAR_EDITING_DONE; 679 } 680 else 681 { 682 M4OSA_TRACE1_1( 683 "M4VSS3GPP_intEditStepVideo: TRANSITION:\ 684 pVideoEncoderGlobalFcts->pFctEncode returns 0x%x", 685 err); 686 return err; 687 } 688 } 689 690 /** 691 * Increment time by the encoding period */ 692 // Decorrelate input and output encoding timestamp to handle encoder prefetch 693 pC->ewc.dInputVidCts += pC->dOutputFrameDuration; 694 } 695 break; 696 697 /* ____________ */ 698 /*| |*/ 699 /*| ERROR CASE |*/ 700 /*|____________|*/ 701 702 default: 703 M4OSA_TRACE1_1( 704 "M4VSS3GPP_intEditStepVideo: invalid internal state (0x%x),\ 705 returning M4VSS3GPP_ERR_INTERNAL_STATE", 706 pC->Vstate); 707 return M4VSS3GPP_ERR_INTERNAL_STATE; 708 } 709 710 /** 711 * Return with no error */ 712 M4OSA_TRACE3_0("M4VSS3GPP_intEditStepVideo: returning M4NO_ERROR"); 713 return M4NO_ERROR; 714 } 715 716 /** 717 ****************************************************************************** 718 * M4OSA_ERR M4VSS3GPP_intCheckVideoMode() 719 * @brief Check which video process mode we must use, depending on the output CTS. 720 * @param pC (IN/OUT) Internal edit context 721 ****************************************************************************** 722 */ 723 static M4OSA_ERR M4VSS3GPP_intCheckVideoMode( 724 M4VSS3GPP_InternalEditContext *pC ) 725 { 726 M4OSA_ERR err; 727 // Decorrelate input and output encoding timestamp to handle encoder prefetch 728 const M4OSA_Int32 t = (M4OSA_Int32)pC->ewc.dInputVidCts; 729 /**< Transition duration */ 730 const M4OSA_Int32 TD = pC->pTransitionList[pC->uiCurrentClip].uiTransitionDuration; 731 732 M4OSA_Int32 iTmp; 733 734 const M4VSS3GPP_EditVideoState previousVstate = pC->Vstate; 735 736 /** 737 * Check if Clip1 is on its begin cut, or in an effect zone */ 738 M4VSS3GPP_intCheckVideoEffects(pC, 1); 739 740 /** 741 * Check if we are in the transition with next clip */ 742 if( ( TD > 0) && (( t - pC->pC1->iVoffset) >= (pC->pC1->iEndTime - TD)) ) 743 { 744 /** 745 * We are in a transition */ 746 pC->Vstate = M4VSS3GPP_kEditVideoState_TRANSITION; 747 pC->bTransitionEffect = M4OSA_TRUE; 748 749 /** 750 * Open second clip for transition, if not yet opened */ 751 if( M4OSA_NULL == pC->pC2 ) 752 { 753 pC->pC1->bGetYuvDataFromDecoder = M4OSA_TRUE; 754 755 err = M4VSS3GPP_intOpenClip(pC, &pC->pC2, 756 &pC->pClipList[pC->uiCurrentClip + 1]); 757 758 if( M4NO_ERROR != err ) 759 { 760 M4OSA_TRACE1_1( 761 "M4VSS3GPP_intCheckVideoMode: M4VSS3GPP_editOpenClip returns 0x%x!", 762 err); 763 return err; 764 } 765 766 /** 767 * Add current video output CTS to the clip offset 768 * (audio output CTS is not yet at the transition, so audio 769 * offset can't be updated yet). */ 770 // Decorrelate input and output encoding timestamp to handle encoder prefetch 771 pC->pC2->iVoffset += (M4OSA_UInt32)pC->ewc.dInputVidCts; 772 773 /** 774 * 2005-03-24: BugFix for audio-video synchro: 775 * Update transition duration due to the actual video transition beginning time. 776 * It will avoid desynchronization when doing the audio transition. */ 777 // Decorrelate input and output encoding timestamp to handle encoder prefetch 778 iTmp = ((M4OSA_Int32)pC->ewc.dInputVidCts)\ 779 - (pC->pC1->iEndTime - TD + pC->pC1->iVoffset); 780 if (iTmp < (M4OSA_Int32)pC->pTransitionList[pC->uiCurrentClip].uiTransitionDuration) 781 /**< Test in case of a very short transition */ 782 { 783 pC->pTransitionList[pC-> 784 uiCurrentClip].uiTransitionDuration -= iTmp; 785 786 /** 787 * Don't forget to also correct the total duration used for the progress bar 788 * (it was computed with the original transition duration). */ 789 pC->ewc.iOutputDuration += iTmp; 790 } 791 /**< No "else" here because it's hard predict the effect of 0 duration transition...*/ 792 } 793 794 /** 795 * Check effects for clip2 */ 796 M4VSS3GPP_intCheckVideoEffects(pC, 2); 797 } 798 else 799 { 800 /** 801 * We are not in a transition */ 802 pC->bTransitionEffect = M4OSA_FALSE; 803 804 /* If there is an effect we go to decode/encode mode */ 805 if((pC->nbActiveEffects > 0) || (pC->nbActiveEffects1 > 0) || 806 (pC->pC1->pSettings->FileType == 807 M4VIDEOEDITING_kFileType_ARGB8888) || 808 (pC->pC1->pSettings->bTranscodingRequired == M4OSA_TRUE)) { 809 pC->Vstate = M4VSS3GPP_kEditVideoState_DECODE_ENCODE; 810 } 811 /* We do a begin cut, except if already done (time is not progressing because we want 812 to catch all P-frames after the cut) */ 813 else if( M4OSA_TRUE == pC->bClip1AtBeginCut ) 814 { 815 if(pC->pC1->pSettings->ClipProperties.VideoStreamType == M4VIDEOEDITING_kH264) { 816 pC->Vstate = M4VSS3GPP_kEditVideoState_DECODE_ENCODE; 817 pC->bEncodeTillEoF = M4OSA_TRUE; 818 } else if( ( M4VSS3GPP_kEditVideoState_BEGIN_CUT == previousVstate) 819 || (M4VSS3GPP_kEditVideoState_AFTER_CUT == previousVstate) ) { 820 pC->Vstate = M4VSS3GPP_kEditVideoState_AFTER_CUT; 821 } else { 822 pC->Vstate = M4VSS3GPP_kEditVideoState_BEGIN_CUT; 823 } 824 } 825 /* Else we are in default copy/paste mode */ 826 else 827 { 828 if( ( M4VSS3GPP_kEditVideoState_BEGIN_CUT == previousVstate) 829 || (M4VSS3GPP_kEditVideoState_AFTER_CUT == previousVstate) ) 830 { 831 pC->Vstate = M4VSS3GPP_kEditVideoState_AFTER_CUT; 832 } 833 else if( pC->bIsMMS == M4OSA_TRUE ) 834 { 835 M4OSA_UInt32 currentBitrate; 836 M4OSA_ERR err = M4NO_ERROR; 837 838 /* Do we need to reencode the video to downgrade the bitrate or not ? */ 839 /* Let's compute the cirrent bitrate of the current edited clip */ 840 err = pC->pC1->ShellAPI.m_pReader->m_pFctGetOption( 841 pC->pC1->pReaderContext, 842 M4READER_kOptionID_Bitrate, ¤tBitrate); 843 844 if( err != M4NO_ERROR ) 845 { 846 M4OSA_TRACE1_1( 847 "M4VSS3GPP_intCheckVideoMode:\ 848 Error when getting next bitrate of edited clip: 0x%x", 849 err); 850 return err; 851 } 852 853 /* Remove audio bitrate */ 854 currentBitrate -= 12200; 855 856 /* Test if we go into copy/paste mode or into decode/encode mode */ 857 if( currentBitrate > pC->uiMMSVideoBitrate ) 858 { 859 pC->Vstate = M4VSS3GPP_kEditVideoState_DECODE_ENCODE; 860 } 861 else 862 { 863 pC->Vstate = M4VSS3GPP_kEditVideoState_READ_WRITE; 864 } 865 } 866 else if(!((pC->m_bClipExternalHasStarted == M4OSA_TRUE) && 867 (pC->Vstate == M4VSS3GPP_kEditVideoState_DECODE_ENCODE)) && 868 pC->bEncodeTillEoF == M4OSA_FALSE) 869 { 870 /** 871 * Test if we go into copy/paste mode or into decode/encode mode 872 * If an external effect has been applied on the current clip 873 * then continue to be in decode/encode mode till end of 874 * clip to avoid H.264 distortion. 875 */ 876 pC->Vstate = M4VSS3GPP_kEditVideoState_READ_WRITE; 877 } 878 } 879 } 880 881 /** 882 * Check if we create an encoder */ 883 if( ( ( M4VSS3GPP_kEditVideoState_READ_WRITE == previousVstate) 884 || (M4VSS3GPP_kEditVideoState_AFTER_CUT 885 == previousVstate)) /**< read mode */ 886 && (( M4VSS3GPP_kEditVideoState_DECODE_ENCODE == pC->Vstate) 887 || (M4VSS3GPP_kEditVideoState_BEGIN_CUT == pC->Vstate) 888 || (M4VSS3GPP_kEditVideoState_TRANSITION 889 == pC->Vstate)) /**< encode mode */ 890 && pC->bIsMMS == M4OSA_FALSE ) 891 { 892 /** 893 * Create the encoder, if not created already*/ 894 if (pC->ewc.encoderState == M4VSS3GPP_kNoEncoder) { 895 err = M4VSS3GPP_intCreateVideoEncoder(pC); 896 897 if( M4NO_ERROR != err ) 898 { 899 M4OSA_TRACE1_1( 900 "M4VSS3GPP_intCheckVideoMode: M4VSS3GPP_intCreateVideoEncoder \ 901 returns 0x%x!", err); 902 return err; 903 } 904 } 905 } 906 else if( pC->bIsMMS == M4OSA_TRUE && pC->ewc.pEncContext == M4OSA_NULL ) 907 { 908 /** 909 * Create the encoder */ 910 err = M4VSS3GPP_intCreateVideoEncoder(pC); 911 912 if( M4NO_ERROR != err ) 913 { 914 M4OSA_TRACE1_1( 915 "M4VSS3GPP_intCheckVideoMode: M4VSS3GPP_intCreateVideoEncoder returns 0x%x!", 916 err); 917 return err; 918 } 919 } 920 921 /** 922 * When we go from filtering to read/write, we must act like a begin cut, 923 * because the last filtered image may be different than the original image. */ 924 else if( ( ( M4VSS3GPP_kEditVideoState_DECODE_ENCODE == previousVstate) 925 || (M4VSS3GPP_kEditVideoState_TRANSITION 926 == previousVstate)) /**< encode mode */ 927 && (M4VSS3GPP_kEditVideoState_READ_WRITE == pC->Vstate) /**< read mode */ 928 && (pC->bEncodeTillEoF == M4OSA_FALSE) ) 929 { 930 pC->Vstate = M4VSS3GPP_kEditVideoState_BEGIN_CUT; 931 } 932 933 /** 934 * Check if we destroy an encoder */ 935 else if( ( ( M4VSS3GPP_kEditVideoState_DECODE_ENCODE == previousVstate) 936 || (M4VSS3GPP_kEditVideoState_BEGIN_CUT == previousVstate) 937 || (M4VSS3GPP_kEditVideoState_TRANSITION 938 == previousVstate)) /**< encode mode */ 939 && (( M4VSS3GPP_kEditVideoState_READ_WRITE == pC->Vstate) 940 || (M4VSS3GPP_kEditVideoState_AFTER_CUT 941 == pC->Vstate)) /**< read mode */ 942 && pC->bIsMMS == M4OSA_FALSE ) 943 { 944 /** 945 * Destroy the previously created encoder */ 946 err = M4VSS3GPP_intDestroyVideoEncoder(pC); 947 948 if( M4NO_ERROR != err ) 949 { 950 M4OSA_TRACE1_1( 951 "M4VSS3GPP_intCheckVideoMode: M4VSS3GPP_intDestroyVideoEncoder returns 0x%x!", 952 err); 953 return err; 954 } 955 } 956 957 /** 958 * Return with no error */ 959 M4OSA_TRACE3_0("M4VSS3GPP_intCheckVideoMode: returning M4NO_ERROR"); 960 return M4NO_ERROR; 961 } 962 963 /****************************************************************************** 964 * M4OSA_ERR M4VSS3GPP_intStartAU() 965 * @brief StartAU writer-like interface used for the VSS 3GPP only 966 * @note 967 * @param pContext: (IN) It is the VSS 3GPP context in our case 968 * @param streamID: (IN) Id of the stream to which the Access Unit is related. 969 * @param pAU: (IN/OUT) Access Unit to be prepared. 970 * @return M4NO_ERROR: there is no error 971 ****************************************************************************** 972 */ 973 M4OSA_ERR M4VSS3GPP_intStartAU( M4WRITER_Context pContext, 974 M4SYS_StreamID streamID, M4SYS_AccessUnit *pAU ) 975 { 976 M4OSA_ERR err; 977 M4OSA_UInt32 uiMaxAuSize; 978 979 /** 980 * Given context is actually the VSS3GPP context */ 981 M4VSS3GPP_InternalEditContext *pC = 982 (M4VSS3GPP_InternalEditContext *)pContext; 983 984 /** 985 * Get the output AU to write into */ 986 err = pC->ShellAPI.pWriterDataFcts->pStartAU(pC->ewc.p3gpWriterContext, 987 M4VSS3GPP_WRITER_VIDEO_STREAM_ID, pAU); 988 989 if( M4NO_ERROR != err ) 990 { 991 M4OSA_TRACE1_1( 992 "M4VSS3GPP_intStartAU: pWriterDataFcts->pStartAU(Video) returns 0x%x!", 993 err); 994 return err; 995 } 996 997 /** 998 * Return */ 999 M4OSA_TRACE3_0("M4VSS3GPP_intStartAU: returning M4NO_ERROR"); 1000 return M4NO_ERROR; 1001 } 1002 1003 /****************************************************************************** 1004 * M4OSA_ERR M4VSS3GPP_intProcessAU() 1005 * @brief ProcessAU writer-like interface used for the VSS 3GPP only 1006 * @note 1007 * @param pContext: (IN) It is the VSS 3GPP context in our case 1008 * @param streamID: (IN) Id of the stream to which the Access Unit is related. 1009 * @param pAU: (IN/OUT) Access Unit to be written 1010 * @return M4NO_ERROR: there is no error 1011 ****************************************************************************** 1012 */ 1013 M4OSA_ERR M4VSS3GPP_intProcessAU( M4WRITER_Context pContext, 1014 M4SYS_StreamID streamID, M4SYS_AccessUnit *pAU ) 1015 { 1016 M4OSA_ERR err; 1017 1018 /** 1019 * Given context is actually the VSS3GPP context */ 1020 M4VSS3GPP_InternalEditContext *pC = 1021 (M4VSS3GPP_InternalEditContext *)pContext; 1022 1023 /** 1024 * Fix the encoded AU time */ 1025 // Decorrelate input and output encoding timestamp to handle encoder prefetch 1026 pC->ewc.dOutputVidCts = pAU->CTS; 1027 /** 1028 * Update time info for the Counter Time System to be equal to the bit-stream time */ 1029 M4VSS3GPP_intUpdateTimeInfo(pC, pAU); 1030 1031 /** 1032 * Write the AU */ 1033 err = pC->ShellAPI.pWriterDataFcts->pProcessAU(pC->ewc.p3gpWriterContext, 1034 M4VSS3GPP_WRITER_VIDEO_STREAM_ID, pAU); 1035 1036 if( M4NO_ERROR != err ) 1037 { 1038 M4OSA_TRACE1_1( 1039 "M4VSS3GPP_intProcessAU: pWriterDataFcts->pProcessAU(Video) returns 0x%x!", 1040 err); 1041 return err; 1042 } 1043 1044 /** 1045 * Return */ 1046 M4OSA_TRACE3_0("M4VSS3GPP_intProcessAU: returning M4NO_ERROR"); 1047 return M4NO_ERROR; 1048 } 1049 1050 /** 1051 ****************************************************************************** 1052 * M4OSA_ERR M4VSS3GPP_intVPP() 1053 * @brief We implement our own VideoPreProcessing function 1054 * @note It is called by the video encoder 1055 * @param pContext (IN) VPP context, which actually is the VSS 3GPP context in our case 1056 * @param pPlaneIn (IN) 1057 * @param pPlaneOut (IN/OUT) Pointer to an array of 3 planes that will contain the output 1058 * YUV420 image 1059 * @return M4NO_ERROR: No error 1060 ****************************************************************************** 1061 */ 1062 M4OSA_ERR M4VSS3GPP_intVPP( M4VPP_Context pContext, M4VIFI_ImagePlane *pPlaneIn, 1063 M4VIFI_ImagePlane *pPlaneOut ) 1064 { 1065 M4OSA_ERR err = M4NO_ERROR; 1066 M4_MediaTime ts; 1067 M4VIFI_ImagePlane *pTmp = M4OSA_NULL; 1068 M4VIFI_ImagePlane *pLastDecodedFrame = M4OSA_NULL ; 1069 M4VIFI_ImagePlane *pDecoderRenderFrame = M4OSA_NULL; 1070 M4VIFI_ImagePlane pTemp1[3],pTemp2[3]; 1071 M4VIFI_ImagePlane pTempPlaneClip1[3],pTempPlaneClip2[3]; 1072 M4OSA_UInt32 i = 0, yuvFrameWidth = 0, yuvFrameHeight = 0; 1073 M4OSA_Bool bSkipFrameEffect = M4OSA_FALSE; 1074 /** 1075 * VPP context is actually the VSS3GPP context */ 1076 M4VSS3GPP_InternalEditContext *pC = 1077 (M4VSS3GPP_InternalEditContext *)pContext; 1078 1079 memset((void *)pTemp1, 0, 3*sizeof(M4VIFI_ImagePlane)); 1080 memset((void *)pTemp2, 0, 3*sizeof(M4VIFI_ImagePlane)); 1081 memset((void *)pTempPlaneClip1, 0, 3*sizeof(M4VIFI_ImagePlane)); 1082 memset((void *)pTempPlaneClip2, 0, 3*sizeof(M4VIFI_ImagePlane)); 1083 1084 /** 1085 * Reset VPP error remembered in context */ 1086 pC->ewc.VppError = M4NO_ERROR; 1087 1088 /** 1089 * At the end of the editing, we may be called when no more clip is loaded. 1090 * (because to close the encoder properly it must be stepped one or twice...) */ 1091 if( M4OSA_NULL == pC->pC1 ) 1092 { 1093 /** 1094 * We must fill the input of the encoder with a dummy image, because 1095 * encoding noise leads to a huge video AU, and thus a writer buffer overflow. */ 1096 memset((void *)pPlaneOut[0].pac_data,0, 1097 pPlaneOut[0].u_stride * pPlaneOut[0].u_height); 1098 memset((void *)pPlaneOut[1].pac_data,0, 1099 pPlaneOut[1].u_stride * pPlaneOut[1].u_height); 1100 memset((void *)pPlaneOut[2].pac_data,0, 1101 pPlaneOut[2].u_stride * pPlaneOut[2].u_height); 1102 1103 M4OSA_TRACE3_0("M4VSS3GPP_intVPP: returning M4NO_ERROR (abort)"); 1104 return M4NO_ERROR; 1105 } 1106 1107 /** 1108 **************** Transition case ****************/ 1109 if( M4OSA_TRUE == pC->bTransitionEffect ) 1110 { 1111 1112 err = M4VSS3GPP_intAllocateYUV420(pTemp1, pC->ewc.uiVideoWidth, 1113 pC->ewc.uiVideoHeight); 1114 if (M4NO_ERROR != err) 1115 { 1116 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: M4VSS3GPP_intAllocateYUV420(1) returns 0x%x, \ 1117 returning M4NO_ERROR", err); 1118 pC->ewc.VppError = err; 1119 return M4NO_ERROR; /**< Return no error to the encoder core 1120 (else it may leak in some situations...) */ 1121 } 1122 1123 err = M4VSS3GPP_intAllocateYUV420(pTemp2, pC->ewc.uiVideoWidth, 1124 pC->ewc.uiVideoHeight); 1125 if (M4NO_ERROR != err) 1126 { 1127 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: M4VSS3GPP_intAllocateYUV420(2) returns 0x%x, \ 1128 returning M4NO_ERROR", err); 1129 pC->ewc.VppError = err; 1130 return M4NO_ERROR; /**< Return no error to the encoder core 1131 (else it may leak in some situations...) */ 1132 } 1133 1134 err = M4VSS3GPP_intAllocateYUV420(pC->yuv1, pC->ewc.uiVideoWidth, 1135 pC->ewc.uiVideoHeight); 1136 if( M4NO_ERROR != err ) 1137 { 1138 M4OSA_TRACE1_1( 1139 "M4VSS3GPP_intVPP: M4VSS3GPP_intAllocateYUV420(3) returns 0x%x,\ 1140 returning M4NO_ERROR", 1141 err); 1142 pC->ewc.VppError = err; 1143 return 1144 M4NO_ERROR; /**< Return no error to the encoder core 1145 (else it may leak in some situations...) */ 1146 } 1147 1148 err = M4VSS3GPP_intAllocateYUV420(pC->yuv2, pC->ewc.uiVideoWidth, 1149 pC->ewc.uiVideoHeight); 1150 if( M4NO_ERROR != err ) 1151 { 1152 M4OSA_TRACE1_1( 1153 "M4VSS3GPP_intVPP: M4VSS3GPP_intAllocateYUV420(4) returns 0x%x,\ 1154 returning M4NO_ERROR", 1155 err); 1156 pC->ewc.VppError = err; 1157 return 1158 M4NO_ERROR; /**< Return no error to the encoder core 1159 (else it may leak in some situations...) */ 1160 } 1161 1162 err = M4VSS3GPP_intAllocateYUV420(pC->yuv3, pC->ewc.uiVideoWidth, 1163 pC->ewc.uiVideoHeight); 1164 if( M4NO_ERROR != err ) 1165 { 1166 M4OSA_TRACE1_1( 1167 "M4VSS3GPP_intVPP: M4VSS3GPP_intAllocateYUV420(3) returns 0x%x,\ 1168 returning M4NO_ERROR", 1169 err); 1170 pC->ewc.VppError = err; 1171 return 1172 M4NO_ERROR; /**< Return no error to the encoder core 1173 (else it may leak in some situations...) */ 1174 } 1175 1176 /** 1177 * Compute the time in the clip1 base: ts = to - Offset */ 1178 // Decorrelate input and output encoding timestamp to handle encoder prefetch 1179 ts = pC->ewc.dInputVidCts - pC->pC1->iVoffset; 1180 1181 /** 1182 * Render Clip1 */ 1183 if( pC->pC1->isRenderDup == M4OSA_FALSE ) 1184 { 1185 err = M4VSS3GPP_intRenderFrameWithEffect(pC, pC->pC1, ts, M4OSA_TRUE, 1186 pTempPlaneClip1, pTemp1, 1187 pPlaneOut); 1188 if ((M4NO_ERROR != err) && 1189 (M4WAR_VIDEORENDERER_NO_NEW_FRAME != err)) { 1190 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: \ 1191 M4VSS3GPP_intRenderFrameWithEffect returns 0x%x", err); 1192 pC->ewc.VppError = err; 1193 /** Return no error to the encoder core 1194 * else it may leak in some situations.*/ 1195 return M4NO_ERROR; 1196 } 1197 } 1198 if ((pC->pC1->isRenderDup == M4OSA_TRUE) || 1199 (M4WAR_VIDEORENDERER_NO_NEW_FRAME == err)) { 1200 pTmp = pC->yuv1; 1201 if (pC->pC1->lastDecodedPlane != M4OSA_NULL) { 1202 /* Copy last decoded plane to output plane */ 1203 memcpy((void *)pTmp[0].pac_data, 1204 (void *)pC->pC1->lastDecodedPlane[0].pac_data, 1205 (pTmp[0].u_height * pTmp[0].u_width)); 1206 memcpy((void *)pTmp[1].pac_data, 1207 (void *)pC->pC1->lastDecodedPlane[1].pac_data, 1208 (pTmp[1].u_height * pTmp[1].u_width)); 1209 memcpy((void *)pTmp[2].pac_data, 1210 (void *)pC->pC1->lastDecodedPlane[2].pac_data, 1211 (pTmp[2].u_height * pTmp[2].u_width)); 1212 } else { 1213 err = M4VSS3GPP_ERR_NO_VALID_VID_FRAME; 1214 M4OSA_TRACE1_3("Can not find an input frame. Set error 0x%x in %s (%d)", 1215 err, __FILE__, __LINE__); 1216 pC->ewc.VppError = err; 1217 return M4NO_ERROR; 1218 } 1219 pC->pC1->lastDecodedPlane = pTmp; 1220 } 1221 1222 /** 1223 * Compute the time in the clip2 base: ts = to - Offset */ 1224 // Decorrelate input and output encoding timestamp to handle encoder prefetch 1225 ts = pC->ewc.dInputVidCts - pC->pC2->iVoffset; 1226 /** 1227 * Render Clip2 */ 1228 if( pC->pC2->isRenderDup == M4OSA_FALSE ) 1229 { 1230 1231 err = M4VSS3GPP_intRenderFrameWithEffect(pC, pC->pC2, ts, M4OSA_FALSE, 1232 pTempPlaneClip2, pTemp2, 1233 pPlaneOut); 1234 if ((M4NO_ERROR != err) && 1235 (M4WAR_VIDEORENDERER_NO_NEW_FRAME != err)) { 1236 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: \ 1237 M4VSS3GPP_intRenderFrameWithEffect returns 0x%x", err); 1238 pC->ewc.VppError = err; 1239 /** Return no error to the encoder core 1240 * else it may leak in some situations.*/ 1241 return M4NO_ERROR; 1242 } 1243 } 1244 if ((pC->pC2->isRenderDup == M4OSA_TRUE) || 1245 (M4WAR_VIDEORENDERER_NO_NEW_FRAME == err)) { 1246 pTmp = pC->yuv2; 1247 if (pC->pC2->lastDecodedPlane != M4OSA_NULL) { 1248 /* Copy last decoded plane to output plane */ 1249 memcpy((void *)pTmp[0].pac_data, 1250 (void *)pC->pC2->lastDecodedPlane[0].pac_data, 1251 (pTmp[0].u_height * pTmp[0].u_width)); 1252 memcpy((void *)pTmp[1].pac_data, 1253 (void *)pC->pC2->lastDecodedPlane[1].pac_data, 1254 (pTmp[1].u_height * pTmp[1].u_width)); 1255 memcpy((void *)pTmp[2].pac_data, 1256 (void *)pC->pC2->lastDecodedPlane[2].pac_data, 1257 (pTmp[2].u_height * pTmp[2].u_width)); 1258 } else { 1259 err = M4VSS3GPP_ERR_NO_VALID_VID_FRAME; 1260 M4OSA_TRACE1_3("Can not find an input frame. Set error 0x%x in %s (%d)", 1261 err, __FILE__, __LINE__); 1262 pC->ewc.VppError = err; 1263 return M4NO_ERROR; 1264 } 1265 pC->pC2->lastDecodedPlane = pTmp; 1266 } 1267 1268 1269 pTmp = pPlaneOut; 1270 err = M4VSS3GPP_intVideoTransition(pC, pTmp); 1271 1272 if( M4NO_ERROR != err ) 1273 { 1274 M4OSA_TRACE1_1( 1275 "M4VSS3GPP_intVPP: M4VSS3GPP_intVideoTransition returns 0x%x,\ 1276 returning M4NO_ERROR", 1277 err); 1278 pC->ewc.VppError = err; 1279 return M4NO_ERROR; /**< Return no error to the encoder core 1280 (else it may leak in some situations...) */ 1281 } 1282 for (i=0; i < 3; i++) 1283 { 1284 if(pTempPlaneClip2[i].pac_data != M4OSA_NULL) { 1285 free(pTempPlaneClip2[i].pac_data); 1286 pTempPlaneClip2[i].pac_data = M4OSA_NULL; 1287 } 1288 1289 if(pTempPlaneClip1[i].pac_data != M4OSA_NULL) { 1290 free(pTempPlaneClip1[i].pac_data); 1291 pTempPlaneClip1[i].pac_data = M4OSA_NULL; 1292 } 1293 1294 if (pTemp2[i].pac_data != M4OSA_NULL) { 1295 free(pTemp2[i].pac_data); 1296 pTemp2[i].pac_data = M4OSA_NULL; 1297 } 1298 1299 if (pTemp1[i].pac_data != M4OSA_NULL) { 1300 free(pTemp1[i].pac_data); 1301 pTemp1[i].pac_data = M4OSA_NULL; 1302 } 1303 } 1304 } 1305 /** 1306 **************** No Transition case ****************/ 1307 else 1308 { 1309 M4OSA_TRACE3_0("M4VSS3GPP_intVPP: NO transition case"); 1310 /** 1311 * Compute the time in the clip base: ts = to - Offset */ 1312 ts = pC->ewc.dInputVidCts - pC->pC1->iVoffset; 1313 pC->bIssecondClip = M4OSA_FALSE; 1314 /** 1315 * Render */ 1316 if (pC->pC1->isRenderDup == M4OSA_FALSE) { 1317 M4OSA_TRACE3_0("M4VSS3GPP_intVPP: renderdup false"); 1318 /** 1319 * Check if resizing is needed */ 1320 if (M4OSA_NULL != pC->pC1->m_pPreResizeFrame) { 1321 if ((pC->pC1->pSettings->FileType == 1322 M4VIDEOEDITING_kFileType_ARGB8888) && 1323 (pC->nbActiveEffects == 0) && 1324 (pC->pC1->bGetYuvDataFromDecoder == M4OSA_FALSE)) { 1325 err = pC->pC1->ShellAPI.m_pVideoDecoder->m_pFctSetOption( 1326 pC->pC1->pViDecCtxt, 1327 M4DECODER_kOptionID_EnableYuvWithEffect, 1328 (M4OSA_DataOption)M4OSA_TRUE); 1329 if (M4NO_ERROR == err ) { 1330 err = pC->pC1->ShellAPI.m_pVideoDecoder->m_pFctRender( 1331 pC->pC1->pViDecCtxt, &ts, 1332 pPlaneOut, M4OSA_TRUE); 1333 } 1334 } else { 1335 if (pC->pC1->pSettings->FileType == 1336 M4VIDEOEDITING_kFileType_ARGB8888) { 1337 err = pC->pC1->ShellAPI.m_pVideoDecoder->m_pFctSetOption( 1338 pC->pC1->pViDecCtxt, 1339 M4DECODER_kOptionID_EnableYuvWithEffect, 1340 (M4OSA_DataOption)M4OSA_FALSE); 1341 } 1342 if (M4NO_ERROR == err) { 1343 err = pC->pC1->ShellAPI.m_pVideoDecoder->m_pFctRender( 1344 pC->pC1->pViDecCtxt, &ts, 1345 pC->pC1->m_pPreResizeFrame, M4OSA_TRUE); 1346 } 1347 } 1348 if (M4NO_ERROR != err) { 1349 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: \ 1350 m_pFctRender() returns error 0x%x", err); 1351 pC->ewc.VppError = err; 1352 return M4NO_ERROR; 1353 } 1354 if (pC->pC1->pSettings->FileType != 1355 M4VIDEOEDITING_kFileType_ARGB8888) { 1356 if (0 != pC->pC1->pSettings->ClipProperties.videoRotationDegrees) { 1357 // Save width and height of un-rotated frame 1358 yuvFrameWidth = pC->pC1->m_pPreResizeFrame[0].u_width; 1359 yuvFrameHeight = pC->pC1->m_pPreResizeFrame[0].u_height; 1360 err = M4VSS3GPP_intRotateVideo(pC->pC1->m_pPreResizeFrame, 1361 pC->pC1->pSettings->ClipProperties.videoRotationDegrees); 1362 if (M4NO_ERROR != err) { 1363 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: \ 1364 rotateVideo() returns error 0x%x", err); 1365 pC->ewc.VppError = err; 1366 return M4NO_ERROR; 1367 } 1368 } 1369 } 1370 1371 if (pC->nbActiveEffects > 0) { 1372 pC->pC1->bGetYuvDataFromDecoder = M4OSA_TRUE; 1373 /** 1374 * If we do modify the image, we need an intermediate 1375 * image plane */ 1376 err = M4VSS3GPP_intAllocateYUV420(pTemp1, 1377 pC->pC1->m_pPreResizeFrame[0].u_width, 1378 pC->pC1->m_pPreResizeFrame[0].u_height); 1379 if (M4NO_ERROR != err) { 1380 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: \ 1381 M4VSS3GPP_intAllocateYUV420 error 0x%x", err); 1382 pC->ewc.VppError = err; 1383 return M4NO_ERROR; 1384 } 1385 /* If video frame need to be resized, then apply the overlay after 1386 * the frame was rendered with rendering mode. 1387 * Here skip the framing(overlay) effect when applying video Effect. */ 1388 bSkipFrameEffect = M4OSA_TRUE; 1389 err = M4VSS3GPP_intApplyVideoEffect(pC, 1390 pC->pC1->m_pPreResizeFrame, pTemp1, bSkipFrameEffect); 1391 if (M4NO_ERROR != err) { 1392 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: \ 1393 M4VSS3GPP_intApplyVideoEffect() error 0x%x", err); 1394 pC->ewc.VppError = err; 1395 return M4NO_ERROR; 1396 } 1397 pDecoderRenderFrame= pTemp1; 1398 1399 } else { 1400 pDecoderRenderFrame = pC->pC1->m_pPreResizeFrame; 1401 } 1402 /* Prepare overlay temporary buffer if overlay exist */ 1403 if (pC->bClip1ActiveFramingEffect) { 1404 err = M4VSS3GPP_intAllocateYUV420(pTemp2, 1405 pPlaneOut[0].u_width, pPlaneOut[0].u_height); 1406 if (M4NO_ERROR != err) { 1407 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: M4VSS3GPP_intAllocateYUV420 \ 1408 returns 0x%x, returning M4NO_ERROR", err); 1409 pC->ewc.VppError = err; 1410 return M4NO_ERROR; 1411 } 1412 pTmp = pTemp2; 1413 } else { 1414 pTmp = pPlaneOut; 1415 } 1416 1417 /* Do rendering mode. */ 1418 if ((pC->pC1->bGetYuvDataFromDecoder == M4OSA_TRUE) || 1419 (pC->pC1->pSettings->FileType != 1420 M4VIDEOEDITING_kFileType_ARGB8888)) { 1421 1422 err = M4VSS3GPP_intApplyRenderingMode(pC, 1423 pC->pC1->pSettings->xVSS.MediaRendering, 1424 pDecoderRenderFrame, pTmp); 1425 if (M4NO_ERROR != err) { 1426 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: \ 1427 M4VSS3GPP_intApplyRenderingMode) error 0x%x ", err); 1428 pC->ewc.VppError = err; 1429 return M4NO_ERROR; 1430 } 1431 } 1432 1433 /* Apply overlay if overlay is exist */ 1434 if (pC->bClip1ActiveFramingEffect) { 1435 pDecoderRenderFrame = pTmp; 1436 pTmp = pPlaneOut; 1437 err = M4VSS3GPP_intApplyVideoOverlay(pC, 1438 pDecoderRenderFrame, pTmp); 1439 if (M4NO_ERROR != err) { 1440 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: \ 1441 M4VSS3GPP_intApplyVideoOverlay) error 0x%x ", err); 1442 pC->ewc.VppError = err; 1443 return M4NO_ERROR; 1444 } 1445 } 1446 1447 if ((pC->pC1->pSettings->FileType == 1448 M4VIDEOEDITING_kFileType_ARGB8888) && 1449 (pC->nbActiveEffects == 0) && 1450 (pC->pC1->bGetYuvDataFromDecoder == M4OSA_TRUE)) { 1451 1452 err = pC->pC1->ShellAPI.m_pVideoDecoder->m_pFctSetOption( 1453 pC->pC1->pViDecCtxt, 1454 M4DECODER_kOptionID_YuvWithEffectNonContiguous, 1455 (M4OSA_DataOption)pTmp); 1456 if (M4NO_ERROR != err) { 1457 pC->ewc.VppError = err; 1458 return M4NO_ERROR; 1459 } 1460 pC->pC1->bGetYuvDataFromDecoder = M4OSA_FALSE; 1461 } 1462 1463 // Reset original width and height for resize frame plane 1464 if (0 != pC->pC1->pSettings->ClipProperties.videoRotationDegrees && 1465 180 != pC->pC1->pSettings->ClipProperties.videoRotationDegrees) { 1466 1467 M4VSS3GPP_intSetYUV420Plane(pC->pC1->m_pPreResizeFrame, 1468 yuvFrameWidth, yuvFrameHeight); 1469 } 1470 } 1471 else 1472 { 1473 M4OSA_TRACE3_0("M4VSS3GPP_intVPP: NO resize required"); 1474 if (pC->nbActiveEffects > 0) { 1475 /** If we do modify the image, we need an 1476 * intermediate image plane */ 1477 err = M4VSS3GPP_intAllocateYUV420(pTemp1, 1478 pC->ewc.uiVideoWidth, 1479 pC->ewc.uiVideoHeight); 1480 if (M4NO_ERROR != err) { 1481 pC->ewc.VppError = err; 1482 return M4NO_ERROR; 1483 } 1484 pDecoderRenderFrame = pTemp1; 1485 } 1486 else { 1487 pDecoderRenderFrame = pPlaneOut; 1488 } 1489 1490 pTmp = pPlaneOut; 1491 err = pC->pC1->ShellAPI.m_pVideoDecoder->m_pFctRender( 1492 pC->pC1->pViDecCtxt, &ts, 1493 pDecoderRenderFrame, M4OSA_TRUE); 1494 if (M4NO_ERROR != err) { 1495 pC->ewc.VppError = err; 1496 return M4NO_ERROR; 1497 } 1498 1499 if (pC->nbActiveEffects > 0) { 1500 /* Here we do not skip the overlay effect since 1501 * overlay and video frame are both of same resolution */ 1502 bSkipFrameEffect = M4OSA_FALSE; 1503 err = M4VSS3GPP_intApplyVideoEffect(pC, 1504 pDecoderRenderFrame,pPlaneOut,bSkipFrameEffect); 1505 } 1506 if (M4NO_ERROR != err) { 1507 pC->ewc.VppError = err; 1508 return M4NO_ERROR; 1509 } 1510 } 1511 pC->pC1->lastDecodedPlane = pTmp; 1512 pC->pC1->iVideoRenderCts = (M4OSA_Int32)ts; 1513 1514 } else { 1515 M4OSA_TRACE3_0("M4VSS3GPP_intVPP: renderdup true"); 1516 1517 if (M4OSA_NULL != pC->pC1->m_pPreResizeFrame) { 1518 /** 1519 * Copy last decoded plane to output plane */ 1520 if (pC->pC1->lastDecodedPlane != M4OSA_NULL) { 1521 1522 memcpy((void *)pC->pC1->m_pPreResizeFrame[0].pac_data, 1523 (void *)pC->pC1->lastDecodedPlane[0].pac_data, 1524 (pC->pC1->m_pPreResizeFrame[0].u_height * \ 1525 pC->pC1->m_pPreResizeFrame[0].u_width)); 1526 1527 memcpy((void *)pC->pC1->m_pPreResizeFrame[1].pac_data, 1528 (void *)pC->pC1->lastDecodedPlane[1].pac_data, 1529 (pC->pC1->m_pPreResizeFrame[1].u_height * \ 1530 pC->pC1->m_pPreResizeFrame[1].u_width)); 1531 1532 memcpy((void *)pC->pC1->m_pPreResizeFrame[2].pac_data, 1533 (void *)pC->pC1->lastDecodedPlane[2].pac_data, 1534 (pC->pC1->m_pPreResizeFrame[2].u_height * \ 1535 pC->pC1->m_pPreResizeFrame[2].u_width)); 1536 } else { 1537 err = M4VSS3GPP_ERR_NO_VALID_VID_FRAME; 1538 M4OSA_TRACE1_3("Can not find an input frame. Set error 0x%x in %s (%d)", 1539 err, __FILE__, __LINE__); 1540 pC->ewc.VppError = err; 1541 return M4NO_ERROR; 1542 } 1543 1544 if(pC->nbActiveEffects > 0) { 1545 /** 1546 * If we do modify the image, we need an 1547 * intermediate image plane */ 1548 err = M4VSS3GPP_intAllocateYUV420(pTemp1, 1549 pC->pC1->m_pPreResizeFrame[0].u_width, 1550 pC->pC1->m_pPreResizeFrame[0].u_height); 1551 if (M4NO_ERROR != err) { 1552 pC->ewc.VppError = err; 1553 return M4NO_ERROR; 1554 } 1555 /* If video frame need to be resized, then apply the overlay after 1556 * the frame was rendered with rendering mode. 1557 * Here skip the framing(overlay) effect when applying video Effect. */ 1558 bSkipFrameEffect = M4OSA_TRUE; 1559 err = M4VSS3GPP_intApplyVideoEffect(pC, 1560 pC->pC1->m_pPreResizeFrame,pTemp1, bSkipFrameEffect); 1561 if (M4NO_ERROR != err) { 1562 pC->ewc.VppError = err; 1563 return M4NO_ERROR; 1564 } 1565 pDecoderRenderFrame= pTemp1; 1566 } else { 1567 pDecoderRenderFrame = pC->pC1->m_pPreResizeFrame; 1568 } 1569 /* Prepare overlay temporary buffer if overlay exist */ 1570 if (pC->bClip1ActiveFramingEffect) { 1571 err = M4VSS3GPP_intAllocateYUV420( 1572 pTemp2, pC->ewc.uiVideoWidth, pC->ewc.uiVideoHeight); 1573 if (M4NO_ERROR != err) { 1574 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: M4VSS3GPP_intAllocateYUV420 \ 1575 returns 0x%x, returning M4NO_ERROR", err); 1576 pC->ewc.VppError = err; 1577 return M4NO_ERROR; 1578 } 1579 pTmp = pTemp2; 1580 } else { 1581 pTmp = pPlaneOut; 1582 } 1583 /* Do rendering mode */ 1584 err = M4VSS3GPP_intApplyRenderingMode(pC, 1585 pC->pC1->pSettings->xVSS.MediaRendering, 1586 pDecoderRenderFrame, pTmp); 1587 if (M4NO_ERROR != err) { 1588 pC->ewc.VppError = err; 1589 return M4NO_ERROR; 1590 } 1591 /* Apply overlay if overlay is exist */ 1592 pTmp = pPlaneOut; 1593 if (pC->bClip1ActiveFramingEffect) { 1594 err = M4VSS3GPP_intApplyVideoOverlay(pC, 1595 pTemp2, pTmp); 1596 if (M4NO_ERROR != err) { 1597 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: \ 1598 M4VSS3GPP_intApplyRenderingMode) error 0x%x ", err); 1599 pC->ewc.VppError = err; 1600 return M4NO_ERROR; 1601 } 1602 } 1603 } else { 1604 1605 err = M4VSS3GPP_intAllocateYUV420(pTemp1, 1606 pC->ewc.uiVideoWidth, 1607 pC->ewc.uiVideoHeight); 1608 if (M4NO_ERROR != err) { 1609 pC->ewc.VppError = err; 1610 return M4NO_ERROR; 1611 } 1612 /** 1613 * Copy last decoded plane to output plane */ 1614 if (pC->pC1->lastDecodedPlane != M4OSA_NULL && 1615 pLastDecodedFrame != M4OSA_NULL) { 1616 memcpy((void *)pLastDecodedFrame[0].pac_data, 1617 (void *)pC->pC1->lastDecodedPlane[0].pac_data, 1618 (pLastDecodedFrame[0].u_height * pLastDecodedFrame[0].u_width)); 1619 1620 memcpy((void *)pLastDecodedFrame[1].pac_data, 1621 (void *)pC->pC1->lastDecodedPlane[1].pac_data, 1622 (pLastDecodedFrame[1].u_height * pLastDecodedFrame[1].u_width)); 1623 1624 memcpy((void *)pLastDecodedFrame[2].pac_data, 1625 (void *)pC->pC1->lastDecodedPlane[2].pac_data, 1626 (pLastDecodedFrame[2].u_height * pLastDecodedFrame[2].u_width)); 1627 } else { 1628 err = M4VSS3GPP_ERR_NO_VALID_VID_FRAME; 1629 M4OSA_TRACE1_3("Can not find an input frame. Set error 0x%x in %s (%d)", 1630 err, __FILE__, __LINE__); 1631 pC->ewc.VppError = err; 1632 return M4NO_ERROR; 1633 } 1634 1635 pTmp = pPlaneOut; 1636 /** 1637 * Check if there is a effect */ 1638 if(pC->nbActiveEffects > 0) { 1639 /* Here we do not skip the overlay effect since 1640 * overlay and video are both of same resolution */ 1641 bSkipFrameEffect = M4OSA_FALSE; 1642 err = M4VSS3GPP_intApplyVideoEffect(pC, 1643 pLastDecodedFrame, pTmp,bSkipFrameEffect); 1644 if (M4NO_ERROR != err) { 1645 pC->ewc.VppError = err; 1646 return M4NO_ERROR; 1647 } 1648 } 1649 } 1650 pC->pC1->lastDecodedPlane = pTmp; 1651 } 1652 1653 M4OSA_TRACE3_1("M4VSS3GPP_intVPP: Rendered at CTS %.3f", ts); 1654 1655 for (i=0; i<3; i++) { 1656 if (pTemp1[i].pac_data != M4OSA_NULL) { 1657 free(pTemp1[i].pac_data); 1658 pTemp1[i].pac_data = M4OSA_NULL; 1659 } 1660 } 1661 for (i=0; i<3; i++) { 1662 if (pTemp2[i].pac_data != M4OSA_NULL) { 1663 free(pTemp2[i].pac_data); 1664 pTemp2[i].pac_data = M4OSA_NULL; 1665 } 1666 } 1667 } 1668 1669 /** 1670 * Return */ 1671 M4OSA_TRACE3_0("M4VSS3GPP_intVPP: returning M4NO_ERROR"); 1672 return M4NO_ERROR; 1673 } 1674 /** 1675 ****************************************************************************** 1676 * M4OSA_ERR M4VSS3GPP_intApplyVideoOverlay() 1677 * @brief Apply video overlay from pPlaneIn to pPlaneOut 1678 * @param pC (IN/OUT) Internal edit context 1679 * @param pInputPlanes (IN) Input raw YUV420 image 1680 * @param pOutputPlanes (IN/OUT) Output raw YUV420 image 1681 * @return M4NO_ERROR: No error 1682 ****************************************************************************** 1683 */ 1684 static M4OSA_ERR 1685 M4VSS3GPP_intApplyVideoOverlay (M4VSS3GPP_InternalEditContext *pC, 1686 M4VIFI_ImagePlane *pPlaneIn, M4VIFI_ImagePlane *pPlaneOut) { 1687 1688 M4VSS3GPP_ClipContext *pClip; 1689 M4VSS3GPP_EffectSettings *pFx; 1690 M4VSS3GPP_ExternalProgress extProgress; 1691 M4OSA_Double VideoEffectTime; 1692 M4OSA_Double PercentageDone; 1693 M4OSA_UInt8 NumActiveEffects =0; 1694 M4OSA_UInt32 Cts = 0; 1695 M4OSA_Int32 nextEffectTime; 1696 M4OSA_Int32 tmp; 1697 M4OSA_UInt8 i; 1698 M4OSA_ERR err; 1699 1700 pClip = pC->pC1; 1701 if (pC->bIssecondClip == M4OSA_TRUE) { 1702 NumActiveEffects = pC->nbActiveEffects1; 1703 } else { 1704 NumActiveEffects = pC->nbActiveEffects; 1705 } 1706 for (i=0; i<NumActiveEffects; i++) { 1707 if (pC->bIssecondClip == M4OSA_TRUE) { 1708 pFx = &(pC->pEffectsList[pC->pActiveEffectsList1[i]]); 1709 /* Compute how far from the beginning of the effect we are, in clip-base time. */ 1710 // Decorrelate input and output encoding timestamp to handle encoder prefetch 1711 VideoEffectTime = ((M4OSA_Int32)pC->ewc.dInputVidCts) + 1712 pC->pTransitionList[pC->uiCurrentClip].uiTransitionDuration - pFx->uiStartTime; 1713 } else { 1714 pFx = &(pC->pEffectsList[pC->pActiveEffectsList[i]]); 1715 /* Compute how far from the beginning of the effect we are, in clip-base time. */ 1716 // Decorrelate input and output encoding timestamp to handle encoder prefetch 1717 VideoEffectTime = ((M4OSA_Int32)pC->ewc.dInputVidCts) - pFx->uiStartTime; 1718 } 1719 /* Do the framing(overlay) effect only, 1720 * skip other color effect which had been applied */ 1721 if (pFx->xVSS.pFramingBuffer == M4OSA_NULL) { 1722 continue; 1723 } 1724 1725 /* To calculate %, substract timeIncrement because effect should finish 1726 * on the last frame which is presented from CTS = eof-timeIncrement till CTS = eof */ 1727 PercentageDone = VideoEffectTime / ((M4OSA_Float)pFx->uiDuration); 1728 1729 if (PercentageDone < 0.0) { 1730 PercentageDone = 0.0; 1731 } 1732 if (PercentageDone > 1.0) { 1733 PercentageDone = 1.0; 1734 } 1735 /** 1736 * Compute where we are in the effect (scale is 0->1000) */ 1737 tmp = (M4OSA_Int32)(PercentageDone * 1000); 1738 1739 /** 1740 * Set the progress info provided to the external function */ 1741 extProgress.uiProgress = (M4OSA_UInt32)tmp; 1742 // Decorrelate input and output encoding timestamp to handle encoder prefetch 1743 extProgress.uiOutputTime = (M4OSA_UInt32)pC->ewc.dInputVidCts; 1744 extProgress.uiClipTime = extProgress.uiOutputTime - pClip->iVoffset; 1745 extProgress.bIsLast = M4OSA_FALSE; 1746 // Decorrelate input and output encoding timestamp to handle encoder prefetch 1747 nextEffectTime = (M4OSA_Int32)(pC->ewc.dInputVidCts \ 1748 + pC->dOutputFrameDuration); 1749 if (nextEffectTime >= (M4OSA_Int32)(pFx->uiStartTime + pFx->uiDuration)) { 1750 extProgress.bIsLast = M4OSA_TRUE; 1751 } 1752 err = pFx->ExtVideoEffectFct(pFx->pExtVideoEffectFctCtxt, 1753 pPlaneIn, pPlaneOut, &extProgress, 1754 pFx->VideoEffectType - M4VSS3GPP_kVideoEffectType_External); 1755 1756 if (M4NO_ERROR != err) { 1757 M4OSA_TRACE1_1( 1758 "M4VSS3GPP_intApplyVideoOverlay: \ 1759 External video effect function returns 0x%x!", 1760 err); 1761 return err; 1762 } 1763 } 1764 1765 /** 1766 * Return */ 1767 M4OSA_TRACE3_0("M4VSS3GPP_intApplyVideoOverlay: returning M4NO_ERROR"); 1768 return M4NO_ERROR; 1769 } 1770 /** 1771 ****************************************************************************** 1772 * M4OSA_ERR M4VSS3GPP_intApplyVideoEffect() 1773 * @brief Apply video effect from pPlaneIn to pPlaneOut 1774 * @param pC (IN/OUT) Internal edit context 1775 * @param uiClip1orClip2 (IN/OUT) 1 for first clip, 2 for second clip 1776 * @param pInputPlanes (IN) Input raw YUV420 image 1777 * @param pOutputPlanes (IN/OUT) Output raw YUV420 image 1778 * @param bSkipFramingEffect (IN) skip framing effect flag 1779 * @return M4NO_ERROR: No error 1780 ****************************************************************************** 1781 */ 1782 static M4OSA_ERR 1783 M4VSS3GPP_intApplyVideoEffect (M4VSS3GPP_InternalEditContext *pC, 1784 M4VIFI_ImagePlane *pPlaneIn, M4VIFI_ImagePlane *pPlaneOut, 1785 M4OSA_Bool bSkipFramingEffect) { 1786 1787 M4OSA_ERR err; 1788 1789 M4VSS3GPP_ClipContext *pClip; 1790 M4VSS3GPP_EffectSettings *pFx; 1791 M4VSS3GPP_ExternalProgress extProgress; 1792 1793 M4OSA_Double VideoEffectTime; 1794 M4OSA_Double PercentageDone; 1795 M4OSA_Int32 tmp; 1796 1797 M4VIFI_ImagePlane *pPlaneTempIn; 1798 M4VIFI_ImagePlane *pPlaneTempOut; 1799 M4VIFI_ImagePlane pTempYuvPlane[3]; 1800 M4OSA_UInt8 i; 1801 M4OSA_UInt8 NumActiveEffects =0; 1802 1803 1804 pClip = pC->pC1; 1805 if (pC->bIssecondClip == M4OSA_TRUE) 1806 { 1807 NumActiveEffects = pC->nbActiveEffects1; 1808 } 1809 else 1810 { 1811 NumActiveEffects = pC->nbActiveEffects; 1812 } 1813 1814 memset((void *)pTempYuvPlane, 0, 3*sizeof(M4VIFI_ImagePlane)); 1815 1816 /** 1817 * Allocate temporary plane if needed RC */ 1818 if (NumActiveEffects > 1) { 1819 err = M4VSS3GPP_intAllocateYUV420(pTempYuvPlane, pPlaneOut->u_width, 1820 pPlaneOut->u_height); 1821 1822 if( M4NO_ERROR != err ) 1823 { 1824 M4OSA_TRACE1_1( 1825 "M4VSS3GPP_intApplyVideoEffect: M4VSS3GPP_intAllocateYUV420(4) returns 0x%x,\ 1826 returning M4NO_ERROR", 1827 err); 1828 pC->ewc.VppError = err; 1829 return 1830 M4NO_ERROR; /**< Return no error to the encoder core 1831 (else it may leak in some situations...) */ 1832 } 1833 } 1834 1835 if (NumActiveEffects % 2 == 0) 1836 { 1837 pPlaneTempIn = pPlaneIn; 1838 pPlaneTempOut = pTempYuvPlane; 1839 } 1840 else 1841 { 1842 pPlaneTempIn = pPlaneIn; 1843 pPlaneTempOut = pPlaneOut; 1844 } 1845 1846 for (i=0; i<NumActiveEffects; i++) 1847 { 1848 if (pC->bIssecondClip == M4OSA_TRUE) 1849 { 1850 1851 1852 pFx = &(pC->pEffectsList[pC->pActiveEffectsList1[i]]); 1853 /* Compute how far from the beginning of the effect we are, in clip-base time. */ 1854 // Decorrelate input and output encoding timestamp to handle encoder prefetch 1855 VideoEffectTime = ((M4OSA_Int32)pC->ewc.dInputVidCts) + 1856 pC->pTransitionList[pC->uiCurrentClip]. 1857 uiTransitionDuration- pFx->uiStartTime; 1858 } 1859 else 1860 { 1861 pFx = &(pC->pEffectsList[pC->pActiveEffectsList[i]]); 1862 /* Compute how far from the beginning of the effect we are, in clip-base time. */ 1863 // Decorrelate input and output encoding timestamp to handle encoder prefetch 1864 VideoEffectTime = ((M4OSA_Int32)pC->ewc.dInputVidCts) - pFx->uiStartTime; 1865 } 1866 1867 1868 1869 /* To calculate %, substract timeIncrement because effect should finish on the last frame*/ 1870 /* which is presented from CTS = eof-timeIncrement till CTS = eof */ 1871 PercentageDone = VideoEffectTime 1872 / ((M4OSA_Float)pFx->uiDuration/*- pC->dOutputFrameDuration*/); 1873 1874 if( PercentageDone < 0.0 ) 1875 PercentageDone = 0.0; 1876 1877 if( PercentageDone > 1.0 ) 1878 PercentageDone = 1.0; 1879 1880 switch( pFx->VideoEffectType ) 1881 { 1882 case M4VSS3GPP_kVideoEffectType_FadeFromBlack: 1883 /** 1884 * Compute where we are in the effect (scale is 0->1024). */ 1885 tmp = (M4OSA_Int32)(PercentageDone * 1024); 1886 1887 /** 1888 * Apply the darkening effect */ 1889 err = 1890 M4VFL_modifyLumaWithScale((M4ViComImagePlane *)pPlaneTempIn, 1891 (M4ViComImagePlane *)pPlaneTempOut, tmp, M4OSA_NULL); 1892 1893 if( M4NO_ERROR != err ) 1894 { 1895 M4OSA_TRACE1_1( 1896 "M4VSS3GPP_intApplyVideoEffect:\ 1897 M4VFL_modifyLumaWithScale returns error 0x%x,\ 1898 returning M4VSS3GPP_ERR_LUMA_FILTER_ERROR", 1899 err); 1900 return M4VSS3GPP_ERR_LUMA_FILTER_ERROR; 1901 } 1902 break; 1903 1904 case M4VSS3GPP_kVideoEffectType_FadeToBlack: 1905 /** 1906 * Compute where we are in the effect (scale is 0->1024) */ 1907 tmp = (M4OSA_Int32)(( 1.0 - PercentageDone) * 1024); 1908 1909 /** 1910 * Apply the darkening effect */ 1911 err = 1912 M4VFL_modifyLumaWithScale((M4ViComImagePlane *)pPlaneTempIn, 1913 (M4ViComImagePlane *)pPlaneTempOut, tmp, M4OSA_NULL); 1914 1915 if( M4NO_ERROR != err ) 1916 { 1917 M4OSA_TRACE1_1( 1918 "M4VSS3GPP_intApplyVideoEffect:\ 1919 M4VFL_modifyLumaWithScale returns error 0x%x,\ 1920 returning M4VSS3GPP_ERR_LUMA_FILTER_ERROR", 1921 err); 1922 return M4VSS3GPP_ERR_LUMA_FILTER_ERROR; 1923 } 1924 break; 1925 1926 default: 1927 if( pFx->VideoEffectType 1928 >= M4VSS3GPP_kVideoEffectType_External ) 1929 { 1930 M4OSA_UInt32 Cts = 0; 1931 M4OSA_Int32 nextEffectTime; 1932 1933 /** 1934 * Compute where we are in the effect (scale is 0->1000) */ 1935 tmp = (M4OSA_Int32)(PercentageDone * 1000); 1936 1937 /** 1938 * Set the progress info provided to the external function */ 1939 extProgress.uiProgress = (M4OSA_UInt32)tmp; 1940 // Decorrelate input and output encoding timestamp to handle encoder prefetch 1941 extProgress.uiOutputTime = (M4OSA_UInt32)pC->ewc.dInputVidCts; 1942 extProgress.uiClipTime = extProgress.uiOutputTime - pClip->iVoffset; 1943 extProgress.bIsLast = M4OSA_FALSE; 1944 // Decorrelate input and output encoding timestamp to handle encoder prefetch 1945 nextEffectTime = (M4OSA_Int32)(pC->ewc.dInputVidCts \ 1946 + pC->dOutputFrameDuration); 1947 if(nextEffectTime >= (M4OSA_Int32)(pFx->uiStartTime + pFx->uiDuration)) 1948 { 1949 extProgress.bIsLast = M4OSA_TRUE; 1950 } 1951 /* Here skip the framing effect, 1952 * do the framing effect after apply rendering mode */ 1953 if ((pFx->xVSS.pFramingBuffer != M4OSA_NULL) && 1954 bSkipFramingEffect == M4OSA_TRUE) { 1955 memcpy(pPlaneTempOut[0].pac_data, pPlaneTempIn[0].pac_data, 1956 pPlaneTempIn[0].u_height * pPlaneTempIn[0].u_width); 1957 memcpy(pPlaneTempOut[1].pac_data, pPlaneTempIn[1].pac_data, 1958 pPlaneTempIn[1].u_height * pPlaneTempIn[1].u_width); 1959 memcpy(pPlaneTempOut[2].pac_data, pPlaneTempIn[2].pac_data, 1960 pPlaneTempIn[2].u_height * pPlaneTempIn[2].u_width); 1961 1962 } else { 1963 err = pFx->ExtVideoEffectFct(pFx->pExtVideoEffectFctCtxt, 1964 pPlaneTempIn, pPlaneTempOut, &extProgress, 1965 pFx->VideoEffectType 1966 - M4VSS3GPP_kVideoEffectType_External); 1967 } 1968 if( M4NO_ERROR != err ) 1969 { 1970 M4OSA_TRACE1_1( 1971 "M4VSS3GPP_intApplyVideoEffect: \ 1972 External video effect function returns 0x%x!", 1973 err); 1974 return err; 1975 } 1976 break; 1977 } 1978 else 1979 { 1980 M4OSA_TRACE1_1( 1981 "M4VSS3GPP_intApplyVideoEffect: unknown effect type (0x%x),\ 1982 returning M4VSS3GPP_ERR_INVALID_VIDEO_EFFECT_TYPE", 1983 pFx->VideoEffectType); 1984 return M4VSS3GPP_ERR_INVALID_VIDEO_EFFECT_TYPE; 1985 } 1986 } 1987 /** 1988 * RC Updates pTempPlaneIn and pTempPlaneOut depending on current effect */ 1989 if (((i % 2 == 0) && (NumActiveEffects % 2 == 0)) 1990 || ((i % 2 != 0) && (NumActiveEffects % 2 != 0))) 1991 { 1992 pPlaneTempIn = pTempYuvPlane; 1993 pPlaneTempOut = pPlaneOut; 1994 } 1995 else 1996 { 1997 pPlaneTempIn = pPlaneOut; 1998 pPlaneTempOut = pTempYuvPlane; 1999 } 2000 } 2001 2002 for(i=0; i<3; i++) { 2003 if(pTempYuvPlane[i].pac_data != M4OSA_NULL) { 2004 free(pTempYuvPlane[i].pac_data); 2005 pTempYuvPlane[i].pac_data = M4OSA_NULL; 2006 } 2007 } 2008 2009 /** 2010 * Return */ 2011 M4OSA_TRACE3_0("M4VSS3GPP_intApplyVideoEffect: returning M4NO_ERROR"); 2012 return M4NO_ERROR; 2013 } 2014 2015 /** 2016 ****************************************************************************** 2017 * M4OSA_ERR M4VSS3GPP_intVideoTransition() 2018 * @brief Apply video transition effect pC1+pC2->pPlaneOut 2019 * @param pC (IN/OUT) Internal edit context 2020 * @param pOutputPlanes (IN/OUT) Output raw YUV420 image 2021 * @return M4NO_ERROR: No error 2022 ****************************************************************************** 2023 */ 2024 static M4OSA_ERR 2025 M4VSS3GPP_intVideoTransition( M4VSS3GPP_InternalEditContext *pC, 2026 M4VIFI_ImagePlane *pPlaneOut ) 2027 { 2028 M4OSA_ERR err; 2029 M4OSA_Int32 iProgress; 2030 M4VSS3GPP_ExternalProgress extProgress; 2031 M4VIFI_ImagePlane *pPlane; 2032 M4OSA_Int32 i; 2033 const M4OSA_Int32 iDur = (M4OSA_Int32)pC-> 2034 pTransitionList[pC->uiCurrentClip].uiTransitionDuration; 2035 2036 /** 2037 * Compute how far from the end cut we are, in clip-base time. 2038 * It is done with integers because the offset and begin cut have been rounded already. */ 2039 // Decorrelate input and output encoding timestamp to handle encoder prefetch 2040 iProgress = (M4OSA_Int32)((M4OSA_Double)pC->pC1->iEndTime) - pC->ewc.dInputVidCts + 2041 ((M4OSA_Double)pC->pC1->iVoffset); 2042 /** 2043 * We must remove the duration of one frame, else we would almost never reach the end 2044 * (It's kind of a "pile and intervals" issue). */ 2045 iProgress -= (M4OSA_Int32)pC->dOutputFrameDuration; 2046 2047 if( iProgress < 0 ) /**< Sanity checks */ 2048 { 2049 iProgress = 0; 2050 } 2051 2052 /** 2053 * Compute where we are in the transition, on a base 1000 */ 2054 iProgress = ( ( iDur - iProgress) * 1000) / iDur; 2055 2056 /** 2057 * Sanity checks */ 2058 if( iProgress < 0 ) 2059 { 2060 iProgress = 0; 2061 } 2062 else if( iProgress > 1000 ) 2063 { 2064 iProgress = 1000; 2065 } 2066 2067 switch( pC->pTransitionList[pC->uiCurrentClip].TransitionBehaviour ) 2068 { 2069 case M4VSS3GPP_TransitionBehaviour_SpeedUp: 2070 iProgress = ( iProgress * iProgress) / 1000; 2071 break; 2072 2073 case M4VSS3GPP_TransitionBehaviour_Linear: 2074 /*do nothing*/ 2075 break; 2076 2077 case M4VSS3GPP_TransitionBehaviour_SpeedDown: 2078 iProgress = (M4OSA_Int32)(sqrt(iProgress * 1000)); 2079 break; 2080 2081 case M4VSS3GPP_TransitionBehaviour_SlowMiddle: 2082 if( iProgress < 500 ) 2083 { 2084 iProgress = (M4OSA_Int32)(sqrt(iProgress * 500)); 2085 } 2086 else 2087 { 2088 iProgress = 2089 (M4OSA_Int32)(( ( ( iProgress - 500) * (iProgress - 500)) 2090 / 500) + 500); 2091 } 2092 break; 2093 2094 case M4VSS3GPP_TransitionBehaviour_FastMiddle: 2095 if( iProgress < 500 ) 2096 { 2097 iProgress = (M4OSA_Int32)(( iProgress * iProgress) / 500); 2098 } 2099 else 2100 { 2101 iProgress = (M4OSA_Int32)(sqrt(( iProgress - 500) * 500) + 500); 2102 } 2103 break; 2104 2105 default: 2106 /*do nothing*/ 2107 break; 2108 } 2109 2110 switch( pC->pTransitionList[pC->uiCurrentClip].VideoTransitionType ) 2111 { 2112 case M4VSS3GPP_kVideoTransitionType_CrossFade: 2113 /** 2114 * Apply the transition effect */ 2115 err = M4VIFI_ImageBlendingonYUV420(M4OSA_NULL, 2116 (M4ViComImagePlane *)pC->yuv1, 2117 (M4ViComImagePlane *)pC->yuv2, 2118 (M4ViComImagePlane *)pPlaneOut, iProgress); 2119 2120 if( M4NO_ERROR != err ) 2121 { 2122 M4OSA_TRACE1_1( 2123 "M4VSS3GPP_intVideoTransition:\ 2124 M4VIFI_ImageBlendingonYUV420 returns error 0x%x,\ 2125 returning M4VSS3GPP_ERR_TRANSITION_FILTER_ERROR", 2126 err); 2127 return M4VSS3GPP_ERR_TRANSITION_FILTER_ERROR; 2128 } 2129 break; 2130 2131 case M4VSS3GPP_kVideoTransitionType_None: 2132 /** 2133 * This is a stupid-non optimized version of the None transition... 2134 * We copy the YUV frame */ 2135 if( iProgress < 500 ) /**< first half of transition */ 2136 { 2137 pPlane = pC->yuv1; 2138 } 2139 else /**< second half of transition */ 2140 { 2141 pPlane = pC->yuv2; 2142 } 2143 /** 2144 * Copy the input YUV frames */ 2145 i = 3; 2146 2147 while( i-- > 0 ) 2148 { 2149 memcpy((void *)pPlaneOut[i].pac_data, 2150 (void *)pPlane[i].pac_data, 2151 pPlaneOut[i].u_stride * pPlaneOut[i].u_height); 2152 } 2153 break; 2154 2155 default: 2156 if( pC->pTransitionList[pC->uiCurrentClip].VideoTransitionType 2157 >= M4VSS3GPP_kVideoTransitionType_External ) 2158 { 2159 /** 2160 * Set the progress info provided to the external function */ 2161 extProgress.uiProgress = (M4OSA_UInt32)iProgress; 2162 // Decorrelate input and output encoding timestamp to handle encoder prefetch 2163 extProgress.uiOutputTime = (M4OSA_UInt32)pC->ewc.dInputVidCts; 2164 extProgress.uiClipTime = extProgress.uiOutputTime - pC->pC1->iVoffset; 2165 2166 err = pC->pTransitionList[pC-> 2167 uiCurrentClip].ExtVideoTransitionFct( 2168 pC->pTransitionList[pC-> 2169 uiCurrentClip].pExtVideoTransitionFctCtxt, 2170 pC->yuv1, pC->yuv2, pPlaneOut, &extProgress, 2171 pC->pTransitionList[pC-> 2172 uiCurrentClip].VideoTransitionType 2173 - M4VSS3GPP_kVideoTransitionType_External); 2174 2175 if( M4NO_ERROR != err ) 2176 { 2177 M4OSA_TRACE1_1( 2178 "M4VSS3GPP_intVideoTransition:\ 2179 External video transition function returns 0x%x!", 2180 err); 2181 return err; 2182 } 2183 break; 2184 } 2185 else 2186 { 2187 M4OSA_TRACE1_1( 2188 "M4VSS3GPP_intVideoTransition: unknown transition type (0x%x),\ 2189 returning M4VSS3GPP_ERR_INVALID_VIDEO_TRANSITION_TYPE", 2190 pC->pTransitionList[pC->uiCurrentClip].VideoTransitionType); 2191 return M4VSS3GPP_ERR_INVALID_VIDEO_TRANSITION_TYPE; 2192 } 2193 } 2194 2195 /** 2196 * Return */ 2197 M4OSA_TRACE3_0("M4VSS3GPP_intVideoTransition: returning M4NO_ERROR"); 2198 return M4NO_ERROR; 2199 } 2200 2201 /** 2202 ****************************************************************************** 2203 * M4OSA_Void M4VSS3GPP_intUpdateTimeInfo() 2204 * @brief Update bit stream time info by Counter Time System to be compliant with 2205 * players using bit stream time info 2206 * @note H263 uses an absolute time counter unlike MPEG4 which uses Group Of Vops 2207 * (GOV, see the standard) 2208 * @param pC (IN/OUT) returns time updated video AU, 2209 * the offset between system and video time (MPEG4 only) 2210 * and the state of the current clip (MPEG4 only) 2211 * @return nothing 2212 ****************************************************************************** 2213 */ 2214 static M4OSA_Void 2215 M4VSS3GPP_intUpdateTimeInfo( M4VSS3GPP_InternalEditContext *pC, 2216 M4SYS_AccessUnit *pAU ) 2217 { 2218 M4OSA_UInt8 uiTmp; 2219 M4OSA_UInt32 uiCts = 0; 2220 M4OSA_MemAddr8 pTmp; 2221 M4OSA_UInt32 uiAdd; 2222 M4OSA_UInt32 uiCurrGov; 2223 M4OSA_Int8 iDiff; 2224 2225 M4VSS3GPP_ClipContext *pClipCtxt = pC->pC1; 2226 M4OSA_Int32 *pOffset = &(pC->ewc.iMpeg4GovOffset); 2227 2228 /** 2229 * Set H263 time counter from system time */ 2230 if( M4SYS_kH263 == pAU->stream->streamType ) 2231 { 2232 uiTmp = (M4OSA_UInt8)((M4OSA_UInt32)( ( pAU->CTS * 30) / 1001 + 0.5) 2233 % M4VSS3GPP_EDIT_H263_MODULO_TIME); 2234 M4VSS3GPP_intSetH263TimeCounter((M4OSA_MemAddr8)(pAU->dataAddress), 2235 uiTmp); 2236 } 2237 /* 2238 * Set MPEG4 GOV time counter regarding video and system time */ 2239 else if( M4SYS_kMPEG_4 == pAU->stream->streamType ) 2240 { 2241 /* 2242 * If GOV. 2243 * beware of little/big endian! */ 2244 /* correction: read 8 bits block instead of one 32 bits block */ 2245 M4OSA_UInt8 *temp8 = (M4OSA_UInt8 *)(pAU->dataAddress); 2246 M4OSA_UInt32 temp32 = 0; 2247 2248 temp32 = ( 0x000000ff & (M4OSA_UInt32)(*temp8)) 2249 + (0x0000ff00 & ((M4OSA_UInt32)(*(temp8 + 1))) << 8) 2250 + (0x00ff0000 & ((M4OSA_UInt32)(*(temp8 + 2))) << 16) 2251 + (0xff000000 & ((M4OSA_UInt32)(*(temp8 + 3))) << 24); 2252 2253 M4OSA_TRACE3_2("RC: Temp32: 0x%x, dataAddress: 0x%x\n", temp32, 2254 *(pAU->dataAddress)); 2255 2256 if( M4VSS3GPP_EDIT_GOV_HEADER == temp32 ) 2257 { 2258 pTmp = 2259 (M4OSA_MemAddr8)(pAU->dataAddress 2260 + 1); /**< Jump to the time code (just after the 32 bits header) */ 2261 uiAdd = (M4OSA_UInt32)(pAU->CTS)+( *pOffset); 2262 2263 switch( pClipCtxt->bMpeg4GovState ) 2264 { 2265 case M4OSA_FALSE: /*< INIT */ 2266 { 2267 /* video time = ceil (system time + offset) */ 2268 uiCts = ( uiAdd + 999) / 1000; 2269 2270 /* offset update */ 2271 ( *pOffset) += (( uiCts * 1000) - uiAdd); 2272 2273 /* Save values */ 2274 pClipCtxt->uiMpeg4PrevGovValueSet = uiCts; 2275 2276 /* State to 'first' */ 2277 pClipCtxt->bMpeg4GovState = M4OSA_TRUE; 2278 } 2279 break; 2280 2281 case M4OSA_TRUE: /*< UPDATE */ 2282 { 2283 /* Get current Gov value */ 2284 M4VSS3GPP_intGetMPEG4Gov(pTmp, &uiCurrGov); 2285 2286 /* video time = floor or ceil (system time + offset) */ 2287 uiCts = (uiAdd / 1000); 2288 iDiff = (M4OSA_Int8)(uiCurrGov 2289 - pClipCtxt->uiMpeg4PrevGovValueGet - uiCts 2290 + pClipCtxt->uiMpeg4PrevGovValueSet); 2291 2292 /* ceiling */ 2293 if( iDiff > 0 ) 2294 { 2295 uiCts += (M4OSA_UInt32)(iDiff); 2296 2297 /* offset update */ 2298 ( *pOffset) += (( uiCts * 1000) - uiAdd); 2299 } 2300 2301 /* Save values */ 2302 pClipCtxt->uiMpeg4PrevGovValueGet = uiCurrGov; 2303 pClipCtxt->uiMpeg4PrevGovValueSet = uiCts; 2304 } 2305 break; 2306 } 2307 2308 M4VSS3GPP_intSetMPEG4Gov(pTmp, uiCts); 2309 } 2310 } 2311 return; 2312 } 2313 2314 /** 2315 ****************************************************************************** 2316 * M4OSA_Void M4VSS3GPP_intCheckVideoEffects() 2317 * @brief Check which video effect must be applied at the current time 2318 ****************************************************************************** 2319 */ 2320 static M4OSA_Void 2321 M4VSS3GPP_intCheckVideoEffects( M4VSS3GPP_InternalEditContext *pC, 2322 M4OSA_UInt8 uiClipNumber ) 2323 { 2324 M4OSA_UInt8 uiClipIndex; 2325 M4OSA_UInt8 uiFxIndex, i; 2326 M4VSS3GPP_ClipContext *pClip; 2327 M4VSS3GPP_EffectSettings *pFx; 2328 M4OSA_Int32 Off, BC, EC; 2329 // Decorrelate input and output encoding timestamp to handle encoder prefetch 2330 M4OSA_Int32 t = (M4OSA_Int32)pC->ewc.dInputVidCts; 2331 2332 uiClipIndex = pC->uiCurrentClip; 2333 if (uiClipNumber == 1) { 2334 pClip = pC->pC1; 2335 pC->bClip1ActiveFramingEffect = M4OSA_FALSE; 2336 } else { 2337 pClip = pC->pC2; 2338 pC->bClip2ActiveFramingEffect = M4OSA_FALSE; 2339 } 2340 /** 2341 * Shortcuts for code readability */ 2342 Off = pClip->iVoffset; 2343 BC = pClip->iActualVideoBeginCut; 2344 EC = pClip->iEndTime; 2345 2346 i = 0; 2347 2348 for ( uiFxIndex = 0; uiFxIndex < pC->nbEffects; uiFxIndex++ ) 2349 { 2350 /** Shortcut, reverse order because of priority between effects(EndEffect always clean )*/ 2351 pFx = &(pC->pEffectsList[pC->nbEffects - 1 - uiFxIndex]); 2352 2353 if( M4VSS3GPP_kVideoEffectType_None != pFx->VideoEffectType ) 2354 { 2355 /** 2356 * Check if there is actually a video effect */ 2357 2358 if(uiClipNumber ==1) 2359 { 2360 /**< Are we after the start time of the effect? 2361 * or Are we into the effect duration? 2362 */ 2363 if ( (t >= (M4OSA_Int32)(pFx->uiStartTime)) && 2364 (t <= (M4OSA_Int32)(pFx->uiStartTime + pFx->uiDuration)) ) { 2365 /** 2366 * Set the active effect(s) */ 2367 pC->pActiveEffectsList[i] = pC->nbEffects-1-uiFxIndex; 2368 2369 /** 2370 * Update counter of active effects */ 2371 i++; 2372 if (pFx->xVSS.pFramingBuffer != M4OSA_NULL) { 2373 pC->bClip1ActiveFramingEffect = M4OSA_TRUE; 2374 } 2375 2376 /** 2377 * For all external effects set this flag to true. */ 2378 if(pFx->VideoEffectType > M4VSS3GPP_kVideoEffectType_External) 2379 { 2380 pC->m_bClipExternalHasStarted = M4OSA_TRUE; 2381 } 2382 } 2383 2384 } 2385 else 2386 { 2387 /**< Are we into the effect duration? */ 2388 if ( ((M4OSA_Int32)(t + pC->pTransitionList[uiClipIndex].uiTransitionDuration) 2389 >= (M4OSA_Int32)(pFx->uiStartTime)) 2390 && ( (M4OSA_Int32)(t + pC->pTransitionList[uiClipIndex].uiTransitionDuration) 2391 <= (M4OSA_Int32)(pFx->uiStartTime + pFx->uiDuration)) ) { 2392 /** 2393 * Set the active effect(s) */ 2394 pC->pActiveEffectsList1[i] = pC->nbEffects-1-uiFxIndex; 2395 2396 /** 2397 * Update counter of active effects */ 2398 i++; 2399 if (pFx->xVSS.pFramingBuffer != M4OSA_NULL) { 2400 pC->bClip2ActiveFramingEffect = M4OSA_TRUE; 2401 } 2402 /** 2403 * For all external effects set this flag to true. */ 2404 if(pFx->VideoEffectType > M4VSS3GPP_kVideoEffectType_External) 2405 { 2406 pC->m_bClipExternalHasStarted = M4OSA_TRUE; 2407 } 2408 2409 /** 2410 * The third effect has the highest priority, then the second one, then the first one. 2411 * Hence, as soon as we found an active effect, we can get out of this loop */ 2412 } 2413 } 2414 if (M4VIDEOEDITING_kH264 != 2415 pC->pC1->pSettings->ClipProperties.VideoStreamType) { 2416 2417 // For Mpeg4 and H263 clips, full decode encode not required 2418 pC->m_bClipExternalHasStarted = M4OSA_FALSE; 2419 } 2420 } 2421 } 2422 if(1==uiClipNumber) 2423 { 2424 /** 2425 * Save number of active effects */ 2426 pC->nbActiveEffects = i; 2427 } 2428 else 2429 { 2430 pC->nbActiveEffects1 = i; 2431 } 2432 2433 /** 2434 * Change the absolut time to clip related time */ 2435 t -= Off; 2436 2437 /** 2438 * Check if we are on the begin cut (for clip1 only) */ 2439 if( ( 0 != BC) && (t == BC) && (1 == uiClipNumber) ) 2440 { 2441 pC->bClip1AtBeginCut = M4OSA_TRUE; 2442 } 2443 else 2444 { 2445 pC->bClip1AtBeginCut = M4OSA_FALSE; 2446 } 2447 2448 return; 2449 } 2450 2451 /** 2452 ****************************************************************************** 2453 * M4OSA_ERR M4VSS3GPP_intCreateVideoEncoder() 2454 * @brief Creates the video encoder 2455 * @note 2456 ****************************************************************************** 2457 */ 2458 M4OSA_ERR M4VSS3GPP_intCreateVideoEncoder( M4VSS3GPP_InternalEditContext *pC ) 2459 { 2460 M4OSA_ERR err; 2461 M4ENCODER_AdvancedParams EncParams; 2462 2463 /** 2464 * Simulate a writer interface with our specific function */ 2465 pC->ewc.OurWriterDataInterface.pProcessAU = 2466 M4VSS3GPP_intProcessAU; /**< This function is VSS 3GPP specific, 2467 but it follow the writer interface */ 2468 pC->ewc.OurWriterDataInterface.pStartAU = 2469 M4VSS3GPP_intStartAU; /**< This function is VSS 3GPP specific, 2470 but it follow the writer interface */ 2471 pC->ewc.OurWriterDataInterface.pWriterContext = 2472 (M4WRITER_Context) 2473 pC; /**< We give the internal context as writer context */ 2474 2475 /** 2476 * Get the encoder interface, if not already done */ 2477 if( M4OSA_NULL == pC->ShellAPI.pVideoEncoderGlobalFcts ) 2478 { 2479 err = M4VSS3GPP_setCurrentVideoEncoder(&pC->ShellAPI, 2480 pC->ewc.VideoStreamType); 2481 M4OSA_TRACE1_1( 2482 "M4VSS3GPP_intCreateVideoEncoder: setCurrentEncoder returns 0x%x", 2483 err); 2484 M4ERR_CHECK_RETURN(err); 2485 } 2486 2487 /** 2488 * Set encoder shell parameters according to VSS settings */ 2489 2490 /* Common parameters */ 2491 EncParams.InputFormat = M4ENCODER_kIYUV420; 2492 EncParams.FrameWidth = pC->ewc.uiVideoWidth; 2493 EncParams.FrameHeight = pC->ewc.uiVideoHeight; 2494 EncParams.uiTimeScale = pC->ewc.uiVideoTimeScale; 2495 2496 if( pC->bIsMMS == M4OSA_FALSE ) 2497 { 2498 /* No strict regulation in video editor */ 2499 /* Because of the effects and transitions we should allow more flexibility */ 2500 /* Also it prevents to drop important frames (with a bad result on sheduling and 2501 block effetcs) */ 2502 EncParams.bInternalRegulation = M4OSA_FALSE; 2503 // Variable framerate is not supported by StageFright encoders 2504 EncParams.FrameRate = M4ENCODER_k30_FPS; 2505 } 2506 else 2507 { 2508 /* In case of MMS mode, we need to enable bitrate regulation to be sure */ 2509 /* to reach the targeted output file size */ 2510 EncParams.bInternalRegulation = M4OSA_TRUE; 2511 EncParams.FrameRate = pC->MMSvideoFramerate; 2512 } 2513 2514 /** 2515 * Other encoder settings (defaults) */ 2516 EncParams.uiHorizontalSearchRange = 0; /* use default */ 2517 EncParams.uiVerticalSearchRange = 0; /* use default */ 2518 EncParams.bErrorResilience = M4OSA_FALSE; /* no error resilience */ 2519 EncParams.uiIVopPeriod = 0; /* use default */ 2520 EncParams.uiMotionEstimationTools = 0; /* M4V_MOTION_EST_TOOLS_ALL */ 2521 EncParams.bAcPrediction = M4OSA_TRUE; /* use AC prediction */ 2522 EncParams.uiStartingQuantizerValue = 10; /* initial QP = 10 */ 2523 EncParams.bDataPartitioning = M4OSA_FALSE; /* no data partitioning */ 2524 2525 /** 2526 * Set the video profile and level */ 2527 EncParams.videoProfile = pC->ewc.outputVideoProfile; 2528 EncParams.videoLevel= pC->ewc.outputVideoLevel; 2529 2530 switch ( pC->ewc.VideoStreamType ) 2531 { 2532 case M4SYS_kH263: 2533 2534 EncParams.Format = M4ENCODER_kH263; 2535 2536 EncParams.uiStartingQuantizerValue = 10; 2537 EncParams.uiRateFactor = 1; /* default */ 2538 2539 EncParams.bErrorResilience = M4OSA_FALSE; 2540 EncParams.bDataPartitioning = M4OSA_FALSE; 2541 break; 2542 2543 case M4SYS_kMPEG_4: 2544 2545 EncParams.Format = M4ENCODER_kMPEG4; 2546 2547 EncParams.uiStartingQuantizerValue = 8; 2548 EncParams.uiRateFactor = (M4OSA_UInt8)(( pC->dOutputFrameDuration 2549 * pC->ewc.uiVideoTimeScale) / 1000.0 + 0.5); 2550 2551 if( EncParams.uiRateFactor == 0 ) 2552 EncParams.uiRateFactor = 1; /* default */ 2553 2554 if( M4OSA_FALSE == pC->ewc.bVideoDataPartitioning ) 2555 { 2556 EncParams.bErrorResilience = M4OSA_FALSE; 2557 EncParams.bDataPartitioning = M4OSA_FALSE; 2558 } 2559 else 2560 { 2561 EncParams.bErrorResilience = M4OSA_TRUE; 2562 EncParams.bDataPartitioning = M4OSA_TRUE; 2563 } 2564 break; 2565 2566 case M4SYS_kH264: 2567 M4OSA_TRACE1_0("M4VSS3GPP_intCreateVideoEncoder: M4SYS_H264"); 2568 2569 EncParams.Format = M4ENCODER_kH264; 2570 2571 EncParams.uiStartingQuantizerValue = 10; 2572 EncParams.uiRateFactor = 1; /* default */ 2573 2574 EncParams.bErrorResilience = M4OSA_FALSE; 2575 EncParams.bDataPartitioning = M4OSA_FALSE; 2576 //EncParams.FrameRate = M4VIDEOEDITING_k5_FPS; 2577 break; 2578 2579 default: 2580 M4OSA_TRACE1_1( 2581 "M4VSS3GPP_intCreateVideoEncoder: Unknown videoStreamType 0x%x", 2582 pC->ewc.VideoStreamType); 2583 return M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT; 2584 } 2585 2586 if( pC->bIsMMS == M4OSA_FALSE ) 2587 { 2588 EncParams.Bitrate = pC->xVSS.outputVideoBitrate; 2589 2590 } 2591 else 2592 { 2593 EncParams.Bitrate = pC->uiMMSVideoBitrate; /* RC */ 2594 EncParams.uiTimeScale = 0; /* We let the encoder choose the timescale */ 2595 } 2596 2597 M4OSA_TRACE1_0("M4VSS3GPP_intCreateVideoEncoder: calling encoder pFctInit"); 2598 /** 2599 * Init the video encoder (advanced settings version of the encoder Open function) */ 2600 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctInit(&pC->ewc.pEncContext, 2601 &pC->ewc.OurWriterDataInterface, M4VSS3GPP_intVPP, pC, 2602 pC->ShellAPI.pCurrentVideoEncoderExternalAPI, 2603 pC->ShellAPI.pCurrentVideoEncoderUserData); 2604 2605 if( M4NO_ERROR != err ) 2606 { 2607 M4OSA_TRACE1_1( 2608 "M4VSS3GPP_intCreateVideoEncoder: pVideoEncoderGlobalFcts->pFctInit returns 0x%x", 2609 err); 2610 return err; 2611 } 2612 2613 pC->ewc.encoderState = M4VSS3GPP_kEncoderClosed; 2614 M4OSA_TRACE1_0("M4VSS3GPP_intCreateVideoEncoder: calling encoder pFctOpen"); 2615 2616 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctOpen(pC->ewc.pEncContext, 2617 &pC->ewc.WriterVideoAU, &EncParams); 2618 2619 if( M4NO_ERROR != err ) 2620 { 2621 M4OSA_TRACE1_1( 2622 "M4VSS3GPP_intCreateVideoEncoder: pVideoEncoderGlobalFcts->pFctOpen returns 0x%x", 2623 err); 2624 return err; 2625 } 2626 2627 pC->ewc.encoderState = M4VSS3GPP_kEncoderStopped; 2628 M4OSA_TRACE1_0( 2629 "M4VSS3GPP_intCreateVideoEncoder: calling encoder pFctStart"); 2630 2631 if( M4OSA_NULL != pC->ShellAPI.pVideoEncoderGlobalFcts->pFctStart ) 2632 { 2633 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctStart( 2634 pC->ewc.pEncContext); 2635 2636 if( M4NO_ERROR != err ) 2637 { 2638 M4OSA_TRACE1_1( 2639 "M4VSS3GPP_intCreateVideoEncoder: pVideoEncoderGlobalFcts->pFctStart returns 0x%x", 2640 err); 2641 return err; 2642 } 2643 } 2644 2645 pC->ewc.encoderState = M4VSS3GPP_kEncoderRunning; 2646 2647 /** 2648 * Return */ 2649 M4OSA_TRACE3_0("M4VSS3GPP_intCreateVideoEncoder: returning M4NO_ERROR"); 2650 return M4NO_ERROR; 2651 } 2652 2653 /** 2654 ****************************************************************************** 2655 * M4OSA_ERR M4VSS3GPP_intDestroyVideoEncoder() 2656 * @brief Destroy the video encoder 2657 * @note 2658 ****************************************************************************** 2659 */ 2660 M4OSA_ERR M4VSS3GPP_intDestroyVideoEncoder( M4VSS3GPP_InternalEditContext *pC ) 2661 { 2662 M4OSA_ERR err = M4NO_ERROR; 2663 2664 if( M4OSA_NULL != pC->ewc.pEncContext ) 2665 { 2666 if( M4VSS3GPP_kEncoderRunning == pC->ewc.encoderState ) 2667 { 2668 if( pC->ShellAPI.pVideoEncoderGlobalFcts->pFctStop != M4OSA_NULL ) 2669 { 2670 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctStop( 2671 pC->ewc.pEncContext); 2672 2673 if( M4NO_ERROR != err ) 2674 { 2675 M4OSA_TRACE1_1( 2676 "M4VSS3GPP_intDestroyVideoEncoder:\ 2677 pVideoEncoderGlobalFcts->pFctStop returns 0x%x", 2678 err); 2679 /* Well... how the heck do you handle a failed cleanup? */ 2680 } 2681 } 2682 2683 pC->ewc.encoderState = M4VSS3GPP_kEncoderStopped; 2684 } 2685 2686 /* Has the encoder actually been opened? Don't close it if that's not the case. */ 2687 if( M4VSS3GPP_kEncoderStopped == pC->ewc.encoderState ) 2688 { 2689 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctClose( 2690 pC->ewc.pEncContext); 2691 2692 if( M4NO_ERROR != err ) 2693 { 2694 M4OSA_TRACE1_1( 2695 "M4VSS3GPP_intDestroyVideoEncoder:\ 2696 pVideoEncoderGlobalFcts->pFctClose returns 0x%x", 2697 err); 2698 /* Well... how the heck do you handle a failed cleanup? */ 2699 } 2700 2701 pC->ewc.encoderState = M4VSS3GPP_kEncoderClosed; 2702 } 2703 2704 err = pC->ShellAPI.pVideoEncoderGlobalFcts->pFctCleanup( 2705 pC->ewc.pEncContext); 2706 2707 if( M4NO_ERROR != err ) 2708 { 2709 M4OSA_TRACE1_1( 2710 "M4VSS3GPP_intDestroyVideoEncoder:\ 2711 pVideoEncoderGlobalFcts->pFctCleanup returns 0x%x!", 2712 err); 2713 /**< We do not return the error here because we still have stuff to free */ 2714 } 2715 2716 pC->ewc.encoderState = M4VSS3GPP_kNoEncoder; 2717 /** 2718 * Reset variable */ 2719 pC->ewc.pEncContext = M4OSA_NULL; 2720 } 2721 2722 M4OSA_TRACE3_1("M4VSS3GPP_intDestroyVideoEncoder: returning 0x%x", err); 2723 return err; 2724 } 2725 2726 /** 2727 ****************************************************************************** 2728 * M4OSA_Void M4VSS3GPP_intSetH263TimeCounter() 2729 * @brief Modify the time counter of the given H263 video AU 2730 * @note 2731 * @param pAuDataBuffer (IN/OUT) H263 Video AU to modify 2732 * @param uiCts (IN) New time counter value 2733 * @return nothing 2734 ****************************************************************************** 2735 */ 2736 static M4OSA_Void M4VSS3GPP_intSetH263TimeCounter( M4OSA_MemAddr8 pAuDataBuffer, 2737 M4OSA_UInt8 uiCts ) 2738 { 2739 /* 2740 * The H263 time counter is 8 bits located on the "x" below: 2741 * 2742 * |--------|--------|--------|--------| 2743 * ???????? ???????? ??????xx xxxxxx?? 2744 */ 2745 2746 /** 2747 * Write the 2 bits on the third byte */ 2748 pAuDataBuffer[2] = ( pAuDataBuffer[2] & 0xFC) | (( uiCts >> 6) & 0x3); 2749 2750 /** 2751 * Write the 6 bits on the fourth byte */ 2752 pAuDataBuffer[3] = ( ( uiCts << 2) & 0xFC) | (pAuDataBuffer[3] & 0x3); 2753 2754 return; 2755 } 2756 2757 /** 2758 ****************************************************************************** 2759 * M4OSA_Void M4VSS3GPP_intSetMPEG4Gov() 2760 * @brief Modify the time info from Group Of VOP video AU 2761 * @note 2762 * @param pAuDataBuffer (IN) MPEG4 Video AU to modify 2763 * @param uiCtsSec (IN) New GOV time info in second unit 2764 * @return nothing 2765 ****************************************************************************** 2766 */ 2767 static M4OSA_Void M4VSS3GPP_intSetMPEG4Gov( M4OSA_MemAddr8 pAuDataBuffer, 2768 M4OSA_UInt32 uiCtsSec ) 2769 { 2770 /* 2771 * The MPEG-4 time code length is 18 bits: 2772 * 2773 * hh mm marker ss 2774 * xxxxx|xxx xxx 1 xxxx xx ?????? 2775 * |----- ---|--- - ----|-- ------| 2776 */ 2777 M4OSA_UInt8 uiHh; 2778 M4OSA_UInt8 uiMm; 2779 M4OSA_UInt8 uiSs; 2780 M4OSA_UInt8 uiTmp; 2781 2782 /** 2783 * Write the 2 last bits ss */ 2784 uiSs = (M4OSA_UInt8)(uiCtsSec % 60); /**< modulo part */ 2785 pAuDataBuffer[2] = (( ( uiSs & 0x03) << 6) | (pAuDataBuffer[2] & 0x3F)); 2786 2787 if( uiCtsSec < 60 ) 2788 { 2789 /** 2790 * Write the 3 last bits of mm, the marker bit (0x10 */ 2791 pAuDataBuffer[1] = (( 0x10) | (uiSs >> 2)); 2792 2793 /** 2794 * Write the 5 bits of hh and 3 of mm (out of 6) */ 2795 pAuDataBuffer[0] = 0; 2796 } 2797 else 2798 { 2799 /** 2800 * Write the 3 last bits of mm, the marker bit (0x10 */ 2801 uiTmp = (M4OSA_UInt8)(uiCtsSec / 60); /**< integer part */ 2802 uiMm = (M4OSA_UInt8)(uiTmp % 60); 2803 pAuDataBuffer[1] = (( uiMm << 5) | (0x10) | (uiSs >> 2)); 2804 2805 if( uiTmp < 60 ) 2806 { 2807 /** 2808 * Write the 5 bits of hh and 3 of mm (out of 6) */ 2809 pAuDataBuffer[0] = ((uiMm >> 3)); 2810 } 2811 else 2812 { 2813 /** 2814 * Write the 5 bits of hh and 3 of mm (out of 6) */ 2815 uiHh = (M4OSA_UInt8)(uiTmp / 60); 2816 pAuDataBuffer[0] = (( uiHh << 3) | (uiMm >> 3)); 2817 } 2818 } 2819 return; 2820 } 2821 2822 /** 2823 ****************************************************************************** 2824 * M4OSA_Void M4VSS3GPP_intGetMPEG4Gov() 2825 * @brief Get the time info from Group Of VOP video AU 2826 * @note 2827 * @param pAuDataBuffer (IN) MPEG4 Video AU to modify 2828 * @param pCtsSec (OUT) Current GOV time info in second unit 2829 * @return nothing 2830 ****************************************************************************** 2831 */ 2832 static M4OSA_Void M4VSS3GPP_intGetMPEG4Gov( M4OSA_MemAddr8 pAuDataBuffer, 2833 M4OSA_UInt32 *pCtsSec ) 2834 { 2835 /* 2836 * The MPEG-4 time code length is 18 bits: 2837 * 2838 * hh mm marker ss 2839 * xxxxx|xxx xxx 1 xxxx xx ?????? 2840 * |----- ---|--- - ----|-- ------| 2841 */ 2842 M4OSA_UInt8 uiHh; 2843 M4OSA_UInt8 uiMm; 2844 M4OSA_UInt8 uiSs; 2845 M4OSA_UInt8 uiTmp; 2846 M4OSA_UInt32 uiCtsSec; 2847 2848 /** 2849 * Read ss */ 2850 uiSs = (( pAuDataBuffer[2] & 0xC0) >> 6); 2851 uiTmp = (( pAuDataBuffer[1] & 0x0F) << 2); 2852 uiCtsSec = uiSs + uiTmp; 2853 2854 /** 2855 * Read mm */ 2856 uiMm = (( pAuDataBuffer[1] & 0xE0) >> 5); 2857 uiTmp = (( pAuDataBuffer[0] & 0x07) << 3); 2858 uiMm = uiMm + uiTmp; 2859 uiCtsSec = ( uiMm * 60) + uiCtsSec; 2860 2861 /** 2862 * Read hh */ 2863 uiHh = (( pAuDataBuffer[0] & 0xF8) >> 3); 2864 2865 if( uiHh ) 2866 { 2867 uiCtsSec = ( uiHh * 3600) + uiCtsSec; 2868 } 2869 2870 /* 2871 * in sec */ 2872 *pCtsSec = uiCtsSec; 2873 2874 return; 2875 } 2876 2877 /** 2878 ****************************************************************************** 2879 * M4OSA_ERR M4VSS3GPP_intAllocateYUV420() 2880 * @brief Allocate the three YUV 4:2:0 planes 2881 * @note 2882 * @param pPlanes (IN/OUT) valid pointer to 3 M4VIFI_ImagePlane structures 2883 * @param uiWidth (IN) Image width 2884 * @param uiHeight(IN) Image height 2885 ****************************************************************************** 2886 */ 2887 static M4OSA_ERR M4VSS3GPP_intAllocateYUV420( M4VIFI_ImagePlane *pPlanes, 2888 M4OSA_UInt32 uiWidth, M4OSA_UInt32 uiHeight ) 2889 { 2890 if (pPlanes == M4OSA_NULL) { 2891 M4OSA_TRACE1_0("M4VSS3GPP_intAllocateYUV420: Invalid pPlanes pointer"); 2892 return M4ERR_PARAMETER; 2893 } 2894 /* if the buffer is not NULL and same size with target size, 2895 * do not malloc again*/ 2896 if (pPlanes[0].pac_data != M4OSA_NULL && 2897 pPlanes[0].u_width == uiWidth && 2898 pPlanes[0].u_height == uiHeight) { 2899 return M4NO_ERROR; 2900 } 2901 2902 pPlanes[0].u_width = uiWidth; 2903 pPlanes[0].u_height = uiHeight; 2904 pPlanes[0].u_stride = uiWidth; 2905 pPlanes[0].u_topleft = 0; 2906 2907 if (pPlanes[0].pac_data != M4OSA_NULL) { 2908 free(pPlanes[0].pac_data); 2909 pPlanes[0].pac_data = M4OSA_NULL; 2910 } 2911 pPlanes[0].pac_data = (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(pPlanes[0].u_stride 2912 * pPlanes[0].u_height, M4VSS3GPP, (M4OSA_Char *)"pPlanes[0].pac_data"); 2913 2914 if( M4OSA_NULL == pPlanes[0].pac_data ) 2915 { 2916 M4OSA_TRACE1_0( 2917 "M4VSS3GPP_intAllocateYUV420: unable to allocate pPlanes[0].pac_data,\ 2918 returning M4ERR_ALLOC"); 2919 return M4ERR_ALLOC; 2920 } 2921 2922 pPlanes[1].u_width = pPlanes[0].u_width >> 1; 2923 pPlanes[1].u_height = pPlanes[0].u_height >> 1; 2924 pPlanes[1].u_stride = pPlanes[1].u_width; 2925 pPlanes[1].u_topleft = 0; 2926 if (pPlanes[1].pac_data != M4OSA_NULL) { 2927 free(pPlanes[1].pac_data); 2928 pPlanes[1].pac_data = M4OSA_NULL; 2929 } 2930 pPlanes[1].pac_data = (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(pPlanes[1].u_stride 2931 * pPlanes[1].u_height, M4VSS3GPP,(M4OSA_Char *) "pPlanes[1].pac_data"); 2932 2933 if( M4OSA_NULL == pPlanes[1].pac_data ) 2934 { 2935 M4OSA_TRACE1_0( 2936 "M4VSS3GPP_intAllocateYUV420: unable to allocate pPlanes[1].pac_data,\ 2937 returning M4ERR_ALLOC"); 2938 free((void *)pPlanes[0].pac_data); 2939 pPlanes[0].pac_data = M4OSA_NULL; 2940 return M4ERR_ALLOC; 2941 } 2942 2943 pPlanes[2].u_width = pPlanes[1].u_width; 2944 pPlanes[2].u_height = pPlanes[1].u_height; 2945 pPlanes[2].u_stride = pPlanes[2].u_width; 2946 pPlanes[2].u_topleft = 0; 2947 if (pPlanes[2].pac_data != M4OSA_NULL) { 2948 free(pPlanes[2].pac_data); 2949 pPlanes[2].pac_data = M4OSA_NULL; 2950 } 2951 pPlanes[2].pac_data = (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(pPlanes[2].u_stride 2952 * pPlanes[2].u_height, M4VSS3GPP, (M4OSA_Char *)"pPlanes[2].pac_data"); 2953 2954 if( M4OSA_NULL == pPlanes[2].pac_data ) 2955 { 2956 M4OSA_TRACE1_0( 2957 "M4VSS3GPP_intAllocateYUV420: unable to allocate pPlanes[2].pac_data,\ 2958 returning M4ERR_ALLOC"); 2959 free((void *)pPlanes[0].pac_data); 2960 free((void *)pPlanes[1].pac_data); 2961 pPlanes[0].pac_data = M4OSA_NULL; 2962 pPlanes[1].pac_data = M4OSA_NULL; 2963 return M4ERR_ALLOC; 2964 } 2965 2966 memset((void *)pPlanes[0].pac_data, 0, pPlanes[0].u_stride*pPlanes[0].u_height); 2967 memset((void *)pPlanes[1].pac_data, 0, pPlanes[1].u_stride*pPlanes[1].u_height); 2968 memset((void *)pPlanes[2].pac_data, 0, pPlanes[2].u_stride*pPlanes[2].u_height); 2969 /** 2970 * Return */ 2971 M4OSA_TRACE3_0("M4VSS3GPP_intAllocateYUV420: returning M4NO_ERROR"); 2972 return M4NO_ERROR; 2973 } 2974 2975 /** 2976 ****************************************************************************** 2977 * M4OSA_ERR M4VSS3GPP_internalConvertAndResizeARGB8888toYUV420(M4OSA_Void* pFileIn, 2978 * M4OSA_FileReadPointer* pFileReadPtr, 2979 * M4VIFI_ImagePlane* pImagePlanes, 2980 * M4OSA_UInt32 width, 2981 * M4OSA_UInt32 height); 2982 * @brief It Coverts and resizes a ARGB8888 image to YUV420 2983 * @note 2984 * @param pFileIn (IN) The ARGB888 input file 2985 * @param pFileReadPtr (IN) Pointer on filesystem functions 2986 * @param pImagePlanes (IN/OUT) Pointer on YUV420 output planes allocated by the user. 2987 * ARGB8888 image will be converted and resized to output 2988 * YUV420 plane size 2989 * @param width (IN) width of the ARGB8888 2990 * @param height (IN) height of the ARGB8888 2991 * @return M4NO_ERROR: No error 2992 * @return M4ERR_ALLOC: memory error 2993 * @return M4ERR_PARAMETER: At least one of the function parameters is null 2994 ****************************************************************************** 2995 */ 2996 2997 M4OSA_ERR M4VSS3GPP_internalConvertAndResizeARGB8888toYUV420(M4OSA_Void* pFileIn, 2998 M4OSA_FileReadPointer* pFileReadPtr, 2999 M4VIFI_ImagePlane* pImagePlanes, 3000 M4OSA_UInt32 width,M4OSA_UInt32 height) { 3001 M4OSA_Context pARGBIn; 3002 M4VIFI_ImagePlane rgbPlane1 ,rgbPlane2; 3003 M4OSA_UInt32 frameSize_argb = width * height * 4; 3004 M4OSA_UInt32 frameSize_rgb888 = width * height * 3; 3005 M4OSA_UInt32 i = 0,j= 0; 3006 M4OSA_ERR err = M4NO_ERROR; 3007 3008 M4OSA_UInt8 *pArgbPlane = 3009 (M4OSA_UInt8*) M4OSA_32bitAlignedMalloc(frameSize_argb, 3010 M4VS, (M4OSA_Char*)"argb data"); 3011 if (pArgbPlane == M4OSA_NULL) { 3012 M4OSA_TRACE1_0("M4VSS3GPP_internalConvertAndResizeARGB8888toYUV420: \ 3013 Failed to allocate memory for ARGB plane"); 3014 return M4ERR_ALLOC; 3015 } 3016 3017 /* Get file size */ 3018 err = pFileReadPtr->openRead(&pARGBIn, pFileIn, M4OSA_kFileRead); 3019 if (err != M4NO_ERROR) { 3020 M4OSA_TRACE1_2("M4VSS3GPP_internalConvertAndResizeARGB8888toYUV420 : \ 3021 Can not open input ARGB8888 file %s, error: 0x%x\n",pFileIn, err); 3022 free(pArgbPlane); 3023 pArgbPlane = M4OSA_NULL; 3024 goto cleanup; 3025 } 3026 3027 err = pFileReadPtr->readData(pARGBIn,(M4OSA_MemAddr8)pArgbPlane, 3028 &frameSize_argb); 3029 if (err != M4NO_ERROR) { 3030 M4OSA_TRACE1_2("M4VSS3GPP_internalConvertAndResizeARGB8888toYUV420 \ 3031 Can not read ARGB8888 file %s, error: 0x%x\n",pFileIn, err); 3032 pFileReadPtr->closeRead(pARGBIn); 3033 free(pArgbPlane); 3034 pArgbPlane = M4OSA_NULL; 3035 goto cleanup; 3036 } 3037 3038 err = pFileReadPtr->closeRead(pARGBIn); 3039 if(err != M4NO_ERROR) { 3040 M4OSA_TRACE1_2("M4VSS3GPP_internalConvertAndResizeARGB8888toYUV420 \ 3041 Can not close ARGB8888 file %s, error: 0x%x\n",pFileIn, err); 3042 free(pArgbPlane); 3043 pArgbPlane = M4OSA_NULL; 3044 goto cleanup; 3045 } 3046 3047 rgbPlane1.pac_data = 3048 (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(frameSize_rgb888, 3049 M4VS, (M4OSA_Char*)"RGB888 plane1"); 3050 if(rgbPlane1.pac_data == M4OSA_NULL) { 3051 M4OSA_TRACE1_0("M4VSS3GPP_internalConvertAndResizeARGB8888toYUV420 \ 3052 Failed to allocate memory for rgb plane1"); 3053 free(pArgbPlane); 3054 return M4ERR_ALLOC; 3055 } 3056 3057 rgbPlane1.u_height = height; 3058 rgbPlane1.u_width = width; 3059 rgbPlane1.u_stride = width*3; 3060 rgbPlane1.u_topleft = 0; 3061 3062 3063 /** Remove the alpha channel */ 3064 for (i=0, j = 0; i < frameSize_argb; i++) { 3065 if ((i % 4) == 0) continue; 3066 rgbPlane1.pac_data[j] = pArgbPlane[i]; 3067 j++; 3068 } 3069 free(pArgbPlane); 3070 3071 /** 3072 * Check if resizing is required with color conversion */ 3073 if(width != pImagePlanes->u_width || height != pImagePlanes->u_height) { 3074 3075 frameSize_rgb888 = pImagePlanes->u_width * pImagePlanes->u_height * 3; 3076 rgbPlane2.pac_data = 3077 (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(frameSize_rgb888, M4VS, 3078 (M4OSA_Char*)"rgb Plane2"); 3079 if(rgbPlane2.pac_data == M4OSA_NULL) { 3080 M4OSA_TRACE1_0("Failed to allocate memory for rgb plane2"); 3081 free(rgbPlane1.pac_data); 3082 return M4ERR_ALLOC; 3083 } 3084 rgbPlane2.u_height = pImagePlanes->u_height; 3085 rgbPlane2.u_width = pImagePlanes->u_width; 3086 rgbPlane2.u_stride = pImagePlanes->u_width*3; 3087 rgbPlane2.u_topleft = 0; 3088 3089 /* Resizing */ 3090 err = M4VIFI_ResizeBilinearRGB888toRGB888(M4OSA_NULL, 3091 &rgbPlane1, &rgbPlane2); 3092 free(rgbPlane1.pac_data); 3093 if(err != M4NO_ERROR) { 3094 M4OSA_TRACE1_1("error resizing RGB888 to RGB888: 0x%x\n", err); 3095 free(rgbPlane2.pac_data); 3096 return err; 3097 } 3098 3099 /*Converting Resized RGB888 to YUV420 */ 3100 err = M4VIFI_RGB888toYUV420(M4OSA_NULL, &rgbPlane2, pImagePlanes); 3101 free(rgbPlane2.pac_data); 3102 if(err != M4NO_ERROR) { 3103 M4OSA_TRACE1_1("error converting from RGB888 to YUV: 0x%x\n", err); 3104 return err; 3105 } 3106 } else { 3107 err = M4VIFI_RGB888toYUV420(M4OSA_NULL, &rgbPlane1, pImagePlanes); 3108 if(err != M4NO_ERROR) { 3109 M4OSA_TRACE1_1("error when converting from RGB to YUV: 0x%x\n", err); 3110 } 3111 free(rgbPlane1.pac_data); 3112 } 3113 cleanup: 3114 M4OSA_TRACE3_0("M4VSS3GPP_internalConvertAndResizeARGB8888toYUV420 exit"); 3115 return err; 3116 } 3117 3118 M4OSA_ERR M4VSS3GPP_intApplyRenderingMode(M4VSS3GPP_InternalEditContext *pC, 3119 M4xVSS_MediaRendering renderingMode, 3120 M4VIFI_ImagePlane* pInplane, 3121 M4VIFI_ImagePlane* pOutplane) { 3122 3123 M4OSA_ERR err = M4NO_ERROR; 3124 M4AIR_Params airParams; 3125 M4VIFI_ImagePlane pImagePlanesTemp[3]; 3126 M4OSA_UInt32 i = 0; 3127 3128 if (renderingMode == M4xVSS_kBlackBorders) { 3129 memset((void *)pOutplane[0].pac_data, Y_PLANE_BORDER_VALUE, 3130 (pOutplane[0].u_height*pOutplane[0].u_stride)); 3131 memset((void *)pOutplane[1].pac_data, U_PLANE_BORDER_VALUE, 3132 (pOutplane[1].u_height*pOutplane[1].u_stride)); 3133 memset((void *)pOutplane[2].pac_data, V_PLANE_BORDER_VALUE, 3134 (pOutplane[2].u_height*pOutplane[2].u_stride)); 3135 } 3136 3137 if (renderingMode == M4xVSS_kResizing) { 3138 /** 3139 * Call the resize filter. 3140 * From the intermediate frame to the encoder image plane */ 3141 err = M4VIFI_ResizeBilinearYUV420toYUV420(M4OSA_NULL, 3142 pInplane, pOutplane); 3143 if (M4NO_ERROR != err) { 3144 M4OSA_TRACE1_1("M4VSS3GPP_intApplyRenderingMode: \ 3145 M4ViFilResizeBilinearYUV420toYUV420 returns 0x%x!", err); 3146 return err; 3147 } 3148 } else { 3149 M4VIFI_ImagePlane* pPlaneTemp = M4OSA_NULL; 3150 M4OSA_UInt8* pOutPlaneY = 3151 pOutplane[0].pac_data + pOutplane[0].u_topleft; 3152 M4OSA_UInt8* pOutPlaneU = 3153 pOutplane[1].pac_data + pOutplane[1].u_topleft; 3154 M4OSA_UInt8* pOutPlaneV = 3155 pOutplane[2].pac_data + pOutplane[2].u_topleft; 3156 M4OSA_UInt8* pInPlaneY = M4OSA_NULL; 3157 M4OSA_UInt8* pInPlaneU = M4OSA_NULL; 3158 M4OSA_UInt8* pInPlaneV = M4OSA_NULL; 3159 3160 /* To keep media aspect ratio*/ 3161 /* Initialize AIR Params*/ 3162 airParams.m_inputCoord.m_x = 0; 3163 airParams.m_inputCoord.m_y = 0; 3164 airParams.m_inputSize.m_height = pInplane->u_height; 3165 airParams.m_inputSize.m_width = pInplane->u_width; 3166 airParams.m_outputSize.m_width = pOutplane->u_width; 3167 airParams.m_outputSize.m_height = pOutplane->u_height; 3168 airParams.m_bOutputStripe = M4OSA_FALSE; 3169 airParams.m_outputOrientation = M4COMMON_kOrientationTopLeft; 3170 3171 /** 3172 Media rendering: Black borders*/ 3173 if (renderingMode == M4xVSS_kBlackBorders) { 3174 pImagePlanesTemp[0].u_width = pOutplane[0].u_width; 3175 pImagePlanesTemp[0].u_height = pOutplane[0].u_height; 3176 pImagePlanesTemp[0].u_stride = pOutplane[0].u_width; 3177 pImagePlanesTemp[0].u_topleft = 0; 3178 3179 pImagePlanesTemp[1].u_width = pOutplane[1].u_width; 3180 pImagePlanesTemp[1].u_height = pOutplane[1].u_height; 3181 pImagePlanesTemp[1].u_stride = pOutplane[1].u_width; 3182 pImagePlanesTemp[1].u_topleft = 0; 3183 3184 pImagePlanesTemp[2].u_width = pOutplane[2].u_width; 3185 pImagePlanesTemp[2].u_height = pOutplane[2].u_height; 3186 pImagePlanesTemp[2].u_stride = pOutplane[2].u_width; 3187 pImagePlanesTemp[2].u_topleft = 0; 3188 3189 /** 3190 * Allocates plan in local image plane structure */ 3191 pImagePlanesTemp[0].pac_data = 3192 (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc( 3193 pImagePlanesTemp[0].u_width * pImagePlanesTemp[0].u_height, 3194 M4VS, (M4OSA_Char *)"pImagePlaneTemp Y") ; 3195 if (pImagePlanesTemp[0].pac_data == M4OSA_NULL) { 3196 M4OSA_TRACE1_0("M4VSS3GPP_intApplyRenderingMode: Alloc Error"); 3197 return M4ERR_ALLOC; 3198 } 3199 pImagePlanesTemp[1].pac_data = 3200 (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc( 3201 pImagePlanesTemp[1].u_width * pImagePlanesTemp[1].u_height, 3202 M4VS, (M4OSA_Char *)"pImagePlaneTemp U") ; 3203 if (pImagePlanesTemp[1].pac_data == M4OSA_NULL) { 3204 M4OSA_TRACE1_0("M4VSS3GPP_intApplyRenderingMode: Alloc Error"); 3205 free(pImagePlanesTemp[0].pac_data); 3206 return M4ERR_ALLOC; 3207 } 3208 pImagePlanesTemp[2].pac_data = 3209 (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc( 3210 pImagePlanesTemp[2].u_width * pImagePlanesTemp[2].u_height, 3211 M4VS, (M4OSA_Char *)"pImagePlaneTemp V") ; 3212 if (pImagePlanesTemp[2].pac_data == M4OSA_NULL) { 3213 M4OSA_TRACE1_0("M4VSS3GPP_intApplyRenderingMode: Alloc Error"); 3214 free(pImagePlanesTemp[0].pac_data); 3215 free(pImagePlanesTemp[1].pac_data); 3216 return M4ERR_ALLOC; 3217 } 3218 3219 pInPlaneY = pImagePlanesTemp[0].pac_data ; 3220 pInPlaneU = pImagePlanesTemp[1].pac_data ; 3221 pInPlaneV = pImagePlanesTemp[2].pac_data ; 3222 3223 memset((void *)pImagePlanesTemp[0].pac_data, Y_PLANE_BORDER_VALUE, 3224 (pImagePlanesTemp[0].u_height*pImagePlanesTemp[0].u_stride)); 3225 memset((void *)pImagePlanesTemp[1].pac_data, U_PLANE_BORDER_VALUE, 3226 (pImagePlanesTemp[1].u_height*pImagePlanesTemp[1].u_stride)); 3227 memset((void *)pImagePlanesTemp[2].pac_data, V_PLANE_BORDER_VALUE, 3228 (pImagePlanesTemp[2].u_height*pImagePlanesTemp[2].u_stride)); 3229 3230 M4OSA_UInt32 height = 3231 (pInplane->u_height * pOutplane->u_width) /pInplane->u_width; 3232 3233 if (height <= pOutplane->u_height) { 3234 /** 3235 * Black borders will be on the top and the bottom side */ 3236 airParams.m_outputSize.m_width = pOutplane->u_width; 3237 airParams.m_outputSize.m_height = height; 3238 /** 3239 * Number of lines at the top */ 3240 pImagePlanesTemp[0].u_topleft = 3241 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanesTemp[0].u_height - 3242 airParams.m_outputSize.m_height)>>1)) * 3243 pImagePlanesTemp[0].u_stride; 3244 pImagePlanesTemp[0].u_height = airParams.m_outputSize.m_height; 3245 pImagePlanesTemp[1].u_topleft = 3246 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanesTemp[1].u_height - 3247 (airParams.m_outputSize.m_height>>1)))>>1) * 3248 pImagePlanesTemp[1].u_stride; 3249 pImagePlanesTemp[1].u_height = 3250 airParams.m_outputSize.m_height>>1; 3251 pImagePlanesTemp[2].u_topleft = 3252 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanesTemp[2].u_height - 3253 (airParams.m_outputSize.m_height>>1)))>>1) * 3254 pImagePlanesTemp[2].u_stride; 3255 pImagePlanesTemp[2].u_height = 3256 airParams.m_outputSize.m_height>>1; 3257 } else { 3258 /** 3259 * Black borders will be on the left and right side */ 3260 airParams.m_outputSize.m_height = pOutplane->u_height; 3261 airParams.m_outputSize.m_width = 3262 (M4OSA_UInt32)((pInplane->u_width * pOutplane->u_height)/pInplane->u_height); 3263 3264 pImagePlanesTemp[0].u_topleft = 3265 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanesTemp[0].u_width - 3266 airParams.m_outputSize.m_width)>>1)); 3267 pImagePlanesTemp[0].u_width = airParams.m_outputSize.m_width; 3268 pImagePlanesTemp[1].u_topleft = 3269 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanesTemp[1].u_width - 3270 (airParams.m_outputSize.m_width>>1)))>>1); 3271 pImagePlanesTemp[1].u_width = airParams.m_outputSize.m_width>>1; 3272 pImagePlanesTemp[2].u_topleft = 3273 (M4xVSS_ABS((M4OSA_Int32)(pImagePlanesTemp[2].u_width - 3274 (airParams.m_outputSize.m_width>>1)))>>1); 3275 pImagePlanesTemp[2].u_width = airParams.m_outputSize.m_width>>1; 3276 } 3277 3278 /** 3279 * Width and height have to be even */ 3280 airParams.m_outputSize.m_width = 3281 (airParams.m_outputSize.m_width>>1)<<1; 3282 airParams.m_outputSize.m_height = 3283 (airParams.m_outputSize.m_height>>1)<<1; 3284 airParams.m_inputSize.m_width = 3285 (airParams.m_inputSize.m_width>>1)<<1; 3286 airParams.m_inputSize.m_height = 3287 (airParams.m_inputSize.m_height>>1)<<1; 3288 pImagePlanesTemp[0].u_width = 3289 (pImagePlanesTemp[0].u_width>>1)<<1; 3290 pImagePlanesTemp[1].u_width = 3291 (pImagePlanesTemp[1].u_width>>1)<<1; 3292 pImagePlanesTemp[2].u_width = 3293 (pImagePlanesTemp[2].u_width>>1)<<1; 3294 pImagePlanesTemp[0].u_height = 3295 (pImagePlanesTemp[0].u_height>>1)<<1; 3296 pImagePlanesTemp[1].u_height = 3297 (pImagePlanesTemp[1].u_height>>1)<<1; 3298 pImagePlanesTemp[2].u_height = 3299 (pImagePlanesTemp[2].u_height>>1)<<1; 3300 3301 /** 3302 * Check that values are coherent */ 3303 if (airParams.m_inputSize.m_height == 3304 airParams.m_outputSize.m_height) { 3305 airParams.m_inputSize.m_width = 3306 airParams.m_outputSize.m_width; 3307 } else if (airParams.m_inputSize.m_width == 3308 airParams.m_outputSize.m_width) { 3309 airParams.m_inputSize.m_height = 3310 airParams.m_outputSize.m_height; 3311 } 3312 pPlaneTemp = pImagePlanesTemp; 3313 } 3314 3315 /** 3316 * Media rendering: Cropping*/ 3317 if (renderingMode == M4xVSS_kCropping) { 3318 airParams.m_outputSize.m_height = pOutplane->u_height; 3319 airParams.m_outputSize.m_width = pOutplane->u_width; 3320 if ((airParams.m_outputSize.m_height * 3321 airParams.m_inputSize.m_width)/airParams.m_outputSize.m_width < 3322 airParams.m_inputSize.m_height) { 3323 /* Height will be cropped */ 3324 airParams.m_inputSize.m_height = 3325 (M4OSA_UInt32)((airParams.m_outputSize.m_height * 3326 airParams.m_inputSize.m_width)/airParams.m_outputSize.m_width); 3327 airParams.m_inputSize.m_height = 3328 (airParams.m_inputSize.m_height>>1)<<1; 3329 airParams.m_inputCoord.m_y = 3330 (M4OSA_Int32)((M4OSA_Int32)((pInplane->u_height - 3331 airParams.m_inputSize.m_height))>>1); 3332 } else { 3333 /* Width will be cropped */ 3334 airParams.m_inputSize.m_width = 3335 (M4OSA_UInt32)((airParams.m_outputSize.m_width * 3336 airParams.m_inputSize.m_height)/airParams.m_outputSize.m_height); 3337 airParams.m_inputSize.m_width = 3338 (airParams.m_inputSize.m_width>>1)<<1; 3339 airParams.m_inputCoord.m_x = 3340 (M4OSA_Int32)((M4OSA_Int32)((pInplane->u_width - 3341 airParams.m_inputSize.m_width))>>1); 3342 } 3343 pPlaneTemp = pOutplane; 3344 } 3345 /** 3346 * Call AIR functions */ 3347 if (M4OSA_NULL == pC->m_air_context) { 3348 err = M4AIR_create(&pC->m_air_context, M4AIR_kYUV420P); 3349 if(err != M4NO_ERROR) { 3350 M4OSA_TRACE1_1("M4VSS3GPP_intApplyRenderingMode: \ 3351 M4AIR_create returned error 0x%x", err); 3352 goto cleanUp; 3353 } 3354 } 3355 3356 err = M4AIR_configure(pC->m_air_context, &airParams); 3357 if (err != M4NO_ERROR) { 3358 M4OSA_TRACE1_1("M4VSS3GPP_intApplyRenderingMode: \ 3359 Error when configuring AIR: 0x%x", err); 3360 M4AIR_cleanUp(pC->m_air_context); 3361 goto cleanUp; 3362 } 3363 3364 err = M4AIR_get(pC->m_air_context, pInplane, pPlaneTemp); 3365 if (err != M4NO_ERROR) { 3366 M4OSA_TRACE1_1("M4VSS3GPP_intApplyRenderingMode: \ 3367 Error when getting AIR plane: 0x%x", err); 3368 M4AIR_cleanUp(pC->m_air_context); 3369 goto cleanUp; 3370 } 3371 3372 if (renderingMode == M4xVSS_kBlackBorders) { 3373 for (i=0; i<pOutplane[0].u_height; i++) { 3374 memcpy((void *)pOutPlaneY, (void *)pInPlaneY, 3375 pOutplane[0].u_width); 3376 pInPlaneY += pOutplane[0].u_width; 3377 pOutPlaneY += pOutplane[0].u_stride; 3378 } 3379 for (i=0; i<pOutplane[1].u_height; i++) { 3380 memcpy((void *)pOutPlaneU, (void *)pInPlaneU, 3381 pOutplane[1].u_width); 3382 pInPlaneU += pOutplane[1].u_width; 3383 pOutPlaneU += pOutplane[1].u_stride; 3384 } 3385 for (i=0; i<pOutplane[2].u_height; i++) { 3386 memcpy((void *)pOutPlaneV, (void *)pInPlaneV, 3387 pOutplane[2].u_width); 3388 pInPlaneV += pOutplane[2].u_width; 3389 pOutPlaneV += pOutplane[2].u_stride; 3390 } 3391 } 3392 } 3393 cleanUp: 3394 if (renderingMode == M4xVSS_kBlackBorders) { 3395 for (i=0; i<3; i++) { 3396 if (pImagePlanesTemp[i].pac_data != M4OSA_NULL) { 3397 free(pImagePlanesTemp[i].pac_data); 3398 pImagePlanesTemp[i].pac_data = M4OSA_NULL; 3399 } 3400 } 3401 } 3402 return err; 3403 } 3404 3405 M4OSA_ERR M4VSS3GPP_intSetYuv420PlaneFromARGB888 ( 3406 M4VSS3GPP_InternalEditContext *pC, 3407 M4VSS3GPP_ClipContext* pClipCtxt) { 3408 3409 M4OSA_ERR err= M4NO_ERROR; 3410 3411 // Allocate memory for YUV plane 3412 pClipCtxt->pPlaneYuv = 3413 (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc( 3414 3*sizeof(M4VIFI_ImagePlane), M4VS, 3415 (M4OSA_Char*)"pPlaneYuv"); 3416 3417 if (pClipCtxt->pPlaneYuv == M4OSA_NULL) { 3418 return M4ERR_ALLOC; 3419 } 3420 3421 pClipCtxt->pPlaneYuv[0].u_height = 3422 pClipCtxt->pSettings->ClipProperties.uiStillPicHeight; 3423 pClipCtxt->pPlaneYuv[0].u_width = 3424 pClipCtxt->pSettings->ClipProperties.uiStillPicWidth; 3425 pClipCtxt->pPlaneYuv[0].u_stride = pClipCtxt->pPlaneYuv[0].u_width; 3426 pClipCtxt->pPlaneYuv[0].u_topleft = 0; 3427 3428 pClipCtxt->pPlaneYuv[0].pac_data = 3429 (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc( 3430 pClipCtxt->pPlaneYuv[0].u_height * pClipCtxt->pPlaneYuv[0].u_width * 1.5, 3431 M4VS, (M4OSA_Char*)"imageClip YUV data"); 3432 if (pClipCtxt->pPlaneYuv[0].pac_data == M4OSA_NULL) { 3433 free(pClipCtxt->pPlaneYuv); 3434 return M4ERR_ALLOC; 3435 } 3436 3437 pClipCtxt->pPlaneYuv[1].u_height = pClipCtxt->pPlaneYuv[0].u_height >>1; 3438 pClipCtxt->pPlaneYuv[1].u_width = pClipCtxt->pPlaneYuv[0].u_width >> 1; 3439 pClipCtxt->pPlaneYuv[1].u_stride = pClipCtxt->pPlaneYuv[1].u_width; 3440 pClipCtxt->pPlaneYuv[1].u_topleft = 0; 3441 pClipCtxt->pPlaneYuv[1].pac_data = (M4VIFI_UInt8*)( 3442 pClipCtxt->pPlaneYuv[0].pac_data + 3443 pClipCtxt->pPlaneYuv[0].u_height * pClipCtxt->pPlaneYuv[0].u_width); 3444 3445 pClipCtxt->pPlaneYuv[2].u_height = pClipCtxt->pPlaneYuv[0].u_height >>1; 3446 pClipCtxt->pPlaneYuv[2].u_width = pClipCtxt->pPlaneYuv[0].u_width >> 1; 3447 pClipCtxt->pPlaneYuv[2].u_stride = pClipCtxt->pPlaneYuv[2].u_width; 3448 pClipCtxt->pPlaneYuv[2].u_topleft = 0; 3449 pClipCtxt->pPlaneYuv[2].pac_data = (M4VIFI_UInt8*)( 3450 pClipCtxt->pPlaneYuv[1].pac_data + 3451 pClipCtxt->pPlaneYuv[1].u_height * pClipCtxt->pPlaneYuv[1].u_width); 3452 3453 err = M4VSS3GPP_internalConvertAndResizeARGB8888toYUV420 ( 3454 pClipCtxt->pSettings->pFile, 3455 pC->pOsaFileReadPtr, 3456 pClipCtxt->pPlaneYuv, 3457 pClipCtxt->pSettings->ClipProperties.uiStillPicWidth, 3458 pClipCtxt->pSettings->ClipProperties.uiStillPicHeight); 3459 if (M4NO_ERROR != err) { 3460 free(pClipCtxt->pPlaneYuv[0].pac_data); 3461 free(pClipCtxt->pPlaneYuv); 3462 return err; 3463 } 3464 3465 // Set the YUV data to the decoder using setoption 3466 err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctSetOption ( 3467 pClipCtxt->pViDecCtxt, 3468 M4DECODER_kOptionID_DecYuvData, 3469 (M4OSA_DataOption)pClipCtxt->pPlaneYuv); 3470 if (M4NO_ERROR != err) { 3471 free(pClipCtxt->pPlaneYuv[0].pac_data); 3472 free(pClipCtxt->pPlaneYuv); 3473 return err; 3474 } 3475 3476 pClipCtxt->pSettings->ClipProperties.bSetImageData = M4OSA_TRUE; 3477 3478 // Allocate Yuv plane with effect 3479 pClipCtxt->pPlaneYuvWithEffect = 3480 (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc( 3481 3*sizeof(M4VIFI_ImagePlane), M4VS, 3482 (M4OSA_Char*)"pPlaneYuvWithEffect"); 3483 if (pClipCtxt->pPlaneYuvWithEffect == M4OSA_NULL) { 3484 free(pClipCtxt->pPlaneYuv[0].pac_data); 3485 free(pClipCtxt->pPlaneYuv); 3486 return M4ERR_ALLOC; 3487 } 3488 3489 pClipCtxt->pPlaneYuvWithEffect[0].u_height = pC->ewc.uiVideoHeight; 3490 pClipCtxt->pPlaneYuvWithEffect[0].u_width = pC->ewc.uiVideoWidth; 3491 pClipCtxt->pPlaneYuvWithEffect[0].u_stride = pC->ewc.uiVideoWidth; 3492 pClipCtxt->pPlaneYuvWithEffect[0].u_topleft = 0; 3493 3494 pClipCtxt->pPlaneYuvWithEffect[0].pac_data = 3495 (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc( 3496 pC->ewc.uiVideoHeight * pC->ewc.uiVideoWidth * 1.5, 3497 M4VS, (M4OSA_Char*)"imageClip YUV data"); 3498 if (pClipCtxt->pPlaneYuvWithEffect[0].pac_data == M4OSA_NULL) { 3499 free(pClipCtxt->pPlaneYuv[0].pac_data); 3500 free(pClipCtxt->pPlaneYuv); 3501 free(pClipCtxt->pPlaneYuvWithEffect); 3502 return M4ERR_ALLOC; 3503 } 3504 3505 pClipCtxt->pPlaneYuvWithEffect[1].u_height = 3506 pClipCtxt->pPlaneYuvWithEffect[0].u_height >>1; 3507 pClipCtxt->pPlaneYuvWithEffect[1].u_width = 3508 pClipCtxt->pPlaneYuvWithEffect[0].u_width >> 1; 3509 pClipCtxt->pPlaneYuvWithEffect[1].u_stride = 3510 pClipCtxt->pPlaneYuvWithEffect[1].u_width; 3511 pClipCtxt->pPlaneYuvWithEffect[1].u_topleft = 0; 3512 pClipCtxt->pPlaneYuvWithEffect[1].pac_data = (M4VIFI_UInt8*)( 3513 pClipCtxt->pPlaneYuvWithEffect[0].pac_data + 3514 pClipCtxt->pPlaneYuvWithEffect[0].u_height * pClipCtxt->pPlaneYuvWithEffect[0].u_width); 3515 3516 pClipCtxt->pPlaneYuvWithEffect[2].u_height = 3517 pClipCtxt->pPlaneYuvWithEffect[0].u_height >>1; 3518 pClipCtxt->pPlaneYuvWithEffect[2].u_width = 3519 pClipCtxt->pPlaneYuvWithEffect[0].u_width >> 1; 3520 pClipCtxt->pPlaneYuvWithEffect[2].u_stride = 3521 pClipCtxt->pPlaneYuvWithEffect[2].u_width; 3522 pClipCtxt->pPlaneYuvWithEffect[2].u_topleft = 0; 3523 pClipCtxt->pPlaneYuvWithEffect[2].pac_data = (M4VIFI_UInt8*)( 3524 pClipCtxt->pPlaneYuvWithEffect[1].pac_data + 3525 pClipCtxt->pPlaneYuvWithEffect[1].u_height * pClipCtxt->pPlaneYuvWithEffect[1].u_width); 3526 3527 err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctSetOption( 3528 pClipCtxt->pViDecCtxt, M4DECODER_kOptionID_YuvWithEffectContiguous, 3529 (M4OSA_DataOption)pClipCtxt->pPlaneYuvWithEffect); 3530 if (M4NO_ERROR != err) { 3531 free(pClipCtxt->pPlaneYuv[0].pac_data); 3532 free(pClipCtxt->pPlaneYuv); 3533 free(pClipCtxt->pPlaneYuvWithEffect); 3534 return err; 3535 } 3536 3537 return M4NO_ERROR; 3538 } 3539 3540 M4OSA_ERR M4VSS3GPP_intRenderFrameWithEffect(M4VSS3GPP_InternalEditContext *pC, 3541 M4VSS3GPP_ClipContext* pClipCtxt, 3542 M4_MediaTime ts, 3543 M4OSA_Bool bIsClip1, 3544 M4VIFI_ImagePlane *pResizePlane, 3545 M4VIFI_ImagePlane *pPlaneNoResize, 3546 M4VIFI_ImagePlane *pPlaneOut) { 3547 3548 M4OSA_ERR err = M4NO_ERROR; 3549 M4OSA_UInt8 numEffects = 0; 3550 M4VIFI_ImagePlane *pDecoderRenderFrame = M4OSA_NULL; 3551 M4OSA_UInt32 yuvFrameWidth = 0, yuvFrameHeight = 0; 3552 M4VIFI_ImagePlane* pTmp = M4OSA_NULL; 3553 M4VIFI_ImagePlane pTemp[3]; 3554 M4OSA_UInt8 i = 0; 3555 M4OSA_Bool bSkipFramingEffect = M4OSA_FALSE; 3556 3557 memset((void *)pTemp, 0, 3*sizeof(M4VIFI_ImagePlane)); 3558 /* Resize or rotate case */ 3559 if (M4OSA_NULL != pClipCtxt->m_pPreResizeFrame) { 3560 /** 3561 * If we do modify the image, we need an intermediate image plane */ 3562 err = M4VSS3GPP_intAllocateYUV420(pResizePlane, 3563 pClipCtxt->m_pPreResizeFrame[0].u_width, 3564 pClipCtxt->m_pPreResizeFrame[0].u_height); 3565 if (M4NO_ERROR != err) { 3566 M4OSA_TRACE1_1("M4VSS3GPP_intRenderFrameWithEffect: \ 3567 M4VSS3GPP_intAllocateYUV420 returns 0x%x", err); 3568 return err; 3569 } 3570 3571 if ((pClipCtxt->pSettings->FileType == 3572 M4VIDEOEDITING_kFileType_ARGB8888) && 3573 (pC->nbActiveEffects == 0) && 3574 (pClipCtxt->bGetYuvDataFromDecoder == M4OSA_FALSE)) { 3575 3576 err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctSetOption( 3577 pClipCtxt->pViDecCtxt, 3578 M4DECODER_kOptionID_EnableYuvWithEffect, 3579 (M4OSA_DataOption)M4OSA_TRUE); 3580 if (M4NO_ERROR == err) { 3581 pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctRender( 3582 pClipCtxt->pViDecCtxt, &ts, 3583 pClipCtxt->pPlaneYuvWithEffect, M4OSA_TRUE); 3584 } 3585 3586 } else { 3587 if (pClipCtxt->pSettings->FileType == 3588 M4VIDEOEDITING_kFileType_ARGB8888) { 3589 err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctSetOption( 3590 pClipCtxt->pViDecCtxt, 3591 M4DECODER_kOptionID_EnableYuvWithEffect, 3592 (M4OSA_DataOption)M4OSA_FALSE); 3593 } 3594 if (M4NO_ERROR == err) { 3595 err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctRender( 3596 pClipCtxt->pViDecCtxt, &ts, 3597 pClipCtxt->m_pPreResizeFrame, M4OSA_TRUE); 3598 } 3599 3600 } 3601 if (M4NO_ERROR != err) { 3602 M4OSA_TRACE1_1("M4VSS3GPP_intRenderFrameWithEffect: \ 3603 returns error 0x%x", err); 3604 return err; 3605 } 3606 3607 if (pClipCtxt->pSettings->FileType != 3608 M4VIDEOEDITING_kFileType_ARGB8888) { 3609 if (0 != pClipCtxt->pSettings->ClipProperties.videoRotationDegrees) { 3610 // Save width and height of un-rotated frame 3611 yuvFrameWidth = pClipCtxt->m_pPreResizeFrame[0].u_width; 3612 yuvFrameHeight = pClipCtxt->m_pPreResizeFrame[0].u_height; 3613 err = M4VSS3GPP_intRotateVideo(pClipCtxt->m_pPreResizeFrame, 3614 pClipCtxt->pSettings->ClipProperties.videoRotationDegrees); 3615 if (M4NO_ERROR != err) { 3616 M4OSA_TRACE1_1("M4VSS3GPP_intRenderFrameWithEffect: \ 3617 rotateVideo() returns error 0x%x", err); 3618 return err; 3619 } 3620 /* Set the new video size for temporary buffer */ 3621 M4VSS3GPP_intSetYUV420Plane(pResizePlane, 3622 pClipCtxt->m_pPreResizeFrame[0].u_width, 3623 pClipCtxt->m_pPreResizeFrame[0].u_height); 3624 } 3625 } 3626 3627 if (bIsClip1 == M4OSA_TRUE) { 3628 pC->bIssecondClip = M4OSA_FALSE; 3629 numEffects = pC->nbActiveEffects; 3630 } else { 3631 numEffects = pC->nbActiveEffects1; 3632 pC->bIssecondClip = M4OSA_TRUE; 3633 } 3634 3635 if ( numEffects > 0) { 3636 pClipCtxt->bGetYuvDataFromDecoder = M4OSA_TRUE; 3637 /* If video frame need to be resized or rotated, 3638 * then apply the overlay after the frame was rendered with rendering mode. 3639 * Here skip the framing(overlay) effect when applying video Effect. */ 3640 bSkipFramingEffect = M4OSA_TRUE; 3641 err = M4VSS3GPP_intApplyVideoEffect(pC, 3642 pClipCtxt->m_pPreResizeFrame, pResizePlane, bSkipFramingEffect); 3643 if (M4NO_ERROR != err) { 3644 M4OSA_TRACE1_1("M4VSS3GPP_intRenderFrameWithEffect: \ 3645 M4VSS3GPP_intApplyVideoEffect() err 0x%x", err); 3646 return err; 3647 } 3648 pDecoderRenderFrame= pResizePlane; 3649 } else { 3650 pDecoderRenderFrame = pClipCtxt->m_pPreResizeFrame; 3651 } 3652 /* Do rendering mode */ 3653 if ((pClipCtxt->bGetYuvDataFromDecoder == M4OSA_TRUE) || 3654 (pClipCtxt->pSettings->FileType != 3655 M4VIDEOEDITING_kFileType_ARGB8888)) { 3656 if (bIsClip1 == M4OSA_TRUE) { 3657 if (pC->bClip1ActiveFramingEffect == M4OSA_TRUE) { 3658 err = M4VSS3GPP_intAllocateYUV420(pTemp, 3659 pPlaneOut[0].u_width, pPlaneOut[0].u_height); 3660 if (M4NO_ERROR != err) { 3661 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: \ 3662 M4VSS3GPP_intAllocateYUV420 error 0x%x", err); 3663 pC->ewc.VppError = err; 3664 return M4NO_ERROR; 3665 } 3666 pTmp = pTemp; 3667 } else { 3668 pTmp = pC->yuv1; 3669 } 3670 err = M4VSS3GPP_intApplyRenderingMode (pC, 3671 pClipCtxt->pSettings->xVSS.MediaRendering, 3672 pDecoderRenderFrame,pTmp); 3673 } else { 3674 if (pC->bClip2ActiveFramingEffect == M4OSA_TRUE) { 3675 err = M4VSS3GPP_intAllocateYUV420(pTemp, 3676 pPlaneOut[0].u_width, pPlaneOut[0].u_height); 3677 if (M4NO_ERROR != err) { 3678 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: \ 3679 M4VSS3GPP_intAllocateYUV420 error 0x%x", err); 3680 pC->ewc.VppError = err; 3681 return M4NO_ERROR; 3682 } 3683 pTmp = pTemp; 3684 } else { 3685 pTmp = pC->yuv2; 3686 } 3687 err = M4VSS3GPP_intApplyRenderingMode (pC, 3688 pClipCtxt->pSettings->xVSS.MediaRendering, 3689 pDecoderRenderFrame,pTmp); 3690 } 3691 if (M4NO_ERROR != err) { 3692 M4OSA_TRACE1_1("M4VSS3GPP_intRenderFrameWithEffect: \ 3693 M4VSS3GPP_intApplyRenderingMode error 0x%x ", err); 3694 for (i=0; i<3; i++) { 3695 if (pTemp[i].pac_data != M4OSA_NULL) { 3696 free(pTemp[i].pac_data); 3697 pTemp[i].pac_data = M4OSA_NULL; 3698 } 3699 } 3700 return err; 3701 } 3702 /* Apply overlay if overlay exist*/ 3703 if (bIsClip1 == M4OSA_TRUE) { 3704 if (pC->bClip1ActiveFramingEffect == M4OSA_TRUE) { 3705 err = M4VSS3GPP_intApplyVideoOverlay(pC, 3706 pTemp, pC->yuv1); 3707 } 3708 pClipCtxt->lastDecodedPlane = pC->yuv1; 3709 } else { 3710 if (pC->bClip2ActiveFramingEffect == M4OSA_TRUE) { 3711 err = M4VSS3GPP_intApplyVideoOverlay(pC, 3712 pTemp, pC->yuv2); 3713 } 3714 pClipCtxt->lastDecodedPlane = pC->yuv2; 3715 } 3716 if (M4NO_ERROR != err) { 3717 M4OSA_TRACE1_1("M4VSS3GPP_intVPP: \ 3718 M4VSS3GPP_intApplyVideoOverlay) error 0x%x ", err); 3719 pC->ewc.VppError = err; 3720 for (i=0; i<3; i++) { 3721 if (pTemp[i].pac_data != M4OSA_NULL) { 3722 free(pTemp[i].pac_data); 3723 pTemp[i].pac_data = M4OSA_NULL; 3724 } 3725 } 3726 return M4NO_ERROR; 3727 } 3728 } else { 3729 pClipCtxt->lastDecodedPlane = pClipCtxt->pPlaneYuvWithEffect; 3730 } 3731 // free the temp buffer 3732 for (i=0; i<3; i++) { 3733 if (pTemp[i].pac_data != M4OSA_NULL) { 3734 free(pTemp[i].pac_data); 3735 pTemp[i].pac_data = M4OSA_NULL; 3736 } 3737 } 3738 3739 if ((pClipCtxt->pSettings->FileType == 3740 M4VIDEOEDITING_kFileType_ARGB8888) && 3741 (pC->nbActiveEffects == 0) && 3742 (pClipCtxt->bGetYuvDataFromDecoder == M4OSA_TRUE)) { 3743 if (bIsClip1 == M4OSA_TRUE) { 3744 err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctSetOption( 3745 pClipCtxt->pViDecCtxt, 3746 M4DECODER_kOptionID_YuvWithEffectNonContiguous, 3747 (M4OSA_DataOption)pC->yuv1); 3748 } else { 3749 err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctSetOption( 3750 pClipCtxt->pViDecCtxt, 3751 M4DECODER_kOptionID_YuvWithEffectNonContiguous, 3752 (M4OSA_DataOption)pC->yuv2); 3753 } 3754 if (M4NO_ERROR != err) { 3755 M4OSA_TRACE1_1("M4VSS3GPP_intRenderFrameWithEffect: \ 3756 null decoder setOption error 0x%x ", err); 3757 return err; 3758 } 3759 pClipCtxt->bGetYuvDataFromDecoder = M4OSA_FALSE; 3760 } 3761 3762 // Reset original width and height for resize frame plane 3763 if (0 != pClipCtxt->pSettings->ClipProperties.videoRotationDegrees && 3764 180 != pClipCtxt->pSettings->ClipProperties.videoRotationDegrees) { 3765 3766 M4VSS3GPP_intSetYUV420Plane(pClipCtxt->m_pPreResizeFrame, 3767 yuvFrameWidth, yuvFrameHeight); 3768 } 3769 3770 } else { 3771 /* No rotate or no resize case*/ 3772 if (bIsClip1 == M4OSA_TRUE) { 3773 numEffects = pC->nbActiveEffects; 3774 } else { 3775 numEffects = pC->nbActiveEffects1; 3776 } 3777 3778 if(numEffects > 0) { 3779 err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctRender( 3780 pClipCtxt->pViDecCtxt, &ts, pPlaneNoResize, M4OSA_TRUE); 3781 if (M4NO_ERROR != err) { 3782 M4OSA_TRACE1_1("M4VSS3GPP_intRenderFrameWithEffect: \ 3783 Render returns error 0x%x", err); 3784 return err; 3785 } 3786 3787 bSkipFramingEffect = M4OSA_FALSE; 3788 if (bIsClip1 == M4OSA_TRUE) { 3789 pC->bIssecondClip = M4OSA_FALSE; 3790 err = M4VSS3GPP_intApplyVideoEffect(pC, pPlaneNoResize, 3791 pC->yuv1, bSkipFramingEffect); 3792 pClipCtxt->lastDecodedPlane = pC->yuv1; 3793 } else { 3794 pC->bIssecondClip = M4OSA_TRUE; 3795 err = M4VSS3GPP_intApplyVideoEffect(pC, pPlaneNoResize, 3796 pC->yuv2, bSkipFramingEffect); 3797 pClipCtxt->lastDecodedPlane = pC->yuv2; 3798 } 3799 3800 if (M4NO_ERROR != err) { 3801 M4OSA_TRACE1_1("M4VSS3GPP_intRenderFrameWithEffect: \ 3802 M4VSS3GPP_intApplyVideoEffect error 0x%x", err); 3803 return err; 3804 } 3805 } else { 3806 3807 if (bIsClip1 == M4OSA_TRUE) { 3808 pTmp = pC->yuv1; 3809 } else { 3810 pTmp = pC->yuv2; 3811 } 3812 err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctRender( 3813 pClipCtxt->pViDecCtxt, &ts, pTmp, M4OSA_TRUE); 3814 if (M4NO_ERROR != err) { 3815 M4OSA_TRACE1_1("M4VSS3GPP_intRenderFrameWithEffect: \ 3816 Render returns error 0x%x,", err); 3817 return err; 3818 } 3819 pClipCtxt->lastDecodedPlane = pTmp; 3820 } 3821 pClipCtxt->iVideoRenderCts = (M4OSA_Int32)ts; 3822 } 3823 3824 return err; 3825 } 3826 3827 M4OSA_ERR M4VSS3GPP_intRotateVideo(M4VIFI_ImagePlane* pPlaneIn, 3828 M4OSA_UInt32 rotationDegree) { 3829 3830 M4OSA_ERR err = M4NO_ERROR; 3831 M4VIFI_ImagePlane outPlane[3]; 3832 3833 if (rotationDegree != 180) { 3834 // Swap width and height of in plane 3835 outPlane[0].u_width = pPlaneIn[0].u_height; 3836 outPlane[0].u_height = pPlaneIn[0].u_width; 3837 outPlane[0].u_stride = outPlane[0].u_width; 3838 outPlane[0].u_topleft = 0; 3839 outPlane[0].pac_data = (M4OSA_UInt8 *)M4OSA_32bitAlignedMalloc( 3840 (outPlane[0].u_stride*outPlane[0].u_height), M4VS, 3841 (M4OSA_Char*)("out Y plane for rotation")); 3842 if (outPlane[0].pac_data == M4OSA_NULL) { 3843 return M4ERR_ALLOC; 3844 } 3845 3846 outPlane[1].u_width = pPlaneIn[0].u_height/2; 3847 outPlane[1].u_height = pPlaneIn[0].u_width/2; 3848 outPlane[1].u_stride = outPlane[1].u_width; 3849 outPlane[1].u_topleft = 0; 3850 outPlane[1].pac_data = (M4OSA_UInt8 *)M4OSA_32bitAlignedMalloc( 3851 (outPlane[1].u_stride*outPlane[1].u_height), M4VS, 3852 (M4OSA_Char*)("out U plane for rotation")); 3853 if (outPlane[1].pac_data == M4OSA_NULL) { 3854 free((void *)outPlane[0].pac_data); 3855 return M4ERR_ALLOC; 3856 } 3857 3858 outPlane[2].u_width = pPlaneIn[0].u_height/2; 3859 outPlane[2].u_height = pPlaneIn[0].u_width/2; 3860 outPlane[2].u_stride = outPlane[2].u_width; 3861 outPlane[2].u_topleft = 0; 3862 outPlane[2].pac_data = (M4OSA_UInt8 *)M4OSA_32bitAlignedMalloc( 3863 (outPlane[2].u_stride*outPlane[2].u_height), M4VS, 3864 (M4OSA_Char*)("out V plane for rotation")); 3865 if (outPlane[2].pac_data == M4OSA_NULL) { 3866 free((void *)outPlane[0].pac_data); 3867 free((void *)outPlane[1].pac_data); 3868 return M4ERR_ALLOC; 3869 } 3870 } 3871 3872 switch(rotationDegree) { 3873 case 90: 3874 M4VIFI_Rotate90RightYUV420toYUV420(M4OSA_NULL, pPlaneIn, outPlane); 3875 break; 3876 3877 case 180: 3878 // In plane rotation, so planeOut = planeIn 3879 M4VIFI_Rotate180YUV420toYUV420(M4OSA_NULL, pPlaneIn, pPlaneIn); 3880 break; 3881 3882 case 270: 3883 M4VIFI_Rotate90LeftYUV420toYUV420(M4OSA_NULL, pPlaneIn, outPlane); 3884 break; 3885 3886 default: 3887 M4OSA_TRACE1_1("invalid rotation param %d", (int)rotationDegree); 3888 err = M4ERR_PARAMETER; 3889 break; 3890 } 3891 3892 if (rotationDegree != 180) { 3893 memset((void *)pPlaneIn[0].pac_data, 0, 3894 (pPlaneIn[0].u_width*pPlaneIn[0].u_height)); 3895 memset((void *)pPlaneIn[1].pac_data, 0, 3896 (pPlaneIn[1].u_width*pPlaneIn[1].u_height)); 3897 memset((void *)pPlaneIn[2].pac_data, 0, 3898 (pPlaneIn[2].u_width*pPlaneIn[2].u_height)); 3899 // Copy Y, U and V planes 3900 memcpy((void *)pPlaneIn[0].pac_data, (void *)outPlane[0].pac_data, 3901 (pPlaneIn[0].u_width*pPlaneIn[0].u_height)); 3902 memcpy((void *)pPlaneIn[1].pac_data, (void *)outPlane[1].pac_data, 3903 (pPlaneIn[1].u_width*pPlaneIn[1].u_height)); 3904 memcpy((void *)pPlaneIn[2].pac_data, (void *)outPlane[2].pac_data, 3905 (pPlaneIn[2].u_width*pPlaneIn[2].u_height)); 3906 3907 free((void *)outPlane[0].pac_data); 3908 free((void *)outPlane[1].pac_data); 3909 free((void *)outPlane[2].pac_data); 3910 3911 // Swap the width and height of the in plane 3912 uint32_t temp = 0; 3913 temp = pPlaneIn[0].u_width; 3914 pPlaneIn[0].u_width = pPlaneIn[0].u_height; 3915 pPlaneIn[0].u_height = temp; 3916 pPlaneIn[0].u_stride = pPlaneIn[0].u_width; 3917 3918 temp = pPlaneIn[1].u_width; 3919 pPlaneIn[1].u_width = pPlaneIn[1].u_height; 3920 pPlaneIn[1].u_height = temp; 3921 pPlaneIn[1].u_stride = pPlaneIn[1].u_width; 3922 3923 temp = pPlaneIn[2].u_width; 3924 pPlaneIn[2].u_width = pPlaneIn[2].u_height; 3925 pPlaneIn[2].u_height = temp; 3926 pPlaneIn[2].u_stride = pPlaneIn[2].u_width; 3927 } 3928 3929 return err; 3930 } 3931 3932 M4OSA_ERR M4VSS3GPP_intSetYUV420Plane(M4VIFI_ImagePlane* planeIn, 3933 M4OSA_UInt32 width, M4OSA_UInt32 height) { 3934 3935 M4OSA_ERR err = M4NO_ERROR; 3936 3937 if (planeIn == M4OSA_NULL) { 3938 M4OSA_TRACE1_0("NULL in plane, error"); 3939 return M4ERR_PARAMETER; 3940 } 3941 3942 planeIn[0].u_width = width; 3943 planeIn[0].u_height = height; 3944 planeIn[0].u_stride = planeIn[0].u_width; 3945 3946 planeIn[1].u_width = width/2; 3947 planeIn[1].u_height = height/2; 3948 planeIn[1].u_stride = planeIn[1].u_width; 3949 3950 planeIn[2].u_width = width/2; 3951 planeIn[2].u_height = height/2; 3952 planeIn[2].u_stride = planeIn[1].u_width; 3953 3954 return err; 3955 } 3956