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