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_EditAudio.c
19 * @brief    Video Studio Service 3GPP edit API implementation.
20 * @note
21 ******************************************************************************
22 */
23
24/****************/
25/*** Includes ***/
26/****************/
27
28#include "NXPSW_CompilerSwitches.h"
29/**
30 * Our header */
31#include "M4VSS3GPP_API.h"
32#include "M4VSS3GPP_InternalTypes.h"
33#include "M4VSS3GPP_InternalFunctions.h"
34#include "M4VSS3GPP_InternalConfig.h"
35#include "M4VSS3GPP_ErrorCodes.h"
36
37/**
38 * OSAL headers */
39#include "M4OSA_Memory.h" /**< OSAL memory management */
40#include "M4OSA_Debug.h"  /**< OSAL debug management */
41
42#define PWR_FXP_FRACT_MAX            (32768)
43
44/************************************************************************/
45/* Static local functions                                               */
46/************************************************************************/
47static M4OSA_ERR M4VSS3GPP_intCheckAudioMode( M4VSS3GPP_InternalEditContext
48                                             *pC );
49static M4OSA_Void M4VSS3GPP_intCheckAudioEffects( M4VSS3GPP_InternalEditContext
50                                                 *pC, M4OSA_UInt8 uiClipNumber );
51static M4OSA_ERR M4VSS3GPP_intApplyAudioEffect( M4VSS3GPP_InternalEditContext
52                                               *pC, M4OSA_UInt8 uiClip1orClip2,
53                                               M4OSA_Int16 *pPCMdata,
54                                               M4OSA_UInt32 uiPCMsize );
55static M4OSA_ERR M4VSS3GPP_intAudioTransition( M4VSS3GPP_InternalEditContext
56                                              *pC, M4OSA_Int16 *pPCMdata1,
57                                              M4OSA_Int16 *pPCMdata2,
58                                              M4OSA_UInt32 uiPCMsize );
59
60/**
61 ******************************************************************************
62 * M4OSA_ERR M4VSS3GPP_intEditJumpMP3()
63 * @brief    One step of jumping processing for the MP3 clip.
64 * @note    On one step, the jump of several AU is done
65 * @param   pC    (IN/OUT) Internal edit context
66 ******************************************************************************
67 */
68M4OSA_ERR M4VSS3GPP_intEditJumpMP3( M4VSS3GPP_InternalEditContext *pC )
69{
70    M4OSA_ERR err;
71    M4VSS3GPP_ClipContext *pClip = pC->pC1; /**< shortcut */
72    M4OSA_Int32 JumpCts;
73
74    JumpCts = pClip->iActualAudioBeginCut;
75
76    err = M4VSS3GPP_intClipJumpAudioAt(pClip, &JumpCts);
77
78    if( M4NO_ERROR != err )
79    {
80        M4OSA_TRACE1_1(
81            "M4VSS3GPP_intOpenClip: M4VSS3GPP_intClipJumpAudioAt(A) returns 0x%x!",
82            err);
83        return err;
84    }
85
86    if( JumpCts >= pClip->iActualAudioBeginCut )
87    {
88        pC->State = M4VSS3GPP_kEditState_MP3;
89
90        /**
91        * Update clip offset with the audio begin cut */
92        pClip->iAoffset = -JumpCts;
93
94        /**
95        * The audio is currently in reading mode */
96        pClip->Astatus = M4VSS3GPP_kClipStatus_READ;
97    }
98    return M4NO_ERROR;
99}
100
101/**
102 ******************************************************************************
103 * M4OSA_ERR M4VSS3GPP_intEditStepMP3()
104 * @brief    One step of audio processing for the MP3 clip
105 * @param   pC    (IN/OUT) Internal edit context
106 ******************************************************************************
107 */
108M4OSA_ERR M4VSS3GPP_intEditStepMP3( M4VSS3GPP_InternalEditContext *pC )
109{
110    M4OSA_ERR err;
111    M4VSS3GPP_ClipContext *pClip = pC->pC1; /**< shortcut */
112
113    /**
114    * Copy the input AU to the output AU */
115    err = pC->pOsaFileWritPtr->writeData(pC->ewc.p3gpWriterContext,
116        pClip->pAudioFramePtr, (M4OSA_UInt32)pClip->uiAudioFrameSize);
117
118    /**
119    * Read the next audio frame */
120    err = M4VSS3GPP_intClipReadNextAudioFrame(pClip);
121
122    if( M4OSA_ERR_IS_ERROR(err) )
123    {
124        M4OSA_TRACE1_1(
125            "M4VSS3GPP_intEditStepMP3: READ_WRITE:\
126            M4VSS3GPP_intClipReadNextAudioFrame returns 0x%x!",    err);
127        return err;
128    }
129    else
130    {
131        /**
132        * Update current time (to=tc+T) */
133        pC->ewc.dATo =
134            ( pClip->iAudioFrameCts + pClip->iAoffset) / pClip->scale_audio;
135
136        if( (M4OSA_Int32)(pClip->iAudioFrameCts / pClip->scale_audio + 0.5)
137            >= pClip->iEndTime )
138        {
139            M4READER_Buffer mp3tagBuffer;
140
141            /**
142            * The duration is better respected if the first AU and last AU are both above
143            the cut time */
144            err = pC->pOsaFileWritPtr->writeData(pC->ewc.p3gpWriterContext,
145                pClip->pAudioFramePtr,
146                (M4OSA_UInt32)pClip->uiAudioFrameSize);
147
148            /* The ID3v1 tag is always at the end of the mp3 file so the end of the cutting
149            process is waited */
150            /* before writing the metadata in the output file*/
151
152            /* Retrieve the data of the ID3v1 Tag */
153            err = pClip->ShellAPI.m_pReader->m_pFctGetOption(
154                pClip->pReaderContext, M4READER_kOptionID_Mp3Id3v1Tag,
155                (M4OSA_DataOption) &mp3tagBuffer);
156
157            if( M4NO_ERROR != err )
158            {
159                M4OSA_TRACE1_1(
160                    "M4VSS3GPP_intEditStepMP3: M4MP3R_getOption returns 0x%x",
161                    err);
162                return err;
163            }
164
165            /* Write the data of the ID3v1 Tag in the output file */
166            if( 0 != mp3tagBuffer.m_uiBufferSize )
167            {
168                err = pC->pOsaFileWritPtr->writeData(pC->ewc.p3gpWriterContext,
169                    (M4OSA_MemAddr8)mp3tagBuffer.m_pData, mp3tagBuffer.m_uiBufferSize);
170                /**
171                * Free before the error checking anyway */
172                free(mp3tagBuffer.m_pData);
173
174                /**
175                * Error checking */
176                if( M4NO_ERROR != err )
177                {
178                    M4OSA_TRACE1_1(
179                        "M4VSS3GPP_intEditStepMP3:\
180                        pOsaFileWritPtr->writeData(ID3v1Tag) returns 0x%x",    err);
181                    return err;
182                }
183
184                mp3tagBuffer.m_uiBufferSize = 0;
185                mp3tagBuffer.m_pData = M4OSA_NULL;
186            }
187
188            /* The End Cut has been reached */
189            err = M4VSS3GPP_intReachedEndOfAudio(pC);
190
191            if( M4NO_ERROR != err )
192            {
193                M4OSA_TRACE1_1(
194                    "M4VSS3GPP_intEditStepMP3 : M4VSS3GPP_intReachedEndOfAudio returns 0x%x",
195                    err);
196                return err;
197            }
198        }
199
200        if( ( M4WAR_NO_MORE_AU == err) && (M4OSA_FALSE
201            == pC->bSupportSilence) ) /**< Reached end of clip */
202        {
203            err = M4VSS3GPP_intReachedEndOfAudio(
204                pC); /**< Clip done, do the next one */
205
206            if( M4NO_ERROR != err )
207            {
208                M4OSA_TRACE1_1(
209                    "M4VSS3GPP_intEditStepMP3: READ_WRITE:\
210                    M4VSS3GPP_intReachedEndOfAudio returns 0x%x",
211                    err);
212                return err;
213            }
214        }
215    }
216
217    /**
218    * Return with no error */
219    M4OSA_TRACE3_0("M4VSS3GPP_intEditStepMP3: returning M4NO_ERROR");
220    return M4NO_ERROR;
221}
222/**
223 ******************************************************************************
224 * M4OSA_ERR M4VSS3GPP_intEditStepAudio()
225 * @brief    One step of audio processing
226 * @param   pC    (IN/OUT) Internal edit context
227 ******************************************************************************
228 */
229M4OSA_ERR M4VSS3GPP_intEditStepAudio( M4VSS3GPP_InternalEditContext *pC )
230{
231    M4OSA_ERR err;
232    int32_t auTimeStamp = -1;
233
234    M4ENCODER_AudioBuffer pEncInBuffer;  /**< Encoder input buffer for api */
235    M4ENCODER_AudioBuffer pEncOutBuffer; /**< Encoder output buffer for api */
236    M4OSA_Time
237        frameTimeDelta; /**< Duration of the encoded (then written) data */
238    M4OSA_Bool bStopAudio;
239
240    /**
241    * Check if we reached end cut */
242    if( ( pC->ewc.dATo - pC->pC1->iAoffset / pC->pC1->scale_audio + 0.5)
243        >= pC->pC1->iEndTime )
244    {
245        /**
246        * Audio is done for this clip */
247        err = M4VSS3GPP_intReachedEndOfAudio(pC);
248
249        /* RC: to know when a file has been processed */
250        if( M4NO_ERROR != err && err != M4VSS3GPP_WAR_SWITCH_CLIP )
251        {
252            M4OSA_TRACE1_1(
253                "M4VSS3GPP_intEditStepAudio: M4VSS3GPP_intReachedEndOfAudio returns 0x%x",
254                err);
255        }
256
257        return err;
258    }
259
260    /**
261    * Check Audio Mode, depending on the current output CTS */
262    err = M4VSS3GPP_intCheckAudioMode(
263        pC); /**< This function change the pC->Astate variable! */
264
265    if( M4NO_ERROR != err )
266    {
267        M4OSA_TRACE1_1(
268            "M4VSS3GPP_intEditStepAudio: M4VSS3GPP_intCheckAudioMode returns 0x%x!",
269            err);
270        return err;
271    }
272
273    M4OSA_TRACE2_3("  AUDIO step : dATo = %f  state = %d  offset = %ld",
274        pC->ewc.dATo, pC->Astate, pC->pC1->iAoffset);
275
276    bStopAudio = M4OSA_FALSE;
277
278    switch( pC->Astate )
279    {
280            /* _________________ */
281            /*|                 |*/
282            /*| READ_WRITE MODE |*/
283            /*|_________________|*/
284
285        case M4VSS3GPP_kEditAudioState_READ_WRITE:
286            {
287                M4OSA_TRACE3_0("M4VSS3GPP_intEditStepAudio READ_WRITE");
288
289                /**
290                * Get the output AU to write into */
291                err = pC->ShellAPI.pWriterDataFcts->pStartAU(
292                    pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
293                    &pC->ewc.WriterAudioAU);
294
295                if( M4NO_ERROR != err )
296                {
297                    M4OSA_TRACE1_1(
298                        "M4VSS3GPP_intEditStepAudio:\
299                        READ_WRITE: pWriterDataFcts->pStartAU returns 0x%x!",
300                        err);
301                    return err;
302                }
303
304                /**
305                * Compute output audio CTS */
306                pC->ewc.WriterAudioAU.CTS =
307                    pC->pC1->iAudioFrameCts + pC->pC1->iAoffset;
308
309                /**
310                * BZZZ bug fix (read-write case):
311                * Replace the first AMR AU of the stream with a silence AU.
312                * It removes annoying "BZZZ" audio glitch.
313                * It is not needed if there is a begin cut.
314                * It is not needed for the first clip.
315                * Because of another bugfix (2005-03-24), the first AU written may be
316                * the second one which CTS is 20. Hence the cts<21 test.
317                * (the BZZZ effect occurs even with the second AU!) */
318                if( ( M4OSA_FALSE == pC->pC1->bFirstAuWritten)
319                    && (0 != pC->uiCurrentClip) && (pC->pC1->iAudioFrameCts
320                    < (pC->ewc.iSilenceFrameDuration + 1)) )
321                {
322                    /**
323                    * Copy a silence AU to the output */
324                    pC->ewc.WriterAudioAU.size = pC->ewc.uiSilenceFrameSize;
325                    memcpy((void *)pC->ewc.WriterAudioAU.dataAddress,
326                        (void *)pC->ewc.pSilenceFrameData, pC->ewc.uiSilenceFrameSize);
327                    M4OSA_TRACE2_0("A #### silence AU");
328                }
329                else if( (M4OSA_UInt32)pC->pC1->uiAudioFrameSize
330                    < pC->ewc.uiAudioMaxAuSize )
331                {
332                    /**
333                    * Copy the input AU to the output AU */
334                    pC->ewc.WriterAudioAU.size =
335                        (M4OSA_UInt32)pC->pC1->uiAudioFrameSize;
336                    memcpy((void *)pC->ewc.WriterAudioAU.dataAddress,
337                        (void *)pC->pC1->pAudioFramePtr, pC->ewc.WriterAudioAU.size);
338                }
339                else
340                {
341                    M4OSA_TRACE1_2(
342                        "M4VSS3GPP_intEditStepAudio: READ_WRITE: AU size greater than MaxAuSize \
343                        (%d>%d)! returning M4VSS3GPP_ERR_INPUT_AUDIO_AU_TOO_LARGE",
344                        pC->pC1->uiAudioFrameSize, pC->ewc.uiAudioMaxAuSize);
345                    return M4VSS3GPP_ERR_INPUT_AUDIO_AU_TOO_LARGE;
346                }
347
348                /**
349                * This boolean is only used to fix the BZZ bug... */
350                pC->pC1->bFirstAuWritten = M4OSA_TRUE;
351
352                M4OSA_TRACE2_2("B ---- write : cts  = %ld [ 0x%x ]",
353                    (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio),
354                    pC->ewc.WriterAudioAU.size);
355
356                /**
357                * Write the AU */
358                err = pC->ShellAPI.pWriterDataFcts->pProcessAU(
359                    pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
360                    &pC->ewc.WriterAudioAU);
361
362                if( M4NO_ERROR != err )
363                {
364                    /*11/12/2008 CR 3283 MMS use case for VideoArtist
365                    the warning M4WAR_WRITER_STOP_REQ is returned when the targeted output file
366                    size is reached
367                    The editing is then finished,
368                     the warning M4VSS3GPP_WAR_EDITING_DONE is returned*/
369                    if( M4WAR_WRITER_STOP_REQ == err )
370                    {
371                        M4OSA_TRACE1_0(
372                            "M4VSS3GPP_intEditStepAudio: File was cut to avoid oversize");
373                        return M4VSS3GPP_WAR_EDITING_DONE;
374                    }
375                    else
376                    {
377                        M4OSA_TRACE1_1(
378                            "M4VSS3GPP_intEditStepAudio:\
379                            READ_WRITE: pWriterDataFcts->pProcessAU returns 0x%x!",
380                            err);
381                        return err;
382                    }
383                }
384
385                /**
386                * Audio is now in read mode (there may be a "if(status!=READ)" here,
387                but it is removed for optimization) */
388                pC->pC1->Astatus = M4VSS3GPP_kClipStatus_READ;
389
390                /**
391                * Read the next audio frame */
392                err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC1);
393
394                M4OSA_TRACE2_3("C .... read  : cts  = %.0f + %.0f [ 0x%x ]",
395                    pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
396                    pC->pC1->iAoffset / pC->pC1->scale_audio,
397                    pC->pC1->uiAudioFrameSize);
398
399                if( M4OSA_ERR_IS_ERROR(err) )
400                {
401                    M4OSA_TRACE1_1(
402                        "M4VSS3GPP_intEditStepAudio: READ_WRITE:\
403                        M4VSS3GPP_intClipReadNextAudioFrame returns 0x%x!",
404                        err);
405                    return err;
406                }
407                else
408                {
409                    /**
410                    * Update current time (to=tc+T) */
411                    pC->ewc.dATo = ( pC->pC1->iAudioFrameCts + pC->pC1->iAoffset)
412                        / pC->pC1->scale_audio;
413
414                    if( ( M4WAR_NO_MORE_AU == err)
415                        && (M4OSA_FALSE == pC->bSupportSilence) )
416                    {
417                        /**
418                        * If output is other than AMR or AAC
419                        (i.e. EVRC,we can't write silence into it)
420                        * So we simply end here.*/
421                        bStopAudio = M4OSA_TRUE;
422                    }
423                }
424            }
425            break;
426
427            /* ____________________ */
428            /*|                    |*/
429            /*| DECODE_ENCODE MODE |*/
430            /*|____________________|*/
431
432        case M4VSS3GPP_kEditAudioState_DECODE_ENCODE:
433            {
434                M4OSA_TRACE3_0("M4VSS3GPP_intEditStepAudio DECODE_ENCODE");
435
436                /**
437                * Get the output AU to write into */
438                err = pC->ShellAPI.pWriterDataFcts->pStartAU(
439                    pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
440                    &pC->ewc.WriterAudioAU);
441
442                if( M4NO_ERROR != err )
443                {
444                    M4OSA_TRACE1_1(
445                        "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE:\
446                        pWriterDataFcts->pStartAU returns 0x%x!",
447                        err);
448                    return err;
449                }
450
451                /**
452                * If we were reading the clip, we must jump a few AU backward to decode/encode
453                (without writing result) from that point. */
454                if( M4VSS3GPP_kClipStatus_READ == pC->pC1->Astatus )
455                {
456                    M4OSA_Int32 iTargetCts, iCurrentCts;
457
458                    if( 0
459                        != pC->pC1->
460                        iAudioFrameCts ) /**<don't try to pre-decode if clip is at its beginning. */
461                    {
462                        /**
463                        * Jump a few AUs backward */
464                        iCurrentCts = pC->pC1->iAudioFrameCts;
465                        iTargetCts = iCurrentCts - M4VSS3GPP_NB_AU_PREFETCH
466                            * pC->ewc.iSilenceFrameDuration;
467
468                        if( iTargetCts < 0 )
469                        {
470                            iTargetCts = 0; /**< Sanity check */
471                        }
472
473                        err = M4VSS3GPP_intClipJumpAudioAt(pC->pC1, &iTargetCts);
474
475                        if( M4NO_ERROR != err )
476                        {
477                            M4OSA_TRACE1_1(
478                                "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE-prefetch:\
479                                M4VSS3GPP_intClipJumpAudioAt returns 0x%x!",
480                                err);
481                            return err;
482                        }
483
484                        err = M4VSS3GPP_intClipReadNextAudioFrame(
485                            pC->pC1); /**< read AU where we jumped */
486
487                        M4OSA_TRACE2_3("D .... read  : cts  = %.0f + %.0f [ 0x%x ]",
488                            pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
489                            pC->pC1->iAoffset / pC->pC1->scale_audio,
490                            pC->pC1->uiAudioFrameSize);
491
492                        if( M4OSA_ERR_IS_ERROR(err) )
493                        {
494                            M4OSA_TRACE1_1(
495                                "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE-prefetch:\
496                                M4VSS3GPP_intClipReadNextAudioFrame(a) returns 0x%x!",
497                                err);
498                            return err;
499                        }
500
501                        /**
502                        * Decode/encode up to the wanted position */
503                        while( pC->pC1->iAudioFrameCts < iCurrentCts )
504                        {
505                            err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pC1);
506
507                            if( M4NO_ERROR != err )
508                            {
509                                M4OSA_TRACE1_1(
510                                    "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE-prefetch: \
511                                    M4VSS3GPP_intClipDecodeCurrentAudioFrame returns 0x%x!",
512                                    err);
513                                return err;
514                            }
515
516                            /* [Mono] or [Stereo interleaved] : all is in one buffer */
517                            pEncInBuffer.pTableBuffer[0] =
518                                pC->pC1->AudioDecBufferOut.m_dataAddress;
519                            pEncInBuffer.pTableBufferSize[0] =
520                                pC->pC1->AudioDecBufferOut.m_bufferSize;
521                            pEncInBuffer.pTableBuffer[1] = M4OSA_NULL;
522                            pEncInBuffer.pTableBufferSize[1] = 0;
523
524                            /* Time in ms from data size, because it is PCM16 samples */
525                            frameTimeDelta =
526                                pEncInBuffer.pTableBufferSize[0] / sizeof(short)
527                                / pC->ewc.uiNbChannels;
528
529                            /**
530                            * Prepare output buffer */
531                            pEncOutBuffer.pTableBuffer[0] =
532                                (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress;
533                            pEncOutBuffer.pTableBufferSize[0] = 0;
534
535                            M4OSA_TRACE2_0("E **** pre-encode");
536#ifdef M4VSS_SUPPORT_OMX_CODECS
537                            /*OMX Audio decoder used.
538                            * OMX Audio dec shell does internal buffering and hence does not return
539                            a PCM buffer for every decodeStep call.*
540                            * So PCM buffer sizes might be 0. In this case donot call encode Step*/
541
542                            if( 0 != pEncInBuffer.pTableBufferSize[0] )
543                            {
544#endif
545                                /**
546                                * Encode the PCM audio */
547
548                                err =
549                                    pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep(
550                                    pC->ewc.pAudioEncCtxt,
551                                    &pEncInBuffer, &pEncOutBuffer);
552
553                                if( ( M4NO_ERROR != err)
554                                    && (M4WAR_NO_MORE_AU != err) )
555                                {
556                                    M4OSA_TRACE1_1(
557                                        "M4VSS3GPP_intEditStepAudio():\
558                                        pAudioEncoderGlobalFcts->pFctStep returns 0x%x",
559                                        err);
560                                    return err;
561                                }
562#ifdef M4VSS_SUPPORT_OMX_CODECS
563
564                            } //if(0 != pEncInBuffer.pTableBufferSize[0])
565
566#endif
567                            pC->pC1->pAudioFramePtr = M4OSA_NULL;
568
569                            // Get timestamp of last read AU
570                            pC->pC1->ShellAPI.m_pAudioDecoder->m_pFctGetOptionAudioDec(
571                             pC->pC1->pAudioDecCtxt, M4AD_kOptionID_AuCTS,
572                             (M4OSA_DataOption) &auTimeStamp);
573
574                            if (auTimeStamp == -1) {
575                                M4OSA_TRACE1_0("M4VSS3GPP_intEditStepAudio: \
576                                 invalid audio timestamp returned");
577                                return M4WAR_INVALID_TIME;
578                            }
579
580                            pC->pC1->iAudioFrameCts = auTimeStamp;
581
582                        }
583                    }
584
585                    /**
586                    * Audio is now OK for decoding */
587                    pC->pC1->Astatus = M4VSS3GPP_kClipStatus_DECODE;
588                }
589
590                /**
591                * Decode the input audio */
592                err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pC1);
593
594                if( M4NO_ERROR != err )
595                {
596                    M4OSA_TRACE1_1(
597                        "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE:\
598                        M4VSS3GPP_intClipDecodeCurrentAudioFrame returns 0x%x",
599                        err);
600                    return err;
601                }
602
603                pC->pC1->pAudioFramePtr = M4OSA_NULL;
604
605                // Get timestamp of last read AU
606                pC->pC1->ShellAPI.m_pAudioDecoder->m_pFctGetOptionAudioDec(
607                 pC->pC1->pAudioDecCtxt, M4AD_kOptionID_AuCTS,
608                 (M4OSA_DataOption) &auTimeStamp);
609
610                if (auTimeStamp == -1) {
611                    M4OSA_TRACE1_0("M4VSS3GPP_intEditStepAudio: invalid audio \
612                     timestamp returned");
613                    return M4WAR_INVALID_TIME;
614                }
615
616                pC->pC1->iAudioFrameCts = auTimeStamp;
617
618                /**
619                * Apply the effect */
620                if( pC->iClip1ActiveEffect >= 0 )
621                {
622                    err = M4VSS3GPP_intApplyAudioEffect(pC, 1, (M4OSA_Int16
623                        *)pC->pC1->AudioDecBufferOut.m_dataAddress,
624                        pC->pC1->AudioDecBufferOut.m_bufferSize);
625
626                    if( M4NO_ERROR != err )
627                    {
628                        M4OSA_TRACE1_1(
629                            "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE:\
630                            M4VSS3GPP_intEndAudioEffect returns 0x%x",
631                            err);
632                        return err;
633                    }
634                }
635
636                /**
637                * Compute output audio CTS */
638                pC->ewc.WriterAudioAU.CTS =
639                    pC->pC1->iAudioFrameCts + pC->pC1->iAoffset;
640
641                /* May happen with corrupted input files (which have stts entries not
642                multiple of SilenceFrameDuration) */
643                if( pC->ewc.WriterAudioAU.CTS < 0 )
644                {
645                    pC->ewc.WriterAudioAU.CTS = 0;
646                }
647
648                /**
649                * BZZZ bug fix (decode-encode case):
650                * (Yes, the Bzz bug may also occur when we re-encode. It doesn't
651                *  occur at the decode before the encode, but at the playback!)
652                * Replace the first AMR AU of the encoded stream with a silence AU.
653                * It removes annoying "BZZZ" audio glitch.
654                * It is not needed if there is a begin cut.
655                * It is not needed for the first clip.
656                * Because of another bugfix (2005-03-24), the first AU written may be
657                * the second one which CTS is 20. Hence the cts<21 test.
658                * (the BZZZ effect occurs even with the second AU!) */
659                if( ( M4OSA_FALSE == pC->pC1->bFirstAuWritten)
660                    && (0 != pC->uiCurrentClip) && (pC->pC1->iAudioFrameCts
661                    < (pC->ewc.iSilenceFrameDuration + 1)) )
662                {
663                    /**
664                    * Copy a silence AMR AU to the output */
665                    pC->ewc.WriterAudioAU.size = pC->ewc.uiSilenceFrameSize;
666                    memcpy((void *)pC->ewc.WriterAudioAU.dataAddress,
667                        (void *)pC->ewc.pSilenceFrameData, pC->ewc.uiSilenceFrameSize);
668                    M4OSA_TRACE2_0("G #### silence AU");
669                }
670                else
671                {
672                    /**
673                    * Encode the filtered PCM audio directly into the output AU */
674
675                    /* [Mono] or [Stereo interleaved] : all is in one buffer */
676                    pEncInBuffer.pTableBuffer[0] =
677                        pC->pC1->AudioDecBufferOut.m_dataAddress;
678                    pEncInBuffer.pTableBufferSize[0] =
679                        pC->pC1->AudioDecBufferOut.m_bufferSize;
680                    pEncInBuffer.pTableBuffer[1] = M4OSA_NULL;
681                    pEncInBuffer.pTableBufferSize[1] = 0;
682
683                    /* Time in ms from data size, because it is PCM16 samples */
684                    frameTimeDelta =
685                        pEncInBuffer.pTableBufferSize[0] / sizeof(short)
686                        / pC->ewc.uiNbChannels;
687
688                    /**
689                    * Prepare output buffer */
690                    pEncOutBuffer.pTableBuffer[0] =
691                        (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress;
692                    pEncOutBuffer.pTableBufferSize[0] = 0;
693
694                    M4OSA_TRACE2_0("H ++++ encode AU");
695
696#ifdef M4VSS_SUPPORT_OMX_CODECS
697                    /*OMX Audio decoder used.
698                    * OMX Audio dec shell does internal buffering and hence does not return
699                    a PCM buffer for every decodeStep call.*
700                    * So PCM buffer sizes might be 0. In this case donot call encode Step*/
701
702                    if( 0 != pEncInBuffer.pTableBufferSize[0] )
703                    {
704
705#endif
706
707                        /**
708                        * Encode the PCM audio */
709
710                        err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep(
711                            pC->ewc.pAudioEncCtxt,
712                            &pEncInBuffer, &pEncOutBuffer);
713
714                        if( ( M4NO_ERROR != err) && (M4WAR_NO_MORE_AU != err) )
715                        {
716                            M4OSA_TRACE1_1(
717                                "M4VSS3GPP_intEditStepAudio():\
718                                pAudioEncoderGlobalFcts->pFctStep returns 0x%x",
719                                err);
720                            return err;
721                        }
722#ifdef M4VSS_SUPPORT_OMX_CODECS
723
724                    }
725
726#endif
727
728                    /**
729                    * Set AU size */
730
731                    pC->ewc.WriterAudioAU.size = pEncOutBuffer.pTableBufferSize[
732                        0]; /**< Get the size of encoded data */
733                }
734
735                /**
736                * This boolean is only used to fix the BZZ bug... */
737                pC->pC1->bFirstAuWritten = M4OSA_TRUE;
738
739                M4OSA_TRACE2_2("I ---- write : cts  = %ld [ 0x%x ]",
740                    (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio),
741                    pC->ewc.WriterAudioAU.size);
742
743                /**
744                * Write the AU */
745                err = pC->ShellAPI.pWriterDataFcts->pProcessAU(
746                    pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
747                    &pC->ewc.WriterAudioAU);
748
749                if( M4NO_ERROR != err )
750                {
751                    /*11/12/2008 CR 3283 MMS use case for VideoArtist
752                    the warning M4WAR_WRITER_STOP_REQ is returned when the targeted output file
753                     size is reached
754                    The editing is then finished,
755                     the warning M4VSS3GPP_WAR_EDITING_DONE is returned*/
756                    if( M4WAR_WRITER_STOP_REQ == err )
757                    {
758                        M4OSA_TRACE1_0(
759                            "M4VSS3GPP_intEditStepAudio: File was cut to avoid oversize");
760                        return M4VSS3GPP_WAR_EDITING_DONE;
761                    }
762                    else
763                    {
764                        M4OSA_TRACE1_1(
765                            "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE:\
766                            pWriterDataFcts->pProcessAU returns 0x%x!",
767                            err);
768                        return err;
769                    }
770                }
771
772                /**
773                * Read the next audio frame */
774                err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC1);
775
776                M4OSA_TRACE2_3("J .... read  : cts  = %.0f + %.0f [ 0x%x ]",
777                    pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
778                    pC->pC1->iAoffset / pC->pC1->scale_audio,
779                    pC->pC1->uiAudioFrameSize);
780
781                if( M4OSA_ERR_IS_ERROR(err) )
782                {
783                    M4OSA_TRACE1_1(
784                        "M4VSS3GPP_intEditStepAudio: DECODE_ENCODE:\
785                        M4VSS3GPP_intClipReadNextAudioFrame returns 0x%x!",
786                        err);
787                    return err;
788                }
789                else
790                {
791                    /**
792                    * Update current time (to=tc+T) */
793                    pC->ewc.dATo = ( pC->pC1->iAudioFrameCts + pC->pC1->iAoffset)
794                        / pC->pC1->scale_audio;
795
796                    if( ( M4WAR_NO_MORE_AU == err)
797                        && (M4OSA_FALSE == pC->bSupportSilence) )
798                    {
799                        /**
800                        * If output is other than AMR or AAC
801                        (i.e. EVRC,we can't write silence into it)
802                        * So we simply end here.*/
803                        bStopAudio = M4OSA_TRUE;
804                    }
805                }
806            }
807            break;
808
809            /* _________________ */
810            /*|                 |*/
811            /*| TRANSITION MODE |*/
812            /*|_________________|*/
813
814        case M4VSS3GPP_kEditAudioState_TRANSITION:
815            {
816                M4OSA_TRACE3_0("M4VSS3GPP_intEditStepAudio TRANSITION");
817
818                /**
819                * Get the output AU to write into */
820                err = pC->ShellAPI.pWriterDataFcts->pStartAU(
821                    pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
822                    &pC->ewc.WriterAudioAU);
823
824                if( M4NO_ERROR != err )
825                {
826                    M4OSA_TRACE1_1(
827                        "M4VSS3GPP_intEditStepAudio: TRANSITION:\
828                        pWriterDataFcts->pStartAU returns 0x%x!",
829                        err);
830                    return err;
831                }
832
833                /**
834                * If we were reading the clip, we must jump a few AU backward to decode/encode
835                (without writing result) from that point. */
836                if( M4VSS3GPP_kClipStatus_READ == pC->pC1->Astatus )
837                {
838                    M4OSA_Int32 iTargetCts, iCurrentCts;
839
840                    if( 0
841                        != pC->pC1->
842                        iAudioFrameCts ) /**<don't try to pre-decode if clip is at its beginning.*/
843                    {
844                        /**
845                        * Jump a few AUs backward */
846                        iCurrentCts = pC->pC1->iAudioFrameCts;
847                        iTargetCts = iCurrentCts - M4VSS3GPP_NB_AU_PREFETCH
848                            * pC->ewc.iSilenceFrameDuration;
849
850                        if( iTargetCts < 0 )
851                        {
852                            iTargetCts = 0; /**< Sanity check */
853                        }
854
855                        err = M4VSS3GPP_intClipJumpAudioAt(pC->pC1, &iTargetCts);
856
857                        if( M4NO_ERROR != err )
858                        {
859                            M4OSA_TRACE1_1(
860                                "M4VSS3GPP_intEditStepAudio: TRANSITION-prefetch:\
861                                M4VSS3GPP_intClipJumpAudioAt returns 0x%x!",
862                                err);
863                            return err;
864                        }
865
866                        err = M4VSS3GPP_intClipReadNextAudioFrame(
867                            pC->pC1); /**< read AU where we jumped */
868
869                        M4OSA_TRACE2_3("K .... read  : cts  = %.0f + %.0f [ 0x%x ]",
870                            pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
871                            pC->pC1->iAoffset / pC->pC1->scale_audio,
872                            pC->pC1->uiAudioFrameSize);
873
874                        if( M4OSA_ERR_IS_ERROR(err) )
875                        {
876                            M4OSA_TRACE1_1(
877                                "M4VSS3GPP_intEditStepAudio: TRANSITION-prefetch:\
878                                M4VSS3GPP_intClipReadNextAudioFrame(a) returns 0x%x!",
879                                err);
880                            return err;
881                        }
882
883                        /**
884                        * Decode/encode up to the wanted position */
885                        while( pC->pC1->iAudioFrameCts < iCurrentCts )
886                        {
887                            err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pC1);
888
889                            if( M4NO_ERROR != err )
890                            {
891                                M4OSA_TRACE1_1(
892                                    "M4VSS3GPP_intEditStepAudio: TRANSITION-prefetch:\
893                                    M4VSS3GPP_intClipDecodeCurrentAudioFrame returns 0x%x!",
894                                    err);
895                                return err;
896                            }
897
898                            /* [Mono] or [Stereo interleaved] : all is in one buffer */
899                            pEncInBuffer.pTableBuffer[0] =
900                                pC->pC1->AudioDecBufferOut.m_dataAddress;
901                            pEncInBuffer.pTableBufferSize[0] =
902                                pC->pC1->AudioDecBufferOut.m_bufferSize;
903                            pEncInBuffer.pTableBuffer[1] = M4OSA_NULL;
904                            pEncInBuffer.pTableBufferSize[1] = 0;
905
906                            /* Time in ms from data size, because it is PCM16 samples */
907                            frameTimeDelta =
908                                pEncInBuffer.pTableBufferSize[0] / sizeof(short)
909                                / pC->ewc.uiNbChannels;
910
911                            /**
912                            * Prepare output buffer */
913                            pEncOutBuffer.pTableBuffer[0] =
914                                (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress;
915                            pEncOutBuffer.pTableBufferSize[0] = 0;
916
917                            M4OSA_TRACE2_0("L **** pre-encode");
918#ifdef M4VSS_SUPPORT_OMX_CODECS
919                            /*OMX Audio decoder used.
920                            * OMX Audio dec shell does internal buffering and hence does not return
921                            a PCM buffer for every decodeStep call.*
922                            * So PCM buffer sizes might be 0. In this case donot call encode Step*/
923
924                            if( 0 != pEncInBuffer.pTableBufferSize[0] )
925                            {
926
927#endif
928                                /**
929                                * Encode the PCM audio */
930
931                                err =
932                                    pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep(
933                                    pC->ewc.pAudioEncCtxt,
934                                    &pEncInBuffer, &pEncOutBuffer);
935
936                                if( ( M4NO_ERROR != err)
937                                    && (M4WAR_NO_MORE_AU != err) )
938                                {
939                                    M4OSA_TRACE1_1(
940                                        "M4VSS3GPP_intEditStepAudio():\
941                                        pAudioEncoderGlobalFcts->pFctStep returns 0x%x",
942                                        err);
943                                    return err;
944                                }
945#ifdef M4VSS_SUPPORT_OMX_CODECS
946
947                            }
948
949#endif
950
951                            err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC1);
952
953                            M4OSA_TRACE2_3(
954                                "M .... read  : cts  = %.0f + %.0f [ 0x%x ]",
955                                pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
956                                pC->pC1->iAoffset / pC->pC1->scale_audio,
957                                pC->pC1->uiAudioFrameSize);
958
959                            if( M4OSA_ERR_IS_ERROR(err) )
960                            {
961                                M4OSA_TRACE1_1(
962                                    "M4VSS3GPP_intEditStepAudio: TRANSITION-prefetch:\
963                                    M4VSS3GPP_intClipReadNextAudioFrame(b) returns 0x%x!",
964                                    err);
965                                return err;
966                            }
967                        }
968                    }
969
970                    /**
971                    * Audio is now OK for decoding */
972                    pC->pC1->Astatus = M4VSS3GPP_kClipStatus_DECODE;
973                }
974
975                /**
976                * Decode the first input audio */
977                err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pC1);
978
979                if( M4NO_ERROR != err )
980                {
981                    M4OSA_TRACE1_1(
982                        "M4VSS3GPP_intEditStepAudio: TRANSITION:\
983                        M4VSS3GPP_intClipDecodeCurrentAudioFrame(C1) returns 0x%x",
984                        err);
985                    return err;
986                }
987
988                /**
989                * Decode the second input audio */
990                err = M4VSS3GPP_intClipDecodeCurrentAudioFrame(pC->pC2);
991
992                if( M4NO_ERROR != err )
993                {
994                    M4OSA_TRACE1_1(
995                        "M4VSS3GPP_intEditStepAudio: TRANSITION:\
996                        M4VSS3GPP_intClipDecodeCurrentAudioFrame(C2) returns 0x%x",
997                        err);
998                    return err;
999                }
1000
1001                /**
1002                * Check both clips decoded the same amount of PCM samples */
1003                if( pC->pC1->AudioDecBufferOut.m_bufferSize
1004                    != pC->pC2->AudioDecBufferOut.m_bufferSize )
1005                {
1006                    M4OSA_TRACE1_2(
1007                        "ERR : AudioTransition: both clips AU must have the same decoded\
1008                        PCM size! pc1 size=0x%x, pC2 size = 0x%x",
1009                        pC->pC1->AudioDecBufferOut.m_bufferSize,
1010                        pC->pC2->AudioDecBufferOut.m_bufferSize);
1011#ifdef M4VSS_SUPPORT_OMX_CODECS
1012                    /*OMX Audio decoder used.
1013                    * OMX Audio dec shell does internal buffering and hence does not return
1014                    a PCM buffer for every decodeStep call.*
1015                    * So PCM buffer sizes might be 0 or different for clip1 and clip2.
1016                    * So no need to return error in this case */
1017
1018                    M4OSA_TRACE1_2(
1019                        "M4VSS3GPP_intEditStepAudio: , pc1 AudBuff size=0x%x,\
1020                         pC2 AudBuff size = 0x%x",
1021                        pC->pC1->AudioDecBufferOut.m_bufferSize,
1022                        pC->pC2->AudioDecBufferOut.m_bufferSize);
1023
1024#else
1025
1026                    return M4VSS3GPP_ERR_AUDIO_DECODED_PCM_SIZE_ISSUE;
1027
1028#endif // M4VSS_SUPPORT_OMX_CODECS
1029
1030                }
1031
1032                /**
1033                * Apply the audio effect on clip1 */
1034                if( pC->iClip1ActiveEffect >= 0 )
1035                {
1036                    err = M4VSS3GPP_intApplyAudioEffect(pC, 1, (M4OSA_Int16
1037                        *)pC->pC1->AudioDecBufferOut.m_dataAddress,
1038                        pC->pC1->AudioDecBufferOut.m_bufferSize);
1039
1040                    if( M4NO_ERROR != err )
1041                    {
1042                        M4OSA_TRACE1_1(
1043                            "M4VSS3GPP_intEditStepAudio: TRANSITION:\
1044                            M4VSS3GPP_intApplyAudioEffect(C1) returns 0x%x",
1045                            err);
1046                        return err;
1047                    }
1048                }
1049
1050                /**
1051                * Apply the audio effect on clip2 */
1052                if( pC->iClip2ActiveEffect >= 0 )
1053                {
1054                    err = M4VSS3GPP_intApplyAudioEffect(pC, 2, (M4OSA_Int16
1055                        *)pC->pC2->AudioDecBufferOut.m_dataAddress,
1056                        pC->pC2->AudioDecBufferOut.m_bufferSize);
1057
1058                    if( M4NO_ERROR != err )
1059                    {
1060                        M4OSA_TRACE1_1(
1061                            "M4VSS3GPP_intEditStepAudio: TRANSITION:\
1062                            M4VSS3GPP_intApplyAudioEffect(C2) returns 0x%x",
1063                            err);
1064                        return err;
1065                    }
1066                }
1067
1068                /**
1069                * Apply the transition effect */
1070                err = M4VSS3GPP_intAudioTransition(pC,
1071                    (M4OSA_Int16 *)pC->pC1->AudioDecBufferOut.m_dataAddress,
1072                    (M4OSA_Int16 *)pC->pC2->AudioDecBufferOut.m_dataAddress,
1073                    pC->pC1->AudioDecBufferOut.m_bufferSize);
1074
1075                if( M4NO_ERROR != err )
1076                {
1077                    M4OSA_TRACE1_1(
1078                        "M4VSS3GPP_intEditStepAudio: TRANSITION:\
1079                        M4VSS3GPP_intAudioTransition returns 0x%x",
1080                        err);
1081                    return err;
1082                }
1083
1084                /* [Mono] or [Stereo interleaved] : all is in one buffer */
1085                pEncInBuffer.pTableBuffer[0] =
1086                    pC->pC1->AudioDecBufferOut.m_dataAddress;
1087                pEncInBuffer.pTableBufferSize[0] =
1088                    pC->pC1->AudioDecBufferOut.m_bufferSize;
1089                pEncInBuffer.pTableBuffer[1] = M4OSA_NULL;
1090                pEncInBuffer.pTableBufferSize[1] = 0;
1091
1092                /* Time in ms from data size, because it is PCM16 samples */
1093                frameTimeDelta = pEncInBuffer.pTableBufferSize[0] / sizeof(short)
1094                    / pC->ewc.uiNbChannels;
1095
1096                /**
1097                * Prepare output buffer */
1098                pEncOutBuffer.pTableBuffer[0] =
1099                    (M4OSA_MemAddr8)pC->ewc.WriterAudioAU.dataAddress;
1100                pEncOutBuffer.pTableBufferSize[0] = 0;
1101
1102                M4OSA_TRACE2_0("N **** blend AUs");
1103
1104#ifdef M4VSS_SUPPORT_OMX_CODECS
1105                /*OMX Audio decoder used.
1106                * OMX Audio dec shell does internal buffering and hence does not return
1107                a PCM buffer for every decodeStep call.*
1108                * So PCM buffer sizes might be 0. In this case donot call encode Step*/
1109
1110                if( 0 != pEncInBuffer.pTableBufferSize[0] )
1111                {
1112
1113#endif
1114
1115                    /**
1116                    * Encode the PCM audio */
1117
1118                    err = pC->ShellAPI.pAudioEncoderGlobalFcts->pFctStep(
1119                        pC->ewc.pAudioEncCtxt, &pEncInBuffer, &pEncOutBuffer);
1120
1121                    if( ( M4NO_ERROR != err) && (M4WAR_NO_MORE_AU != err) )
1122                    {
1123                        M4OSA_TRACE1_1(
1124                            "M4VSS3GPP_intEditStepAudio():\
1125                            pAudioEncoderGlobalFcts->pFctStep returns 0x%x",
1126                            err);
1127                        return err;
1128                    }
1129#ifdef M4VSS_SUPPORT_OMX_CODECS
1130
1131                }
1132
1133#endif
1134
1135                /**
1136                * Set AU cts and size */
1137
1138                pC->ewc.WriterAudioAU.size = pEncOutBuffer.pTableBufferSize[
1139                    0]; /**< Get the size of encoded data */
1140                    pC->ewc.WriterAudioAU.CTS += frameTimeDelta;
1141
1142                    M4OSA_TRACE2_2("O ---- write : cts  = %ld [ 0x%x ]",
1143                        (M4OSA_Int32)(pC->ewc.WriterAudioAU.CTS / pC->ewc.scale_audio),
1144                        pC->ewc.WriterAudioAU.size);
1145
1146                    /**
1147                    * Write the AU */
1148                    err = pC->ShellAPI.pWriterDataFcts->pProcessAU(
1149                        pC->ewc.p3gpWriterContext, M4VSS3GPP_WRITER_AUDIO_STREAM_ID,
1150                        &pC->ewc.WriterAudioAU);
1151
1152                    if( M4NO_ERROR != err )
1153                    {
1154                        /*11/12/2008 CR 3283 MMS use case for VideoArtist
1155                        the warning M4WAR_WRITER_STOP_REQ is returned when the targeted output
1156                         file size is reached
1157                        The editing is then finished,the warning M4VSS3GPP_WAR_EDITING_DONE
1158                        is returned*/
1159                        if( M4WAR_WRITER_STOP_REQ == err )
1160                        {
1161                            M4OSA_TRACE1_0(
1162                                "M4VSS3GPP_intEditStepAudio: File was cut to avoid oversize");
1163                            return M4VSS3GPP_WAR_EDITING_DONE;
1164                        }
1165                        else
1166                        {
1167                            M4OSA_TRACE1_1(
1168                                "M4VSS3GPP_intEditStepAudio: TRANSITION:\
1169                                pWriterDataFcts->pProcessAU returns 0x%x!",
1170                                err);
1171                            return err;
1172                        }
1173                    }
1174
1175                    /**
1176                    * Read the next audio frame */
1177                    err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC1);
1178
1179                    M4OSA_TRACE2_3("P .... read  : cts  = %.0f + %.0f [ 0x%x ]",
1180                        pC->pC1->iAudioFrameCts / pC->pC1->scale_audio,
1181                        pC->pC1->iAoffset / pC->pC1->scale_audio,
1182                        pC->pC1->uiAudioFrameSize);
1183
1184                    if( M4OSA_ERR_IS_ERROR(err) )
1185                    {
1186                        M4OSA_TRACE1_1(
1187                            "M4VSS3GPP_intEditStepAudio: TRANSITION:\
1188                            M4VSS3GPP_intClipReadNextAudioFrame(C1) returns 0x%x!",
1189                            err);
1190                        return err;
1191                    }
1192                    else
1193                    {
1194                        M4OSA_ERR secondaryError;
1195
1196                        /**
1197                        * Update current time (to=tc+T) */
1198                        pC->ewc.dATo = ( pC->pC1->iAudioFrameCts + pC->pC1->iAoffset)
1199                            / pC->pC1->scale_audio;
1200
1201                        /**
1202                        * Read the next audio frame in the second clip */
1203                        secondaryError = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC2);
1204
1205                        M4OSA_TRACE2_3("Q .... read  : cts  = %.0f + %.0f [ 0x%x ]",
1206                            pC->pC2->iAudioFrameCts / pC->pC2->scale_audio,
1207                            pC->pC2->iAoffset / pC->pC2->scale_audio,
1208                            pC->pC2->uiAudioFrameSize);
1209
1210                        if( M4OSA_ERR_IS_ERROR(secondaryError) )
1211                        {
1212                            M4OSA_TRACE1_1(
1213                                "M4VSS3GPP_intEditStepAudio: TRANSITION:\
1214                                M4VSS3GPP_intClipReadNextAudioFrame(C2) returns 0x%x!",
1215                                secondaryError);
1216                            return err;
1217                        }
1218
1219                        if( ( ( M4WAR_NO_MORE_AU == err)
1220                            || (M4WAR_NO_MORE_AU == secondaryError))
1221                            && (M4OSA_FALSE == pC->bSupportSilence) )
1222                        {
1223                            /**
1224                            * If output is other than AMR or AAC
1225                              (i.e. EVRC,we can't write silence into it)
1226                            * So we simply end here.*/
1227                            bStopAudio = M4OSA_TRUE;
1228                        }
1229                    }
1230            }
1231            break;
1232
1233            /* ____________ */
1234            /*|            |*/
1235            /*| ERROR CASE |*/
1236            /*|____________|*/
1237
1238        default:
1239
1240            M4OSA_TRACE3_1(
1241                "M4VSS3GPP_intEditStepAudio: invalid internal state (0x%x), \
1242                returning M4VSS3GPP_ERR_INTERNAL_STATE",
1243                pC->Astate);
1244            return M4VSS3GPP_ERR_INTERNAL_STATE;
1245    }
1246
1247    /**
1248    * Check if we are forced to stop audio */
1249    if( M4OSA_TRUE == bStopAudio )
1250    {
1251        /**
1252        * Audio is done for this clip */
1253        err = M4VSS3GPP_intReachedEndOfAudio(pC);
1254
1255        if( M4NO_ERROR != err )
1256        {
1257            M4OSA_TRACE1_1(
1258                "M4VSS3GPP_intEditStepAudio: M4VSS3GPP_intReachedEndOfAudio returns 0x%x",
1259                err);
1260            return err;
1261        }
1262    }
1263
1264    /**
1265    * Return with no error */
1266    M4OSA_TRACE3_0("M4VSS3GPP_intEditStepAudio: returning M4NO_ERROR");
1267    return M4NO_ERROR;
1268}
1269
1270/**
1271 ******************************************************************************
1272 * M4OSA_ERR M4VSS3GPP_intCheckAudioMode()
1273 * @brief    Check which audio process mode we must use, depending on the output CTS.
1274 * @param   pC    (IN/OUT) Internal edit context
1275 ******************************************************************************
1276 */
1277static M4OSA_ERR M4VSS3GPP_intCheckAudioMode( M4VSS3GPP_InternalEditContext
1278                                             *pC )
1279{
1280    M4OSA_ERR err;
1281    const M4OSA_Int32 TD = pC->pTransitionList[pC->
1282        uiCurrentClip].uiTransitionDuration; /**< Transition duration */
1283
1284    const M4VSS3GPP_EditAudioState previousAstate = pC->Astate;
1285
1286    /**
1287    * Check if Clip1 is on its begin cut, or in its begin effect or end effect zone */
1288    M4VSS3GPP_intCheckAudioEffects(pC, 1);
1289
1290    /**
1291    * Check if we are in the transition with next clip */
1292    if( ( TD > 0) && ((M4OSA_Int32)(pC->ewc.dATo - pC->pC1->iAoffset
1293        / pC->pC1->scale_audio + 0.5) >= (pC->pC1->iEndTime - TD)) )
1294    {
1295        /**
1296        * We are in a transition */
1297        pC->Astate = M4VSS3GPP_kEditAudioState_TRANSITION;
1298        pC->bTransitionEffect = M4OSA_TRUE;
1299
1300        /**
1301        * Do we enter the transition section ? */
1302        if( M4VSS3GPP_kEditAudioState_TRANSITION != previousAstate )
1303        {
1304            /**
1305            * Open second clip for transition, if not yet opened */
1306            if( M4OSA_NULL == pC->pC2 )
1307            {
1308                err = M4VSS3GPP_intOpenClip(pC, &pC->pC2,
1309                    &pC->pClipList[pC->uiCurrentClip + 1]);
1310
1311                if( M4NO_ERROR != err )
1312                {
1313                    M4OSA_TRACE1_1(
1314                        "M4VSS3GPP_intCheckAudioMode: M4VSS3GPP_intOpenClip() returns 0x%x!",
1315                        err);
1316                    return err;
1317                }
1318
1319                /**
1320                * In case of short transition and bad luck (...), there may be no video AU
1321                * in the transition. In that case, the second clip has not been opened.
1322                * So we must update the video offset here. */
1323                // Decorrelate input and output encoding timestamp to handle encoder prefetch
1324                /**< Add current video output CTS to the clip offset */
1325                pC->pC2->iVoffset += (M4OSA_UInt32)pC->ewc.dInputVidCts;
1326            }
1327
1328            /**
1329            * Add current audio output CTS to the clip offset
1330            * (video offset has already been set when doing the video transition) */
1331            pC->pC2->iAoffset +=
1332                (M4OSA_UInt32)(pC->ewc.dATo * pC->ewc.scale_audio + 0.5);
1333
1334            /**
1335            * 2005-03-24: BugFix for audio-video synchro:
1336            * There may be a portion of the duration of an audio AU of desynchro at each assembly.
1337            * It leads to an audible desynchro when there are a lot of clips assembled.
1338            * This bug fix allows to resynch the audio track when the delta is higher
1339            * than one audio AU duration.
1340            * We Step one AU in the second clip and we change the audio offset accordingly. */
1341            if( ( pC->pC2->iAoffset
1342                - (M4OSA_Int32)(pC->pC2->iVoffset *pC->pC2->scale_audio + 0.5))
1343                    > pC->ewc.iSilenceFrameDuration )
1344            {
1345                /**
1346                * Advance one AMR frame */
1347                err = M4VSS3GPP_intClipReadNextAudioFrame(pC->pC2);
1348
1349                M4OSA_TRACE2_3("Z .... read  : cts  = %.0f + %.0f [ 0x%x ]",
1350                    pC->pC2->iAudioFrameCts / pC->pC2->scale_audio,
1351                    pC->pC2->iAoffset / pC->pC2->scale_audio,
1352                    pC->pC2->uiAudioFrameSize);
1353
1354                if( M4OSA_ERR_IS_ERROR(err) )
1355                {
1356                    M4OSA_TRACE1_1(
1357                        "M4VSS3GPP_intCheckAudioMode:\
1358                        M4VSS3GPP_intClipReadNextAudioFrame returns 0x%x!",
1359                        err);
1360                    return err;
1361                }
1362                /**
1363                * Update audio offset accordingly*/
1364                pC->pC2->iAoffset -= pC->ewc.iSilenceFrameDuration;
1365            }
1366        }
1367
1368        /**
1369        * Check begin and end effects for clip2 */
1370        M4VSS3GPP_intCheckAudioEffects(pC, 2);
1371    }
1372    else
1373    {
1374        /**
1375        * We are not in a transition */
1376        pC->bTransitionEffect = M4OSA_FALSE;
1377
1378        /**
1379        * Check if current mode is Read/Write or Decode/Encode */
1380        if( pC->iClip1ActiveEffect >= 0 )
1381        {
1382            pC->Astate = M4VSS3GPP_kEditAudioState_DECODE_ENCODE;
1383        }
1384        else
1385        {
1386            pC->Astate = M4VSS3GPP_kEditAudioState_READ_WRITE;
1387        }
1388    }
1389
1390    /**
1391    * Check if we create/destroy an encoder */
1392    if( ( M4VSS3GPP_kEditAudioState_READ_WRITE == previousAstate)
1393        && /**< read mode */
1394        (M4VSS3GPP_kEditAudioState_READ_WRITE != pC->Astate) ) /**< encode mode */
1395    {
1396        M4OSA_UInt32 uiAudioBitrate;
1397
1398        /* Compute max bitrate depending on input files bitrates and transitions */
1399        if( pC->Astate == M4VSS3GPP_kEditAudioState_TRANSITION )
1400        {
1401            /* Max of the two blended files */
1402            if( pC->pC1->pSettings->ClipProperties.uiAudioBitrate
1403                > pC->pC2->pSettings->ClipProperties.uiAudioBitrate )
1404                uiAudioBitrate =
1405                pC->pC1->pSettings->ClipProperties.uiAudioBitrate;
1406            else
1407                uiAudioBitrate =
1408                pC->pC2->pSettings->ClipProperties.uiAudioBitrate;
1409        }
1410        else
1411        {
1412            /* Same as input file */
1413            uiAudioBitrate = pC->pC1->pSettings->ClipProperties.uiAudioBitrate;
1414        }
1415
1416        /**
1417        * Create the encoder */
1418        err = M4VSS3GPP_intCreateAudioEncoder(&pC->ewc, &pC->ShellAPI,
1419            uiAudioBitrate);
1420
1421        if( M4NO_ERROR != err )
1422        {
1423            M4OSA_TRACE1_1(
1424                "M4VSS3GPP_intCheckAudioMode: M4VSS3GPP_intResetAudioEncoder() returns 0x%x!",
1425                err);
1426            return err;
1427        }
1428    }
1429
1430    /**
1431    * Return with no error */
1432    M4OSA_TRACE3_0("M4VSS3GPP_intCheckAudioMode(): returning M4NO_ERROR");
1433    return M4NO_ERROR;
1434}
1435
1436/**
1437 ******************************************************************************
1438 * M4OSA_Void M4VSS3GPP_intCheckAudioEffects()
1439 * @brief    Check which audio effect must be applied at the current time
1440 ******************************************************************************
1441 */
1442static M4OSA_Void M4VSS3GPP_intCheckAudioEffects( M4VSS3GPP_InternalEditContext
1443                                                 *pC, M4OSA_UInt8 uiClipNumber )
1444{
1445    M4OSA_UInt8 uiClipIndex;
1446    M4OSA_UInt8 uiFxIndex;
1447    M4VSS3GPP_ClipContext *pClip;
1448    M4VSS3GPP_EffectSettings *pFx;
1449    M4OSA_Int32 BC, EC;
1450    M4OSA_Int8 *piClipActiveEffect;
1451    M4OSA_Int32 t;
1452
1453    if( 1 == uiClipNumber )
1454    {
1455        uiClipIndex = pC->uiCurrentClip;
1456        pClip = pC->pC1;
1457        piClipActiveEffect = &(pC->iClip1ActiveEffect);
1458    }
1459    else /**< (2 == uiClipNumber) */
1460    {
1461        uiClipIndex = pC->uiCurrentClip + 1;
1462        pClip = pC->pC2;
1463        piClipActiveEffect = &(pC->iClip2ActiveEffect);
1464    }
1465
1466    /**
1467    * Shortcuts for code readability */
1468    BC = pClip->iActualAudioBeginCut;
1469    EC = pClip->iEndTime;
1470
1471    /**
1472    Change the absolut time to clip related time
1473     RC t = (M4OSA_Int32)(pC->ewc.dATo - pClip->iAoffset/pClip->scale_audio + 0.5);
1474    < rounding */;
1475    t = (M4OSA_Int32)(pC->ewc.dATo/*- pClip->iAoffset/pClip->scale_audio*/
1476        + 0.5); /**< rounding */
1477    ;
1478
1479    /**
1480    * Default: no effect active */
1481    *piClipActiveEffect = -1;
1482
1483    /**
1484    * Check the three effects */
1485    // RC    for (uiFxIndex=0; uiFxIndex<pC->pClipList[uiClipIndex].nbEffects; uiFxIndex++)
1486    for ( uiFxIndex = 0; uiFxIndex < pC->nbEffects; uiFxIndex++ )
1487    {
1488        /** Shortcut, reverse order because of priority between effects
1489        ( EndEffect always clean ) */
1490        pFx = &(pC->pEffectsList[pC->nbEffects - 1 - uiFxIndex]);
1491
1492        if( M4VSS3GPP_kAudioEffectType_None != pFx->AudioEffectType )
1493        {
1494            /**
1495            * Check if there is actually a video effect */
1496            if( ( t >= (M4OSA_Int32)(/*BC +*/pFx->uiStartTime))
1497                && /**< Are we after the start time of the effect? */
1498                (t < (M4OSA_Int32)(/*BC +*/pFx->uiStartTime + pFx->
1499                uiDuration)) ) /**< Are we into the effect duration? */
1500            {
1501                /**
1502                * Set the active effect */
1503                *piClipActiveEffect = pC->nbEffects - 1 - uiFxIndex;
1504
1505                /**
1506                * The first effect has the highest priority, then the second one,
1507                  then the thirs one.
1508                * Hence, as soon as we found an active effect, we can get out of this loop */
1509                uiFxIndex = pC->nbEffects; /** get out of the for loop */
1510            }
1511            /**
1512            * Bugfix: The duration of the end effect has been set according to the
1513                      announced clip duration.
1514            * If the announced duration is smaller than the real one, the end effect
1515                      won't be applied at
1516            * the very end of the clip. To solve this issue we force the end effect. */
1517
1518        }
1519    }
1520
1521    return;
1522}
1523
1524/**
1525 ******************************************************************************
1526 * M4OSA_ERR M4VSS3GPP_intApplyAudioEffect()
1527 * @brief    Apply audio effect to pPCMdata
1528 * @param   pC            (IN/OUT) Internal edit context
1529 * @param   uiClip1orClip2    (IN/OUT) 1 for first clip, 2 for second clip
1530 * @param    pPCMdata    (IN/OUT) Input and Output PCM audio data
1531 * @param    uiPCMsize    (IN)     Size of pPCMdata
1532 * @return    M4NO_ERROR:                        No error
1533 ******************************************************************************
1534 */
1535static M4OSA_ERR M4VSS3GPP_intApplyAudioEffect( M4VSS3GPP_InternalEditContext
1536                                               *pC, M4OSA_UInt8 uiClip1orClip2,
1537                                               M4OSA_Int16 *pPCMdata,
1538                                               M4OSA_UInt32 uiPCMsize )
1539{
1540    M4VSS3GPP_ClipContext *pClip;
1541    M4VSS3GPP_ClipSettings *pClipSettings;
1542    M4VSS3GPP_EffectSettings *pFx;
1543    M4OSA_Int32
1544        i32sample; /**< we will cast each Int16 sample into this Int32 variable */
1545    M4OSA_Int32 iPos;
1546    M4OSA_Int32 iDur;
1547
1548    M4OSA_DEBUG_IF2(( 1 != uiClip1orClip2) && (2 != uiClip1orClip2),
1549        M4ERR_PARAMETER,
1550        "M4VSS3GPP_intBeginAudioEffect: uiClip1orClip2 invalid");
1551
1552    if( 1 == uiClip1orClip2 )
1553    {
1554        pClip = pC->pC1;
1555        pClipSettings = &(pC->pClipList[pC->
1556            uiCurrentClip]); /**< Get a shortcut to the clip settings */
1557        // RC        pFx = &(pClipSettings->Effects[pC->iClip1ActiveEffect]);/**< Get a shortcut
1558        //                                                                to the active effect */
1559        pFx = &(pC->
1560            pEffectsList[pC->
1561            iClip1ActiveEffect]); /**< Get a shortcut to the active effect */
1562        M4OSA_DEBUG_IF2(( pC->iClip1ActiveEffect < 0)
1563            || (pC->iClip1ActiveEffect > 2), M4ERR_PARAMETER,
1564            "M4VSS3GPP_intApplyAudioEffect: iClip1ActiveEffect invalid");
1565    }
1566    else /**< if (2==uiClip1orClip2) */
1567    {
1568        pClip = pC->pC2;
1569        pClipSettings = &(pC->pClipList[pC->uiCurrentClip
1570            + 1]); /**< Get a shortcut to the clip settings */
1571        // RC        pFx = &(pClipSettings->Effects[pC->iClip2ActiveEffect]);/**< Get a shortcut
1572        //                                                                to the active effect */
1573        pFx = &(pC->
1574            pEffectsList[pC->
1575            iClip2ActiveEffect]); /**< Get a shortcut to the active effect */
1576        M4OSA_DEBUG_IF2(( pC->iClip2ActiveEffect < 0)
1577            || (pC->iClip2ActiveEffect > 2), M4ERR_PARAMETER,
1578            "M4VSS3GPP_intApplyAudioEffect: iClip2ActiveEffect invalid");
1579    }
1580
1581    iDur = (M4OSA_Int32)pFx->uiDuration;
1582
1583    /**
1584    * Compute how far from the beginning of the effect we are, in clip-base time.
1585    * It is done with integers because the offset and begin cut have been rounded already. */
1586    iPos =
1587        (M4OSA_Int32)(pC->ewc.dATo + 0.5 - pClip->iAoffset / pClip->scale_audio)
1588        - pClip->iActualAudioBeginCut - pFx->uiStartTime;
1589
1590    /**
1591    * Sanity check */
1592    if( iPos > iDur )
1593    {
1594        iPos = iDur;
1595    }
1596    else if( iPos < 0 )
1597    {
1598        iPos = 0;
1599    }
1600
1601    /**
1602    * At this point, iPos is the effect progress, in a 0 to iDur base */
1603    switch( pFx->AudioEffectType )
1604    {
1605        case M4VSS3GPP_kAudioEffectType_FadeIn:
1606
1607            /**
1608            * Original samples are signed 16bits.
1609            * We convert it to signed 32bits and multiply it by iPos.
1610            * So we must assure that iPos is not higher that 16bits max.
1611            * iPos max value is iDur, so we test iDur. */
1612            while( iDur > PWR_FXP_FRACT_MAX )
1613            {
1614                iDur >>=
1615                    2; /**< divide by 2 would be more logical (instead of 4),
1616                       but we have enough dynamic..) */
1617                iPos >>= 2; /**< idem */
1618            }
1619
1620            /**
1621            * From buffer size (bytes) to number of sample (int16): divide by two */
1622            uiPCMsize >>= 1;
1623
1624            /**
1625            * Loop on samples */
1626            while( uiPCMsize-- > 0 ) /**< decrementing to optimize */
1627            {
1628                i32sample = *pPCMdata;
1629                i32sample *= iPos;
1630                i32sample /= iDur;
1631                *pPCMdata++ = (M4OSA_Int16)i32sample;
1632            }
1633
1634            break;
1635
1636        case M4VSS3GPP_kAudioEffectType_FadeOut:
1637
1638            /**
1639            * switch from 0->Dur to Dur->0 in order to do fadeOUT instead of fadeIN */
1640            iPos = iDur - iPos;
1641
1642            /**
1643            * Original samples are signed 16bits.
1644            * We convert it to signed 32bits and multiply it by iPos.
1645            * So we must assure that iPos is not higher that 16bits max.
1646            * iPos max value is iDur, so we test iDur. */
1647            while( iDur > PWR_FXP_FRACT_MAX )
1648            {
1649                iDur >>=
1650                    2; /**< divide by 2 would be more logical (instead of 4),
1651                       but we have enough dynamic..) */
1652                iPos >>= 2; /**< idem */
1653            }
1654
1655            /**
1656            * From buffer size (bytes) to number of sample (int16): divide by two */
1657            uiPCMsize >>= 1;
1658
1659            /**
1660            * Loop on samples, apply the fade factor on each */
1661            while( uiPCMsize-- > 0 ) /**< decrementing counter to optimize */
1662            {
1663                i32sample = *pPCMdata;
1664                i32sample *= iPos;
1665                i32sample /= iDur;
1666                *pPCMdata++ = (M4OSA_Int16)i32sample;
1667            }
1668
1669            break;
1670
1671        default:
1672            M4OSA_TRACE1_1(
1673                "M4VSS3GPP_intApplyAudioEffect: unknown audio effect type (0x%x),\
1674                returning M4VSS3GPP_ERR_INVALID_AUDIO_EFFECT_TYPE",
1675                pFx->AudioEffectType);
1676            return M4VSS3GPP_ERR_INVALID_AUDIO_EFFECT_TYPE;
1677    }
1678
1679    /**
1680    *    Return */
1681    M4OSA_TRACE3_0("M4VSS3GPP_intApplyAudioEffect: returning M4NO_ERROR");
1682    return M4NO_ERROR;
1683}
1684
1685/**
1686 ******************************************************************************
1687 * M4OSA_ERR M4VSS3GPP_intAudioTransition()
1688 * @brief    Apply transition effect to two PCM buffer
1689 * @note    The result of the transition is put in the first buffer.
1690 *          I know it's not beautiful, but it fits my current needs, and it's efficient!
1691 *          So why bother with a third output buffer?
1692 * @param   pC            (IN/OUT) Internal edit context
1693 * @param    pPCMdata1    (IN/OUT) First input and Output PCM audio data
1694 * @param    pPCMdata2    (IN) Second input PCM audio data
1695 * @param    uiPCMsize    (IN) Size of both PCM buffers
1696 * @return    M4NO_ERROR:                        No error
1697 ******************************************************************************
1698 */
1699static M4OSA_ERR M4VSS3GPP_intAudioTransition( M4VSS3GPP_InternalEditContext
1700                                              *pC, M4OSA_Int16 *pPCMdata1,
1701                                              M4OSA_Int16 *pPCMdata2,
1702                                              M4OSA_UInt32 uiPCMsize )
1703{
1704    M4OSA_Int32 i32sample1,
1705        i32sample2; /**< we will cast each Int16 sample into this Int32 variable */
1706    M4OSA_Int32 iPos1, iPos2;
1707    M4OSA_Int32 iDur = (M4OSA_Int32)pC->
1708        pTransitionList[pC->uiCurrentClip].uiTransitionDuration;
1709
1710    /**
1711    * Compute how far from the end cut we are, in clip-base time.
1712    * It is done with integers because the offset and begin cut have been rounded already. */
1713    iPos1 = pC->pC1->iEndTime - (M4OSA_Int32)(pC->ewc.dATo
1714        + 0.5 - pC->pC1->iAoffset / pC->pC1->scale_audio);
1715
1716    /**
1717    * Sanity check */
1718    if( iPos1 > iDur )
1719    {
1720        iPos1 = iDur;
1721    }
1722    else if( iPos1 < 0 )
1723    {
1724        iPos1 = 0;
1725    }
1726
1727    /**
1728    * Position of second clip in the transition */
1729    iPos2 = iDur - iPos1;
1730
1731    /**
1732    * At this point, iPos2 is the transition progress, in a 0 to iDur base.
1733    * iPos1 is the transition progress, in a iDUr to 0 base. */
1734    switch( pC->pTransitionList[pC->uiCurrentClip].AudioTransitionType )
1735    {
1736        case M4VSS3GPP_kAudioTransitionType_CrossFade:
1737
1738            /**
1739            * Original samples are signed 16bits.
1740            * We convert it to signed 32bits and multiply it by iPos.
1741            * So we must assure that iPos is not higher that 16bits max.
1742            * iPos max value is iDur, so we test iDur. */
1743            while( iDur > PWR_FXP_FRACT_MAX )
1744            {
1745                iDur >>=
1746                    2; /**< divide by 2 would be more logical (instead of 4),
1747                       but we have enough dynamic..) */
1748                iPos1 >>= 2; /**< idem */
1749                iPos2 >>= 2; /**< idem */
1750            }
1751
1752            /**
1753            * From buffer size (bytes) to number of sample (int16): divide by two */
1754            uiPCMsize >>= 1;
1755
1756            /**
1757            * Loop on samples, apply the fade factor on each */
1758            while( uiPCMsize-- > 0 ) /**< decrementing counter to optimize */
1759            {
1760                i32sample1 = *pPCMdata1; /**< Get clip1 sample */
1761                i32sample1 *= iPos1;     /**< multiply by fade numerator */
1762                i32sample1 /= iDur;      /**< divide by fade denominator */
1763
1764                i32sample2 = *pPCMdata2; /**< Get clip2 sample */
1765                i32sample2 *= iPos2;     /**< multiply by fade numerator */
1766                i32sample2 /= iDur;      /**< divide by fade denominator */
1767
1768                *pPCMdata1++ = (M4OSA_Int16)(i32sample1
1769                    + i32sample2); /**< mix the two samples */
1770                pPCMdata2++; /**< don't forget to increment the second buffer */
1771            }
1772            break;
1773
1774        case M4VSS3GPP_kAudioTransitionType_None:
1775            /**
1776            * This is a stupid-non optimized version of the None transition...
1777            * We copy the PCM frames */
1778            if( iPos1 < (iDur >> 1) ) /**< second half of transition */
1779            {
1780                /**
1781                * Copy the input PCM to the output buffer */
1782                memcpy((void *)pPCMdata1,
1783                    (void *)pPCMdata2, uiPCMsize);
1784            }
1785            /**
1786            * the output must be put in the first buffer.
1787            * For the first half of the non-transition it's already the case!
1788            * So we have nothing to do here...
1789            */
1790
1791            break;
1792
1793        default:
1794            M4OSA_TRACE1_1(
1795                "M4VSS3GPP_intAudioTransition: unknown transition type (0x%x),\
1796                returning M4VSS3GPP_ERR_INVALID_AUDIO_TRANSITION_TYPE",
1797                pC->pTransitionList[pC->uiCurrentClip].AudioTransitionType);
1798            return M4VSS3GPP_ERR_INVALID_AUDIO_TRANSITION_TYPE;
1799    }
1800
1801    /**
1802    *    Return */
1803    M4OSA_TRACE3_0("M4VSS3GPP_intAudioTransition: returning M4NO_ERROR");
1804    return M4NO_ERROR;
1805}
1806
1807/**
1808 ******************************************************************************
1809 * M4OSA_ERR M4VSS3GPP_intCreateAudioEncoder()
1810 * @brief    Reset the audio encoder (Create it if needed)
1811 * @note
1812 ******************************************************************************
1813 */
1814M4OSA_ERR M4VSS3GPP_intCreateAudioEncoder( M4VSS3GPP_EncodeWriteContext *pC_ewc,
1815                                          M4VSS3GPP_MediaAndCodecCtxt *pC_ShellAPI,
1816                                          M4OSA_UInt32 uiAudioBitrate )
1817{
1818    M4OSA_ERR err;
1819
1820    /**
1821    * If an encoder already exist, we destroy it */
1822    if( M4OSA_NULL != pC_ewc->pAudioEncCtxt )
1823    {
1824        err = pC_ShellAPI->pAudioEncoderGlobalFcts->pFctClose(
1825            pC_ewc->pAudioEncCtxt);
1826
1827        if( M4NO_ERROR != err )
1828        {
1829            M4OSA_TRACE1_1(
1830                "M4VSS3GPP_intResetAudioEncoder: pAudioEncoderGlobalFcts->pFctClose returns 0x%x",
1831                err);
1832            /**< don't return, we still have stuff to free */
1833        }
1834
1835        err = pC_ShellAPI->pAudioEncoderGlobalFcts->pFctCleanUp(
1836            pC_ewc->pAudioEncCtxt);
1837
1838        if( M4NO_ERROR != err )
1839        {
1840            M4OSA_TRACE1_1(
1841                "M4VSS3GPP_intResetAudioEncoder:\
1842                pAudioEncoderGlobalFcts->pFctCleanUp returns 0x%x",    err);
1843            /**< don't return, we still have stuff to free */
1844        }
1845
1846        pC_ewc->pAudioEncCtxt = M4OSA_NULL;
1847    }
1848
1849    /**
1850    * Creates a new encoder  */
1851    switch( pC_ewc->AudioStreamType )
1852    {
1853            //EVRC
1854            //        case M4SYS_kEVRC:
1855            //
1856            //            err = M4VSS3GPP_setCurrentAudioEncoder(&pC->ShellAPI,
1857            //                                                   pC_ewc->AudioStreamType);
1858            //            M4ERR_CHECK_RETURN(err);
1859            //
1860            //            pC_ewc->AudioEncParams.Format = M4ENCODER_kEVRC;
1861            //            pC_ewc->AudioEncParams.Frequency = M4ENCODER_k8000Hz;
1862            //            pC_ewc->AudioEncParams.ChannelNum = M4ENCODER_kMono;
1863            //            pC_ewc->AudioEncParams.Bitrate = M4VSS3GPP_EVRC_DEFAULT_BITRATE;
1864            //            break;
1865
1866        case M4SYS_kAMR:
1867
1868            err = M4VSS3GPP_setCurrentAudioEncoder(pC_ShellAPI,
1869                pC_ewc->AudioStreamType);
1870            M4ERR_CHECK_RETURN(err);
1871
1872            pC_ewc->AudioEncParams.Format = M4ENCODER_kAMRNB;
1873            pC_ewc->AudioEncParams.Frequency = M4ENCODER_k8000Hz;
1874            pC_ewc->AudioEncParams.ChannelNum = M4ENCODER_kMono;
1875            pC_ewc->AudioEncParams.Bitrate = M4VSS3GPP_AMR_DEFAULT_BITRATE;
1876            pC_ewc->AudioEncParams.SpecifParam.AmrSID = M4ENCODER_kAmrNoSID;
1877            break;
1878
1879        case M4SYS_kAAC:
1880
1881            err = M4VSS3GPP_setCurrentAudioEncoder(pC_ShellAPI,
1882                pC_ewc->AudioStreamType);
1883            M4ERR_CHECK_RETURN(err);
1884
1885            pC_ewc->AudioEncParams.Format = M4ENCODER_kAAC;
1886
1887            switch( pC_ewc->uiSamplingFrequency )
1888            {
1889                case 8000:
1890                    pC_ewc->AudioEncParams.Frequency = M4ENCODER_k8000Hz;
1891                    break;
1892
1893                case 16000:
1894                    pC_ewc->AudioEncParams.Frequency = M4ENCODER_k16000Hz;
1895                    break;
1896
1897                case 22050:
1898                    pC_ewc->AudioEncParams.Frequency = M4ENCODER_k22050Hz;
1899                    break;
1900
1901                case 24000:
1902                    pC_ewc->AudioEncParams.Frequency = M4ENCODER_k24000Hz;
1903                    break;
1904
1905                case 32000:
1906                    pC_ewc->AudioEncParams.Frequency = M4ENCODER_k32000Hz;
1907                    break;
1908
1909                case 44100:
1910                    pC_ewc->AudioEncParams.Frequency = M4ENCODER_k44100Hz;
1911                    break;
1912
1913                case 48000:
1914                    pC_ewc->AudioEncParams.Frequency = M4ENCODER_k48000Hz;
1915                    break;
1916
1917                default:
1918                    M4OSA_TRACE1_1(
1919                        "M4VSS3GPP_intCreateAudioEncoder: invalid input AAC sampling frequency\
1920                        (%d Hz), returning M4VSS3GPP_ERR_AUDIO_DECODER_INIT_FAILED",
1921                        pC_ewc->uiSamplingFrequency);
1922                    return M4VSS3GPP_ERR_AUDIO_DECODER_INIT_FAILED;
1923            }
1924            pC_ewc->AudioEncParams.ChannelNum = (pC_ewc->uiNbChannels == 1)
1925                ? M4ENCODER_kMono : M4ENCODER_kStereo;
1926            pC_ewc->AudioEncParams.SpecifParam.AacParam.Regulation =
1927                M4ENCODER_kAacRegulNone; //M4ENCODER_kAacBitReservoir
1928            /* unused */
1929            pC_ewc->AudioEncParams.SpecifParam.AacParam.bIS = M4OSA_FALSE;
1930            pC_ewc->AudioEncParams.SpecifParam.AacParam.bMS = M4OSA_FALSE;
1931            pC_ewc->AudioEncParams.SpecifParam.AacParam.bPNS = M4OSA_FALSE;
1932            pC_ewc->AudioEncParams.SpecifParam.AacParam.bTNS = M4OSA_FALSE;
1933            /* TODO change into highspeed asap */
1934            pC_ewc->AudioEncParams.SpecifParam.AacParam.bHighSpeed =
1935                M4OSA_FALSE;
1936
1937            /* Quantify value (ceil one) */
1938            if( uiAudioBitrate <= 16000 )
1939                pC_ewc->AudioEncParams.Bitrate = 16000;
1940
1941            else if( uiAudioBitrate <= 24000 )
1942                pC_ewc->AudioEncParams.Bitrate = 24000;
1943
1944            else if( uiAudioBitrate <= 32000 )
1945                pC_ewc->AudioEncParams.Bitrate = 32000;
1946
1947            else if( uiAudioBitrate <= 48000 )
1948                pC_ewc->AudioEncParams.Bitrate = 48000;
1949
1950            else if( uiAudioBitrate <= 64000 )
1951                pC_ewc->AudioEncParams.Bitrate = 64000;
1952
1953            else
1954                pC_ewc->AudioEncParams.Bitrate = 96000;
1955
1956            /* Special requirement of our encoder */
1957            if( ( pC_ewc->uiNbChannels == 2)
1958                && (pC_ewc->AudioEncParams.Bitrate < 32000) )
1959                pC_ewc->AudioEncParams.Bitrate = 32000;
1960
1961            break;
1962
1963        default:
1964            M4OSA_TRACE1_1(
1965                "M4VSS3GPP_intResetAudioEncoder: Undefined output audio format (%d),\
1966                returning M4VSS3GPP_ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT",
1967                pC_ewc->AudioStreamType);
1968            return M4VSS3GPP_ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT;
1969    }
1970
1971    /* Initialise the audio encoder */
1972#ifdef M4VSS_SUPPORT_OMX_CODECS
1973
1974    M4OSA_TRACE3_1(
1975        "M4VSS3GPP_intResetAudioEncoder:\
1976        pAudioEncoderGlobalFcts->pFctInit called with userdata 0x%x",
1977        pC_ShellAPI->pCurrentAudioEncoderUserData);
1978    err = pC_ShellAPI->pAudioEncoderGlobalFcts->pFctInit(&pC_ewc->pAudioEncCtxt,
1979        pC_ShellAPI->pCurrentAudioEncoderUserData);
1980
1981#else
1982
1983    err = pC_ShellAPI->pAudioEncoderGlobalFcts->pFctInit(&pC_ewc->pAudioEncCtxt,
1984        M4OSA_NULL /* no HW encoder */);
1985
1986#endif
1987
1988    if( M4NO_ERROR != err )
1989    {
1990        M4OSA_TRACE1_1(
1991            "M4VSS3GPP_intResetAudioEncoder: pAudioEncoderGlobalFcts->pFctInit returns 0x%x",
1992            err);
1993        return err;
1994    }
1995
1996    /* Open the audio encoder */
1997    err = pC_ShellAPI->pAudioEncoderGlobalFcts->pFctOpen(pC_ewc->pAudioEncCtxt,
1998        &pC_ewc->AudioEncParams, &pC_ewc->pAudioEncDSI,
1999        M4OSA_NULL /* no grabbing */);
2000
2001    if( M4NO_ERROR != err )
2002    {
2003        M4OSA_TRACE1_1(
2004            "M4VSS3GPP_intResetAudioEncoder: pAudioEncoderGlobalFcts->pFctOpen returns 0x%x",
2005            err);
2006        return err;
2007    }
2008
2009    /**
2010    * Return with no error */
2011    M4OSA_TRACE3_0("M4VSS3GPP_intResetAudioEncoder: returning M4NO_ERROR");
2012    return M4NO_ERROR;
2013}
2014