Home | History | Annotate | Download | only in src
      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, &currentBitrate);
    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