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