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