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