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