• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
M4VSS3GPP_intEditJumpMP3(M4VSS3GPP_InternalEditContext * pC)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  */
M4VSS3GPP_intEditStepMP3(M4VSS3GPP_InternalEditContext * pC)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  */
M4VSS3GPP_intEditStepAudio(M4VSS3GPP_InternalEditContext * pC)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  */
M4VSS3GPP_intCheckAudioMode(M4VSS3GPP_InternalEditContext * pC)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  */
M4VSS3GPP_intCheckAudioEffects(M4VSS3GPP_InternalEditContext * pC,M4OSA_UInt8 uiClipNumber)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  */
M4VSS3GPP_intApplyAudioEffect(M4VSS3GPP_InternalEditContext * pC,M4OSA_UInt8 uiClip1orClip2,M4OSA_Int16 * pPCMdata,M4OSA_UInt32 uiPCMsize)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  */
M4VSS3GPP_intAudioTransition(M4VSS3GPP_InternalEditContext * pC,M4OSA_Int16 * pPCMdata1,M4OSA_Int16 * pPCMdata2,M4OSA_UInt32 uiPCMsize)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  */
M4VSS3GPP_intCreateAudioEncoder(M4VSS3GPP_EncodeWriteContext * pC_ewc,M4VSS3GPP_MediaAndCodecCtxt * pC_ShellAPI,M4OSA_UInt32 uiAudioBitrate)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