M4VSS3GPP_Clip.c revision bc8e52dadeb078c45e62ebda17fd95e67f689654
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_Clip.c
19 * @brief    Implementation of functions related to input clip management.
20 * @note    All functions in this file are static, i.e. non public
21 ******************************************************************************
22 */
23
24/****************/
25/*** Includes ***/
26/****************/
27
28#include "NXPSW_CompilerSwitches.h"
29/**
30 *    Our headers */
31#include "M4VSS3GPP_API.h"
32#include "M4VSS3GPP_ErrorCodes.h"
33#include "M4VSS3GPP_InternalTypes.h"
34#include "M4VSS3GPP_InternalFunctions.h"
35#include "M4VSS3GPP_InternalConfig.h"
36
37/**
38 *    OSAL headers */
39#include "M4OSA_Memory.h" /* OSAL memory management */
40#include "M4OSA_Debug.h"  /* OSAL debug management */
41
42
43/**
44 * Common headers (for aac) */
45#include "M4_Common.h"
46
47#ifdef M4VSS_ENABLE_EXTERNAL_DECODERS
48#include "M4VD_EXTERNAL_Interface.h"
49
50#endif /* M4VSS_ENABLE_EXTERNAL_DECODERS */
51
52/* Osal header fileno */
53#include "M4OSA_CharStar.h"
54
55/**
56 ******************************************************************************
57 * define    Static function prototypes
58 ******************************************************************************
59 */
60
61static M4OSA_ERR M4VSS3GPP_intClipPrepareAudioDecoder(
62    M4VSS3GPP_ClipContext *pClipCtxt );
63
64static M4OSA_ERR M4VSS3GPP_intCheckAndGetCodecAacProperties(
65        M4VSS3GPP_ClipContext *pClipCtxt);
66
67/**
68 ******************************************************************************
69 * M4OSA_ERR M4VSS3GPP_intClipOpen()
70 * @brief    Open a clip. Creates a clip context.
71 * @note
72 * @param   hClipCtxt            (OUT) Return the internal clip context
73 * @param   pClipSettings        (IN) Edit settings of this clip. The module will keep a
74 *                               reference to this pointer
75 * @param    pFileReadPtrFct        (IN) Pointer to OSAL file reader functions
76 * @param    bSkipAudioTrack        (IN) If true, do not open the audio
77 * @param    bFastOpenMode        (IN) If true, use the fast mode of the 3gpp reader
78 *                             (only the first AU is read)
79 * @return    M4NO_ERROR:                No error
80 * @return    M4ERR_ALLOC:            There is no more available memory
81 ******************************************************************************
82 */
83
84M4OSA_ERR M4VSS3GPP_intClipInit( M4VSS3GPP_ClipContext ** hClipCtxt,
85                                M4OSA_FileReadPointer *pFileReadPtrFct )
86{
87    M4VSS3GPP_ClipContext *pClipCtxt;
88    M4OSA_ERR err;
89
90    M4OSA_DEBUG_IF2((M4OSA_NULL == hClipCtxt), M4ERR_PARAMETER,
91        "M4VSS3GPP_intClipInit: hClipCtxt is M4OSA_NULL");
92    M4OSA_DEBUG_IF2((M4OSA_NULL == pFileReadPtrFct), M4ERR_PARAMETER,
93        "M4VSS3GPP_intClipInit: pFileReadPtrFct is M4OSA_NULL");
94
95    /**
96    * Allocate the clip context */
97    *hClipCtxt =
98        (M4VSS3GPP_ClipContext *)M4OSA_32bitAlignedMalloc(sizeof(M4VSS3GPP_ClipContext),
99        M4VSS3GPP, (M4OSA_Char *)"M4VSS3GPP_ClipContext");
100
101    if( M4OSA_NULL == *hClipCtxt )
102    {
103        M4OSA_TRACE1_0(
104            "M4VSS3GPP_intClipInit(): unable to allocate M4VSS3GPP_ClipContext,\
105            returning M4ERR_ALLOC");
106        return M4ERR_ALLOC;
107    }
108    M4OSA_TRACE3_1("M4VSS3GPP_intClipInit(): clipCtxt=0x%x", *hClipCtxt);
109
110
111    /**
112    * Use this shortcut to simplify the code */
113    pClipCtxt = *hClipCtxt;
114
115    /* Inialization of context Variables */
116    memset((void *)pClipCtxt, 0,sizeof(M4VSS3GPP_ClipContext));
117
118    pClipCtxt->pSettings = M4OSA_NULL;
119
120    /**
121    * Init the clip context */
122    pClipCtxt->Vstatus = M4VSS3GPP_kClipStatus_READ;
123    pClipCtxt->Astatus = M4VSS3GPP_kClipStatus_READ;
124
125    pClipCtxt->pReaderContext = M4OSA_NULL;
126    pClipCtxt->pVideoStream = M4OSA_NULL;
127    pClipCtxt->pAudioStream = M4OSA_NULL;
128    pClipCtxt->VideoAU.m_dataAddress = M4OSA_NULL;
129    pClipCtxt->AudioAU.m_dataAddress = M4OSA_NULL;
130
131    pClipCtxt->pViDecCtxt = M4OSA_NULL;
132    pClipCtxt->bVideoAuAvailable = M4OSA_FALSE;
133    pClipCtxt->bFirstAuWritten = M4OSA_FALSE;
134
135    pClipCtxt->bMpeg4GovState = M4OSA_FALSE;
136
137    pClipCtxt->bAudioFrameAvailable = M4OSA_FALSE;
138    pClipCtxt->pAudioFramePtr = M4OSA_NULL;
139    pClipCtxt->AudioDecBufferOut.m_dataAddress = M4OSA_NULL;
140
141    pClipCtxt->pFileReadPtrFct = pFileReadPtrFct;
142
143    /*
144    * Reset pointers for media and codecs interfaces */
145    err = M4VSS3GPP_clearInterfaceTables(&pClipCtxt->ShellAPI);
146    M4ERR_CHECK_RETURN(err);
147
148    /*
149    *  Call the media and codecs subscription module */
150    err = M4VSS3GPP_subscribeMediaAndCodec(&pClipCtxt->ShellAPI);
151    M4ERR_CHECK_RETURN(err);
152
153    return M4NO_ERROR;
154}
155
156/* Note: if the clip is opened in fast mode, it can only be used for analysis and nothing else. */
157M4OSA_ERR M4VSS3GPP_intClipOpen( M4VSS3GPP_ClipContext *pClipCtxt,
158                                M4VSS3GPP_ClipSettings *pClipSettings, M4OSA_Bool bSkipAudioTrack,
159                                M4OSA_Bool bFastOpenMode, M4OSA_Bool bAvoidOpeningVideoDec )
160{
161    M4OSA_ERR err;
162    M4READER_MediaFamily mediaFamily;
163    M4_StreamHandler *pStreamHandler;
164    M4OSA_Int32 iDuration;
165    M4OSA_Void *decoderUserData;
166#ifdef M4VSS_ENABLE_EXTERNAL_DECODERS
167
168    M4DECODER_MPEG4_DecoderConfigInfo dummy;
169    M4DECODER_VideoSize videoSizeFromDSI;
170#endif /* M4VSS_ENABLE_EXTERNAL_DECODERS */
171
172    M4DECODER_OutputFilter FilterOption;
173    M4OSA_Char pTempFile[100];
174
175    /**
176    *    Check input parameters */
177    M4OSA_DEBUG_IF2((M4OSA_NULL == pClipCtxt), M4ERR_PARAMETER,
178        "M4VSS3GPP_intClipOpen: pClipCtxt is M4OSA_NULL");
179    M4OSA_DEBUG_IF2((M4OSA_NULL == pClipSettings), M4ERR_PARAMETER,
180        "M4VSS3GPP_intClipOpen: pClipSettings is M4OSA_NULL");
181
182    M4OSA_TRACE3_2(
183        "M4VSS3GPP_intClipOpen: called with pClipCtxt: 0x%x, bAvoidOpeningVideoDec=0x%x",
184        pClipCtxt, bAvoidOpeningVideoDec);
185    /**
186    * Keep a pointer to the clip settings. Remember that we don't possess it! */
187    pClipCtxt->pSettings = pClipSettings;
188
189    /**
190    * Get the correct reader interface */
191    err = M4VSS3GPP_setCurrentReader(&pClipCtxt->ShellAPI,
192        pClipCtxt->pSettings->FileType);
193    M4ERR_CHECK_RETURN(err);
194
195    /**
196    * Init the 3GPP or MP3 reader */
197    err =
198        pClipCtxt->ShellAPI.m_pReader->m_pFctCreate(&pClipCtxt->pReaderContext);
199
200    if( M4NO_ERROR != err )
201    {
202        M4OSA_TRACE1_1(
203            "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctCreate returns 0x%x",
204            err);
205        return err;
206    }
207
208    /**
209    * Link the reader interface to the reader context (used by the decoder to know the reader) */
210    pClipCtxt->ShellAPI.m_pReaderDataIt->m_readerContext =
211        pClipCtxt->pReaderContext;
212
213    /**
214    * Set the OSAL read function set */
215    err = pClipCtxt->ShellAPI.m_pReader->m_pFctSetOption(
216        pClipCtxt->pReaderContext,
217        M4READER_kOptionID_SetOsaFileReaderFctsPtr,
218        (M4OSA_DataOption)(pClipCtxt->pFileReadPtrFct));
219
220    if( M4NO_ERROR != err )
221    {
222        M4OSA_TRACE1_1(
223            "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctSetOption returns 0x%x",
224            err);
225        return err;
226    }
227
228    /**
229    * Set the fast open mode if asked (3GPP only) */
230    if( M4VIDEOEDITING_kFileType_3GPP == pClipCtxt->pSettings->FileType )
231    {
232        if( M4OSA_TRUE == bFastOpenMode )
233        {
234            err = pClipCtxt->ShellAPI.m_pReader->m_pFctSetOption(
235                pClipCtxt->pReaderContext,
236                M4READER_3GP_kOptionID_FastOpenMode, M4OSA_NULL);
237
238            if( M4NO_ERROR != err )
239            {
240                M4OSA_TRACE1_1(
241                    "M4VSS3GPP_intClipOpen():\
242                    m_pReader->m_pFctSetOption(FastOpenMode) returns 0x%x",
243                    err);
244                return err;
245            }
246        }
247
248        /**
249        * Set the skip audio option if asked */
250        if( M4OSA_TRUE == bSkipAudioTrack )
251        {
252            err = pClipCtxt->ShellAPI.m_pReader->m_pFctSetOption(
253                pClipCtxt->pReaderContext,
254                M4READER_3GP_kOptionID_VideoOnly, M4OSA_NULL);
255
256            if( M4NO_ERROR != err )
257            {
258                M4OSA_TRACE1_1(
259                    "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctSetOption(VideoOnly) returns 0x%x",
260                    err);
261                return err;
262            }
263        }
264    }
265    if(pClipCtxt->pSettings->FileType == M4VIDEOEDITING_kFileType_PCM)
266    {
267
268
269
270
271        M4OSA_chrNCopy(pTempFile,pClipSettings->pFile,strlen(pClipSettings->pFile));
272
273
274    switch (pClipCtxt->pSettings->ClipProperties.uiSamplingFrequency)
275    {
276        case 8000:
277        strncat((char *)pTempFile,(const char *)"_8000",6);
278        break;
279        case 11025:
280        strncat((char *)pTempFile,(const char *)"_11025",6);
281        break;
282        case 12000:
283        strncat((char *)pTempFile,(const char *)"_12000",6);
284        break;
285        case 16000:
286        strncat((char *)pTempFile,(const char *)"_16000",6);
287        break;
288        case 22050:
289        strncat((char *)pTempFile,(const char *)"_22050",6);
290        break;
291        case 24000:
292        strncat((char *)pTempFile,(const char *)"_24000",6);
293        break;
294        case 32000:
295        strncat((char *)pTempFile,(const char *)"_32000",6);
296        break;
297        case 44100:
298        strncat((char *)pTempFile,(const char *)"_44100",6);
299        break;
300        case 48000:
301        strncat((char *)pTempFile,(const char *)"_48000",6);
302        break;
303        default:
304            M4OSA_TRACE1_1("M4VSS3GPP_intClipOpen: invalid input for BG tracksampling \
305                frequency (%d Hz), returning M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_SAMPLING_FREQUENCY"\
306                    ,pClipCtxt->pSettings->ClipProperties.uiSamplingFrequency );
307            return M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_SAMPLING_FREQUENCY;
308    }
309
310
311
312        //M4OSA_chrNCat(pTempFile,
313        //    itoa(pClipCtxt->pSettings->ClipProperties.uiSamplingFrequency),5);
314        switch(pClipCtxt->pSettings->ClipProperties.uiNbChannels)
315        {
316            case 1:
317                strncat((char *)pTempFile,(const char *)"_1.pcm",6);
318            break;
319            case 2:
320                strncat((char *)pTempFile,(const char *)"_2.pcm",6);
321            break;
322            default:
323            M4OSA_TRACE1_1("M4VSS3GPP_intClipOpen: invalid input for BG track no.\
324                 of channels (%d ), returning M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_NB_OF_CHANNELS",\
325                    pClipCtxt->pSettings->ClipProperties.uiNbChannels);
326            return    M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_NB_OF_CHANNELS;
327        }
328        //M4OSA_chrNCat(pTempFile,itoa(pClipCtxt->pSettings->ClipProperties.uiNbChannels),1);
329
330        err = pClipCtxt->ShellAPI.m_pReader->m_pFctOpen( pClipCtxt->pReaderContext, pTempFile);
331
332    }
333    else
334    {
335    /**
336        * Open the 3GPP/MP3 clip file */
337        err = pClipCtxt->ShellAPI.m_pReader->m_pFctOpen( pClipCtxt->pReaderContext,
338             pClipSettings->pFile);
339    }
340    if( M4NO_ERROR != err )
341    {
342        M4OSA_UInt32 uiDummy, uiCoreId;
343        M4OSA_TRACE1_1(
344            "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctOpen returns 0x%x", err);
345
346        /**
347        * If the error is from the core reader, we change it to a public VSS3GPP error */
348        M4OSA_ERR_SPLIT(err, uiDummy, uiCoreId, uiDummy);
349
350        if( M4MP4_READER == uiCoreId )
351        {
352            M4OSA_TRACE1_0(
353                "M4VSS3GPP_intClipOpen(): returning M4VSS3GPP_ERR_INVALID_3GPP_FILE");
354            return M4VSS3GPP_ERR_INVALID_3GPP_FILE;
355        }
356        return err;
357    }
358
359    /**
360    * Get the audio and video streams */
361    while( err == M4NO_ERROR )
362    {
363        err = pClipCtxt->ShellAPI.m_pReader->m_pFctGetNextStream(
364            pClipCtxt->pReaderContext, &mediaFamily, &pStreamHandler);
365
366        /*in case we found a BIFS stream or something else...*/
367        if( ( err == ((M4OSA_UInt32)M4ERR_READER_UNKNOWN_STREAM_TYPE))
368            || (err == ((M4OSA_UInt32)M4WAR_TOO_MUCH_STREAMS)) )
369        {
370            err = M4NO_ERROR;
371            continue;
372        }
373
374        if( M4NO_ERROR == err ) /**< One stream found */
375        {
376            /**
377            * Found a video stream */
378            if( ( mediaFamily == M4READER_kMediaFamilyVideo)
379                && (M4OSA_NULL == pClipCtxt->pVideoStream) )
380            {
381                if( ( M4DA_StreamTypeVideoH263 == pStreamHandler->m_streamType)
382                    || (M4DA_StreamTypeVideoMpeg4
383                    == pStreamHandler->m_streamType)
384                    || (M4DA_StreamTypeVideoMpeg4Avc
385                    == pStreamHandler->m_streamType) )
386                {
387                    M4OSA_TRACE3_1(
388                        "M4VSS3GPP_intClipOpen():\
389                        Found a H263 or MPEG-4 or H264 video stream in input 3gpp clip; %d",
390                        pStreamHandler->m_streamType);
391
392                    /**
393                    * Keep pointer to the video stream */
394                    pClipCtxt->pVideoStream =
395                        (M4_VideoStreamHandler *)pStreamHandler;
396                    pStreamHandler->m_bStreamIsOK = M4OSA_TRUE;
397
398                    /**
399                    * Reset the stream reader */
400                    err = pClipCtxt->ShellAPI.m_pReader->m_pFctReset(
401                        pClipCtxt->pReaderContext,
402                        (M4_StreamHandler *)pClipCtxt->pVideoStream);
403
404                    if( M4NO_ERROR != err )
405                    {
406                        M4OSA_TRACE1_1(
407                            "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctReset(video) returns 0x%x",
408                            err);
409                        return err;
410                    }
411
412                    /**
413                    * Initializes an access Unit */
414                    err = pClipCtxt->ShellAPI.m_pReader->m_pFctFillAuStruct(
415                        pClipCtxt->pReaderContext,
416                        (M4_StreamHandler *)pClipCtxt->pVideoStream,
417                        &pClipCtxt->VideoAU);
418
419                    if( M4NO_ERROR != err )
420                    {
421                        M4OSA_TRACE1_1(
422                            "M4VSS3GPP_intClipOpen():\
423                            m_pReader->m_pFctFillAuStruct(video) returns 0x%x",
424                            err);
425                        return err;
426                    }
427                }
428                else /**< Not H263 or MPEG-4 (H264, etc.) */
429                {
430                    M4OSA_TRACE1_1(
431                        "M4VSS_editClipOpen():\
432                        Found an unsupported video stream (0x%x) in input 3gpp clip",
433                        pStreamHandler->m_streamType);
434
435                    pStreamHandler->m_bStreamIsOK = M4OSA_FALSE;
436                }
437            }
438            /**
439            * Found an audio stream */
440            else if( ( mediaFamily == M4READER_kMediaFamilyAudio)
441                && (M4OSA_NULL == pClipCtxt->pAudioStream) )
442            {
443                if( ( M4DA_StreamTypeAudioAmrNarrowBand
444                    == pStreamHandler->m_streamType)
445                    || (M4DA_StreamTypeAudioAac == pStreamHandler->m_streamType)
446                    || (M4DA_StreamTypeAudioMp3
447                    == pStreamHandler->m_streamType)
448                    || (M4DA_StreamTypeAudioEvrc
449                    == pStreamHandler->m_streamType)
450                    || (M4DA_StreamTypeAudioPcm
451                    == pStreamHandler->m_streamType) )
452                {
453                    M4OSA_TRACE3_1(
454                        "M4VSS3GPP_intClipOpen(): \
455                        Found an AMR-NB or AAC or MP3 audio stream in input clip; %d",
456                        pStreamHandler->m_streamType);
457
458                    /**
459                    * Keep pointer to the audio stream */
460                    pClipCtxt->pAudioStream =
461                        (M4_AudioStreamHandler *)pStreamHandler;
462                    pStreamHandler->m_bStreamIsOK = M4OSA_TRUE;
463
464                    /**
465                    * Reset the stream reader */
466                    err = pClipCtxt->ShellAPI.m_pReader->m_pFctReset(
467                        pClipCtxt->pReaderContext,
468                        (M4_StreamHandler *)pClipCtxt->pAudioStream);
469
470                    if( M4NO_ERROR != err )
471                    {
472                        M4OSA_TRACE1_1(
473                            "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctReset(audio) returns 0x%x",
474                            err);
475                        return err;
476                    }
477
478                    /**
479                    * Initializes an access Unit */
480                    err = pClipCtxt->ShellAPI.m_pReader->m_pFctFillAuStruct(
481                        pClipCtxt->pReaderContext,
482                        (M4_StreamHandler *)pClipCtxt->pAudioStream,
483                        &pClipCtxt->AudioAU);
484
485                    if( M4NO_ERROR != err )
486                    {
487                        M4OSA_TRACE1_1(
488                            "M4VSS3GPP_intClipOpen():\
489                            m_pReader->m_pFctFillAuStruct(audio) returns 0x%x",
490                            err);
491                        return err;
492                    }
493                }
494                else /**< Not AMR-NB or AAC (AMR-WB...) */
495                {
496                    M4OSA_TRACE1_1(
497                        "M4VSS3GPP_intClipOpen():\
498                        Found an unsupported audio stream (0x%x) in input 3gpp/mp3 clip",
499                        pStreamHandler->m_streamType);
500
501                    pStreamHandler->m_bStreamIsOK = M4OSA_FALSE;
502                }
503            }
504        }
505        else if( M4OSA_ERR_IS_ERROR(err) )
506        {
507            M4OSA_TRACE1_1(
508                "M4VSS3GPP_intClipOpen(): m_pReader->m_pFctGetNextStream() returns 0x%x!",
509                err);
510            return err;
511        }
512    }
513
514    /**
515    * Init Video decoder */
516    if( M4OSA_NULL != pClipCtxt->pVideoStream )
517    {
518#ifdef M4VSS_ENABLE_EXTERNAL_DECODERS
519  /* If external decoders are possible, it's best to avoid opening the decoder if the clip is only
520  going to be used for analysis, as we're not going to use it for the analysis in the case of a
521  possible external decoder anyway, and either there could be no decoder at this point or the HW
522  decoder could be present, which we want to avoid opening for that. See comments in
523  intBuildAnalysis for more details. */
524
525  /* CHANGEME Temporarily only do this for MPEG4, since for now only MPEG4 external decoders are
526  supported, and the following wouldn't work for H263 so a release where external decoders are
527  possible, but not used, wouldn't work with H263 stuff. */
528
529        if( bAvoidOpeningVideoDec && M4DA_StreamTypeVideoMpeg4
530            == pClipCtxt->pVideoStream->m_basicProperties.m_streamType )
531        {
532            /* Oops! The mere act of opening the decoder also results in the image size being
533            filled in the video stream! Compensate for this by using ParseVideoDSI to fill
534            this info. */
535            M4OSA_TRACE3_0(
536                "M4VSS3GPP_intClipOpen: Mpeg4 stream; vid dec not started");
537            err = M4DECODER_EXTERNAL_ParseVideoDSI(pClipCtxt->pVideoStream->
538                m_basicProperties.m_pDecoderSpecificInfo,
539                pClipCtxt->pVideoStream->
540                m_basicProperties.m_decoderSpecificInfoSize,
541                &dummy, &videoSizeFromDSI);
542
543            pClipCtxt->pVideoStream->m_videoWidth = videoSizeFromDSI.m_uiWidth;
544            pClipCtxt->pVideoStream->m_videoHeight =
545                videoSizeFromDSI.m_uiHeight;
546        }
547        else
548        {
549
550#endif
551
552            M4OSA_TRACE3_0(
553                "M4VSS3GPP_intClipOpen: Mp4/H263/H264 stream; set current vid dec");
554            err = M4VSS3GPP_setCurrentVideoDecoder(&pClipCtxt->ShellAPI,
555                pClipCtxt->pVideoStream->m_basicProperties.m_streamType);
556            M4ERR_CHECK_RETURN(err);
557
558#ifdef M4VSS_ENABLE_EXTERNAL_DECODERS
559
560            decoderUserData =
561                pClipCtxt->ShellAPI.m_pCurrentVideoDecoderUserData;
562
563#else
564
565            decoderUserData = M4OSA_NULL;
566
567#endif
568
569            err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctCreate(
570                &pClipCtxt->pViDecCtxt,
571                &pClipCtxt->pVideoStream->m_basicProperties,
572                pClipCtxt->ShellAPI.m_pReaderDataIt,
573                &pClipCtxt->VideoAU, decoderUserData);
574
575            if( ( ((M4OSA_UInt32)M4ERR_DECODER_H263_PROFILE_NOT_SUPPORTED) == err)
576                || (((M4OSA_UInt32)M4ERR_DECODER_H263_NOT_BASELINE) == err) )
577            {
578                /**
579                * Our decoder is not compatible with H263 profile other than 0.
580                * So it returns this internal error code.
581                * We translate it to our own error code */
582                return M4VSS3GPP_ERR_H263_PROFILE_NOT_SUPPORTED;
583            }
584            else if( M4NO_ERROR != err )
585            {
586                M4OSA_TRACE1_1(
587                    "M4VSS3GPP_intClipOpen: m_pVideoDecoder->m_pFctCreate returns 0x%x",
588                    err);
589                return err;
590            }
591            M4OSA_TRACE3_1(
592                "M4VSS3GPP_intClipOpen: Vid dec started; pViDecCtxt=0x%x",
593                pClipCtxt->pViDecCtxt);
594
595            if( M4DA_StreamTypeVideoMpeg4Avc
596                == pClipCtxt->pVideoStream->m_basicProperties.m_streamType )
597            {
598                FilterOption.m_pFilterFunction =
599                    (M4OSA_Void *) &M4VIFI_ResizeBilinearYUV420toYUV420;
600                FilterOption.m_pFilterUserData = M4OSA_NULL;
601                err = pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctSetOption(
602                    pClipCtxt->pViDecCtxt, M4DECODER_kOptionID_OutputFilter,
603                    (M4OSA_DataOption) &FilterOption);
604
605                if( M4NO_ERROR != err )
606                {
607                    M4OSA_TRACE1_1(
608                        "M4VSS3GPP_intClipOpen: m_pVideoDecoder->m_pFctSetOption returns 0x%x",
609                        err);
610                    return err;
611                }
612                else
613                {
614                    M4OSA_TRACE3_0(
615                        "M4VSS3GPP_intClipOpen: m_pVideoDecoder->m_pFctSetOption\
616                        M4DECODER_kOptionID_OutputFilter OK");
617                }
618            }
619#ifdef M4VSS_ENABLE_EXTERNAL_DECODERS
620
621        }
622
623#endif
624
625    }
626
627    /**
628    * Init Audio decoder */
629    if( M4OSA_NULL != pClipCtxt->pAudioStream )
630    {
631        err = M4VSS3GPP_intClipPrepareAudioDecoder(pClipCtxt);
632        M4ERR_CHECK_RETURN(err);
633        M4OSA_TRACE3_1("M4VSS3GPP_intClipOpen: Audio dec started; context=0x%x",
634            pClipCtxt->pAudioDecCtxt);
635    }
636    else
637    {
638        pClipCtxt->AudioAU.m_streamID = 0;
639        pClipCtxt->AudioAU.m_dataAddress = M4OSA_NULL;
640        pClipCtxt->AudioAU.m_size = 0;
641        pClipCtxt->AudioAU.m_CTS = 0;
642        pClipCtxt->AudioAU.m_DTS = 0;
643        pClipCtxt->AudioAU.m_attribute = 0;
644        pClipCtxt->AudioAU.m_maxsize = 0;
645        pClipCtxt->AudioAU.m_structSize = sizeof(pClipCtxt->AudioAU);
646    }
647
648    /**
649    * Get the duration of the longest stream */
650    if( M4OSA_TRUE == pClipCtxt->pSettings->ClipProperties.bAnalysed )
651    {
652        /* If already calculated set it to previous value */
653        /* Because fast open and full open can return a different value,
654           it can mismatch user settings */
655        /* Video track is more important than audio track (if video track is shorter than
656           audio track, it can led to cut larger than expected) */
657        iDuration = pClipCtxt->pSettings->ClipProperties.uiClipVideoDuration;
658
659        if( iDuration == 0 )
660        {
661            iDuration = pClipCtxt->pSettings->ClipProperties.uiClipDuration;
662        }
663    }
664    else
665    {
666        /* Else compute it from streams */
667        iDuration = 0;
668
669        if( M4OSA_NULL != pClipCtxt->pVideoStream )
670        {
671            iDuration = (M4OSA_Int32)(
672                pClipCtxt->pVideoStream->m_basicProperties.m_duration);
673        }
674
675        if( ( M4OSA_NULL != pClipCtxt->pAudioStream) && ((M4OSA_Int32)(
676            pClipCtxt->pAudioStream->m_basicProperties.m_duration)
677            > iDuration) && iDuration == 0 )
678        {
679            iDuration = (M4OSA_Int32)(
680                pClipCtxt->pAudioStream->m_basicProperties.m_duration);
681        }
682    }
683
684    /**
685    * If end time is not used, we set it to the video track duration */
686    if( 0 == pClipCtxt->pSettings->uiEndCutTime )
687    {
688        pClipCtxt->pSettings->uiEndCutTime = (M4OSA_UInt32)iDuration;
689    }
690
691    pClipCtxt->iEndTime = (M4OSA_Int32)pClipCtxt->pSettings->uiEndCutTime;
692
693    /**
694    * Return with no error */
695    M4OSA_TRACE3_0("M4VSS3GPP_intClipOpen(): returning M4NO_ERROR");
696    return M4NO_ERROR;
697}
698
699/**
700 ******************************************************************************
701 * M4OSA_Void M4VSS3GPP_intClipDeleteAudioTrack()
702 * @brief    Delete the audio track. Clip will be like if it had no audio track
703 * @note
704 * @param   pClipCtxt            (IN) Internal clip context
705 ******************************************************************************
706 */
707M4OSA_Void M4VSS3GPP_intClipDeleteAudioTrack( M4VSS3GPP_ClipContext *pClipCtxt )
708{
709    /**
710    * But we don't have to free the audio stream. It will be freed by the reader when closing it*/
711    pClipCtxt->pAudioStream = M4OSA_NULL;
712
713    /**
714    * We will return a constant silence AMR AU.
715    * We set it here once, instead of at each read audio step. */
716    pClipCtxt->pAudioFramePtr = (M4OSA_MemAddr8)pClipCtxt->pSilenceFrameData;
717    pClipCtxt->uiAudioFrameSize = pClipCtxt->uiSilenceFrameSize;
718
719    /**
720    * Free the decoded audio buffer (it needs to be re-allocated to store silence
721      frame eventually)*/
722    if( M4OSA_NULL != pClipCtxt->AudioDecBufferOut.m_dataAddress )
723    {
724        free(pClipCtxt->AudioDecBufferOut.m_dataAddress);
725        pClipCtxt->AudioDecBufferOut.m_dataAddress = M4OSA_NULL;
726    }
727
728    return;
729}
730
731/**
732 ******************************************************************************
733 * M4OSA_ERR M4VSS3GPP_intClipDecodeVideoUpToCurrentTime()
734 * @brief    Jump to the previous RAP and decode up to the current video time
735 * @param   pClipCtxt    (IN) Internal clip context
736 * @param   iCts        (IN) Target CTS
737 ******************************************************************************
738 */
739M4OSA_ERR M4VSS3GPP_intClipDecodeVideoUpToCts( M4VSS3GPP_ClipContext *pClipCtxt,
740                                              M4OSA_Int32 iCts )
741{
742    M4OSA_Int32 iRapCts, iClipCts;
743    M4_MediaTime dDecodeTime;
744    M4OSA_Bool bClipJump = M4OSA_FALSE;
745    M4OSA_ERR err;
746
747    /**
748    * Compute the time in the clip base */
749    iClipCts = iCts - pClipCtxt->iVoffset;
750
751    /**
752    * If we were reading the clip, we must jump to the previous RAP
753    * to decode from that point. */
754    if( M4VSS3GPP_kClipStatus_READ == pClipCtxt->Vstatus )
755    {
756        /**
757        * Jump to the previous RAP in the clip (first get the time, then jump) */
758        iRapCts = iClipCts;
759
760        err = pClipCtxt->ShellAPI.m_pReader->m_pFctGetPrevRapTime(
761            pClipCtxt->pReaderContext,
762            (M4_StreamHandler *)pClipCtxt->pVideoStream, &iRapCts);
763
764        if( M4WAR_READER_INFORMATION_NOT_PRESENT == err )
765        {
766            /* No RAP table, jump backward and predecode */
767            iRapCts = iClipCts - M4VSS3GPP_NO_STSS_JUMP_POINT;
768
769            if( iRapCts < 0 )
770                iRapCts = 0;
771        }
772        else if( M4NO_ERROR != err )
773        {
774            M4OSA_TRACE1_1(
775                "M4VSS3GPP_intClipDecodeVideoUpToCts: m_pFctGetPrevRapTime returns 0x%x!",
776                err);
777            return err;
778        }
779
780        err =
781            pClipCtxt->ShellAPI.m_pReader->m_pFctJump(pClipCtxt->pReaderContext,
782            (M4_StreamHandler *)pClipCtxt->pVideoStream, &iRapCts);
783
784        if( M4NO_ERROR != err )
785        {
786            M4OSA_TRACE1_1(
787                "M4VSS3GPP_intClipDecodeVideoUpToCts: m_pFctJump returns 0x%x!",
788                err);
789            return err;
790        }
791
792        /**
793        * The decoder must be told that we jumped */
794        bClipJump = M4OSA_TRUE;
795        pClipCtxt->iVideoDecCts = iRapCts;
796
797        /**
798        * Remember the clip reading state */
799        pClipCtxt->Vstatus = M4VSS3GPP_kClipStatus_DECODE_UP_TO;
800    }
801
802    /**
803    * If we are in decodeUpTo() process, check if we need to do
804    one more step or if decoding is finished */
805    if( M4VSS3GPP_kClipStatus_DECODE_UP_TO == pClipCtxt->Vstatus )
806    {
807        /* Do a step of 500 ms decoding */
808        pClipCtxt->iVideoDecCts += 500;
809
810        if( pClipCtxt->iVideoDecCts > iClipCts )
811        {
812            /* Target time reached, we switch back to DECODE mode */
813            pClipCtxt->iVideoDecCts = iClipCts;
814            pClipCtxt->Vstatus = M4VSS3GPP_kClipStatus_DECODE;
815        }
816
817        M4OSA_TRACE2_1("c ,,,, decode up to : %ld", pClipCtxt->iVideoDecCts);
818    }
819    else
820    {
821        /* Just decode at current clip cts */
822        pClipCtxt->iVideoDecCts = iClipCts;
823
824        M4OSA_TRACE2_1("d ,,,, decode up to : %ld", pClipCtxt->iVideoDecCts);
825    }
826
827    /**
828    * Decode up to the target */
829    M4OSA_TRACE3_2(
830        "M4VSS3GPP_intClipDecodeVideoUpToCts: Decoding upTo CTS %.3f, pClipCtxt=0x%x",
831        dDecodeTime, pClipCtxt);
832
833    dDecodeTime = (M4OSA_Double)pClipCtxt->iVideoDecCts;
834    pClipCtxt->isRenderDup = M4OSA_FALSE;
835    err =
836        pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctDecode(pClipCtxt->pViDecCtxt,
837        &dDecodeTime, bClipJump);
838
839    if( ( M4NO_ERROR != err) && (M4WAR_NO_MORE_AU != err)
840        && (err != M4WAR_VIDEORENDERER_NO_NEW_FRAME) )
841    {
842        M4OSA_TRACE1_1(
843            "M4VSS3GPP_intClipDecodeVideoUpToCts: m_pFctDecode returns 0x%x!",
844            err);
845        return err;
846    }
847
848    if( err == M4WAR_VIDEORENDERER_NO_NEW_FRAME )
849    {
850        pClipCtxt->isRenderDup = M4OSA_TRUE;
851    }
852
853    /**
854    * Return */
855    M4OSA_TRACE3_0("M4VSS3GPP_intClipDecodeVideoUpToCts: returning M4NO_ERROR");
856    return M4NO_ERROR;
857}
858
859/**
860 ******************************************************************************
861 * M4OSA_ERR M4VSS3GPP_intClipReadNextAudioFrame()
862 * @brief    Read one AU frame in the clip
863 * @note
864 * @param   pClipCtxt            (IN) Internal clip context
865 * @return    M4NO_ERROR:            No error
866 ******************************************************************************
867 */
868M4OSA_ERR M4VSS3GPP_intClipReadNextAudioFrame(
869    M4VSS3GPP_ClipContext *pClipCtxt )
870{
871    M4OSA_ERR err;
872
873    /* ------------------------------ */
874    /* ---------- NO AUDIO ---------- */
875    /* ------------------------------ */
876
877    if( M4OSA_NULL == pClipCtxt->pAudioStream )
878    {
879        /* If there is no audio track, we return silence AUs */
880        pClipCtxt->pAudioFramePtr =
881            (M4OSA_MemAddr8)pClipCtxt->pSilenceFrameData;
882        pClipCtxt->uiAudioFrameSize = pClipCtxt->uiSilenceFrameSize;
883        pClipCtxt->iAudioFrameCts += pClipCtxt->iSilenceFrameDuration;
884
885        M4OSA_TRACE2_0("b #### blank track");
886    }
887
888    /* ---------------------------------- */
889    /* ---------- AMR-NB, EVRC ---------- */
890    /* ---------------------------------- */
891
892    else if( ( M4VIDEOEDITING_kAMR_NB
893        == pClipCtxt->pSettings->ClipProperties.AudioStreamType)
894        || (M4VIDEOEDITING_kEVRC
895        == pClipCtxt->pSettings->ClipProperties.AudioStreamType) )
896    {
897        if( M4OSA_FALSE == pClipCtxt->bAudioFrameAvailable )
898        {
899            /**
900            * No AU available, so we must must read one from the original track reader */
901            err = pClipCtxt->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu(
902                pClipCtxt->pReaderContext,
903                (M4_StreamHandler *)pClipCtxt->pAudioStream,
904                &pClipCtxt->AudioAU);
905
906            if( M4NO_ERROR == err )
907            {
908                /**
909                * Set the current AMR frame position at the beginning of the read AU */
910                pClipCtxt->pAudioFramePtr = pClipCtxt->AudioAU.m_dataAddress;
911
912                /**
913                * Set the AMR frame CTS */
914                pClipCtxt->iAudioFrameCts =
915                    (M4OSA_Int32)(pClipCtxt->AudioAU.m_CTS
916                    * pClipCtxt->scale_audio + 0.5);
917            }
918            else if( ( M4WAR_NO_MORE_AU == err) && (M4VIDEOEDITING_kAMR_NB
919                == pClipCtxt->pSettings->ClipProperties.AudioStreamType) )
920            {
921                /**
922                * If there is less audio than the stream duration indicated,
923                * we return silence at the end of the stream. */
924                pClipCtxt->pAudioFramePtr =
925                    (M4OSA_MemAddr8)pClipCtxt->pSilenceFrameData;
926                pClipCtxt->uiAudioFrameSize = pClipCtxt->uiSilenceFrameSize;
927                pClipCtxt->iAudioFrameCts += pClipCtxt->iSilenceFrameDuration;
928
929                M4OSA_TRACE2_0("a #### silence AU");
930
931                /**
932                * Return with M4WAR_NO_MORE_AU */
933                M4OSA_TRACE3_0(
934                    "M4VSS3GPP_intClipReadNextAudioFrame()-AMR: \
935                    returning M4WAR_NO_MORE_AU (silence)");
936                return M4WAR_NO_MORE_AU;
937            }
938            else /**< fatal error (or no silence in EVRC) */
939            {
940                M4OSA_TRACE3_1(
941                    "M4VSS3GPP_intClipReadNextAudioFrame()-AMR: m_pFctGetNextAu() returns 0x%x",
942                    err);
943                return err;
944            }
945        }
946        else /* bAudioFrameAvailable */
947        {
948            /**
949            * Go to the next AMR frame in the AU */
950            pClipCtxt->pAudioFramePtr += pClipCtxt->uiAudioFrameSize;
951
952            /**
953            * Increment CTS: one AMR frame is 20 ms long */
954            pClipCtxt->iAudioFrameCts += pClipCtxt->iSilenceFrameDuration;
955        }
956
957        /**
958        * Get the size of the pointed AMR frame */
959        switch( pClipCtxt->pSettings->ClipProperties.AudioStreamType )
960        {
961            case M4VIDEOEDITING_kAMR_NB:
962                pClipCtxt->uiAudioFrameSize =
963                    (M4OSA_UInt16)M4VSS3GPP_intGetFrameSize_AMRNB(
964                    pClipCtxt->pAudioFramePtr);
965                break;
966
967            case M4VIDEOEDITING_kEVRC:
968                pClipCtxt->uiAudioFrameSize =
969                    (M4OSA_UInt16)M4VSS3GPP_intGetFrameSize_EVRC(
970                    pClipCtxt->pAudioFramePtr);
971                break;
972            default:
973                break;
974        }
975
976        if( 0 == pClipCtxt->uiAudioFrameSize )
977        {
978            M4OSA_TRACE3_0(
979                "M4VSS3GPP_intClipReadNextAudioFrame()-AMR: AU frame size == 0,\
980                returning M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AMR_AU");
981            return M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU;
982        }
983        else if( pClipCtxt->uiAudioFrameSize > pClipCtxt->AudioAU.m_size )
984        {
985            M4OSA_TRACE3_0(
986                "M4VSS3GPP_intClipReadNextAudioFrame()-AMR: AU frame size greater than AU size!,\
987                returning M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AMR_AU");
988            return M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU;
989        }
990
991        /**
992        * Check if the end of the current AU has been reached or not */
993        if( ( pClipCtxt->pAudioFramePtr + pClipCtxt->uiAudioFrameSize)
994            < (pClipCtxt->AudioAU.m_dataAddress + pClipCtxt->AudioAU.m_size) )
995        {
996            pClipCtxt->bAudioFrameAvailable = M4OSA_TRUE;
997        }
998        else
999        {
1000            pClipCtxt->bAudioFrameAvailable =
1001                M4OSA_FALSE; /**< will be used for next call */
1002        }
1003    }
1004
1005    /* ------------------------- */
1006    /* ---------- AAC ---------- */
1007    /* ------------------------- */
1008
1009    else if( ( M4VIDEOEDITING_kAAC
1010        == pClipCtxt->pSettings->ClipProperties.AudioStreamType)
1011        || (M4VIDEOEDITING_kAACplus
1012        == pClipCtxt->pSettings->ClipProperties.AudioStreamType)
1013        || (M4VIDEOEDITING_keAACplus
1014        == pClipCtxt->pSettings->ClipProperties.AudioStreamType) )
1015    {
1016        err = pClipCtxt->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu(
1017            pClipCtxt->pReaderContext,
1018            (M4_StreamHandler *)pClipCtxt->pAudioStream,
1019            &pClipCtxt->AudioAU);
1020
1021        if( M4NO_ERROR == err )
1022        {
1023            pClipCtxt->pAudioFramePtr = pClipCtxt->AudioAU.m_dataAddress;
1024            pClipCtxt->uiAudioFrameSize =
1025                (M4OSA_UInt16)pClipCtxt->AudioAU.m_size;
1026            pClipCtxt->iAudioFrameCts =
1027                (M4OSA_Int32)(pClipCtxt->AudioAU.m_CTS * pClipCtxt->scale_audio
1028                + 0.5);
1029
1030            /* Patch because m_CTS is unfortunately rounded in 3gp reader shell */
1031            /* (cts is not an integer with frequency 24 kHz for example) */
1032            pClipCtxt->iAudioFrameCts = ( ( pClipCtxt->iAudioFrameCts
1033                + pClipCtxt->iSilenceFrameDuration / 2)
1034                / pClipCtxt->iSilenceFrameDuration)
1035                * pClipCtxt->iSilenceFrameDuration;
1036        }
1037        else if( M4WAR_NO_MORE_AU == err )
1038        {
1039            /**
1040            * If there is less audio than the stream duration indicated,
1041            * we return silence at the end of the stream. */
1042            pClipCtxt->pAudioFramePtr =
1043                (M4OSA_MemAddr8)pClipCtxt->pSilenceFrameData;
1044            pClipCtxt->uiAudioFrameSize = pClipCtxt->uiSilenceFrameSize;
1045            pClipCtxt->iAudioFrameCts += pClipCtxt->iSilenceFrameDuration;
1046
1047            M4OSA_TRACE2_0("a #### silence AU");
1048
1049            /**
1050            * Return with M4WAR_NO_MORE_AU */
1051            M4OSA_TRACE3_0(
1052                "M4VSS3GPP_intClipReadNextAudioFrame()-AAC:\
1053                returning M4WAR_NO_MORE_AU (silence)");
1054            return M4WAR_NO_MORE_AU;
1055        }
1056        else /**< fatal error */
1057        {
1058            M4OSA_TRACE3_1(
1059                "M4VSS3GPP_intClipReadNextAudioFrame()-AAC: m_pFctGetNextAu() returns 0x%x",
1060                err);
1061            return err;
1062        }
1063    }
1064
1065    /* --------------------------------- */
1066    /* ---------- MP3, others ---------- */
1067    /* --------------------------------- */
1068
1069    else
1070    {
1071        err = pClipCtxt->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu(
1072            pClipCtxt->pReaderContext,
1073            (M4_StreamHandler *)pClipCtxt->pAudioStream,
1074            &pClipCtxt->AudioAU);
1075
1076        if( M4NO_ERROR != err )
1077        {
1078            M4OSA_TRACE3_1(
1079                "M4VSS3GPP_intClipReadNextAudioFrame()-MP3: m_pFctGetNextAu() returns 0x%x",
1080                err);
1081            return err;
1082        }
1083
1084        pClipCtxt->pAudioFramePtr = pClipCtxt->AudioAU.m_dataAddress;
1085        pClipCtxt->uiAudioFrameSize = (M4OSA_UInt16)pClipCtxt->AudioAU.m_size;
1086        pClipCtxt->iAudioFrameCts =
1087            (M4OSA_Int32)(pClipCtxt->AudioAU.m_CTS * pClipCtxt->scale_audio
1088            + 0.5);
1089    }
1090
1091    /**
1092    * Return with no error */
1093    M4OSA_TRACE3_0(
1094        "M4VSS3GPP_intClipReadNextAudioFrame(): returning M4NO_ERROR");
1095
1096    return M4NO_ERROR;
1097}
1098
1099/**
1100 ******************************************************************************
1101 * M4OSA_ERR M4VSS3GPP_intClipPrepareAudioDecoder()
1102 * @brief    Creates and initialize the audio decoder for the clip.
1103 * @note
1104 * @param   pClipCtxt        (IN) internal clip context
1105 * @return    M4NO_ERROR:            No error
1106 ******************************************************************************
1107 */
1108static M4OSA_ERR M4VSS3GPP_intClipPrepareAudioDecoder(
1109    M4VSS3GPP_ClipContext *pClipCtxt )
1110{
1111    M4OSA_ERR err = M4NO_ERROR;
1112    M4_StreamType audiotype;
1113#ifdef M4VSS_SUPPORT_OMX_CODECS
1114
1115    M4_AACType iAacType = 0;
1116
1117#endif
1118
1119    /**
1120    * Set the proper audio decoder */
1121
1122    audiotype = pClipCtxt->pAudioStream->m_basicProperties.m_streamType;
1123
1124    //EVRC
1125    if( M4DA_StreamTypeAudioEvrc
1126        != audiotype ) /* decoder not supported yet, but allow to do null encoding */
1127
1128        err = M4VSS3GPP_setCurrentAudioDecoder(&pClipCtxt->ShellAPI, audiotype);
1129    M4ERR_CHECK_RETURN(err);
1130
1131    /**
1132    * Creates the audio decoder */
1133    if( M4OSA_NULL == pClipCtxt->ShellAPI.m_pAudioDecoder )
1134    {
1135        M4OSA_TRACE1_0(
1136            "M4VSS3GPP_intClipPrepareAudioDecoder(): Fails to initiate the audio decoder.");
1137        return M4VSS3GPP_ERR_AUDIO_DECODER_INIT_FAILED;
1138    }
1139
1140    if( M4OSA_NULL == pClipCtxt->pAudioDecCtxt )
1141    {
1142#ifdef M4VSS_SUPPORT_OMX_CODECS
1143
1144        if( M4OSA_TRUE == pClipCtxt->ShellAPI.bAllowFreeingOMXCodecInterface )
1145        {
1146            if( M4DA_StreamTypeAudioAac == audiotype ) {
1147                err = M4VSS3GPP_intCheckAndGetCodecAacProperties(
1148                       pClipCtxt);
1149            } else if (M4DA_StreamTypeAudioPcm != audiotype) {
1150                err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec(
1151                &pClipCtxt->pAudioDecCtxt, pClipCtxt->pAudioStream,
1152                M4OSA_NULL);
1153            } else {
1154                err = M4NO_ERROR;
1155            }
1156            if( M4NO_ERROR != err )
1157            {
1158                M4OSA_TRACE1_1(
1159                    "M4VSS3GPP_intClipPrepareAudioDecoder: m_pAudioDecoder->m_pFctCreateAudioDec\
1160                    returns 0x%x", err);
1161                return err;
1162            }
1163        }
1164        else
1165        {
1166            M4OSA_TRACE3_1(
1167                "M4VSS3GPP_intClipPrepareAudioDecoder:\
1168                Creating external audio decoder of type 0x%x", audiotype);
1169            /* External OMX codecs are used*/
1170            if( M4DA_StreamTypeAudioAac == audiotype )
1171            {
1172                err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec(
1173                    &pClipCtxt->pAudioDecCtxt, pClipCtxt->pAudioStream,
1174                    pClipCtxt->ShellAPI.pCurrentAudioDecoderUserData);
1175
1176                if( M4NO_ERROR == err )
1177                {
1178                    /* AAC properties*/
1179                    /*get from Reader; temporary, till Audio decoder shell API
1180                      available to get the AAC properties*/
1181                    pClipCtxt->AacProperties.aNumChan =
1182                        pClipCtxt->pAudioStream->m_nbChannels;
1183                    pClipCtxt->AacProperties.aSampFreq =
1184                        pClipCtxt->pAudioStream->m_samplingFrequency;
1185
1186                    err = pClipCtxt->ShellAPI.m_pAudioDecoder->
1187                        m_pFctGetOptionAudioDec(pClipCtxt->pAudioDecCtxt,
1188                        M4AD_kOptionID_StreamType,
1189                        (M4OSA_DataOption) &iAacType);
1190
1191                    if( M4NO_ERROR != err )
1192                    {
1193                        M4OSA_TRACE1_1(
1194                            "M4VSS3GPP_intClipPrepareAudioDecoder:\
1195                            m_pAudioDecoder->m_pFctGetOptionAudioDec returns err 0x%x", err);
1196                        iAacType = M4_kAAC; //set to default
1197                        err = M4NO_ERROR;
1198                    }
1199                    else {
1200                        M4OSA_TRACE3_1(
1201                        "M4VSS3GPP_intClipPrepareAudioDecoder: \
1202                        m_pAudioDecoder->m_pFctGetOptionAudioDec returns streamType %d",
1203                        iAacType);
1204                       }
1205                    switch( iAacType )
1206                    {
1207                        case M4_kAAC:
1208                            pClipCtxt->AacProperties.aSBRPresent = 0;
1209                            pClipCtxt->AacProperties.aPSPresent = 0;
1210                            break;
1211
1212                        case M4_kAACplus:
1213                            pClipCtxt->AacProperties.aSBRPresent = 1;
1214                            pClipCtxt->AacProperties.aPSPresent = 0;
1215                            pClipCtxt->AacProperties.aExtensionSampFreq =
1216                                pClipCtxt->pAudioStream->m_samplingFrequency;
1217                            break;
1218
1219                        case M4_keAACplus:
1220                            pClipCtxt->AacProperties.aSBRPresent = 1;
1221                            pClipCtxt->AacProperties.aPSPresent = 1;
1222                            pClipCtxt->AacProperties.aExtensionSampFreq =
1223                                pClipCtxt->pAudioStream->m_samplingFrequency;
1224                            break;
1225                        default:
1226                            break;
1227                    }
1228                    M4OSA_TRACE3_2(
1229                        "M4VSS3GPP_intClipPrepareAudioDecoder: AAC NBChans=%d, SamplFreq=%d",
1230                        pClipCtxt->AacProperties.aNumChan,
1231                        pClipCtxt->AacProperties.aSampFreq);
1232                }
1233            }
1234            else
1235                err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec(
1236                &pClipCtxt->pAudioDecCtxt, pClipCtxt->pAudioStream,
1237                pClipCtxt->ShellAPI.pCurrentAudioDecoderUserData);
1238
1239            if( M4NO_ERROR != err )
1240            {
1241                M4OSA_TRACE1_1(
1242                    "M4VSS3GPP_intClipPrepareAudioDecoder:\
1243                    m_pAudioDecoder->m_pFctCreateAudioDec returns 0x%x",
1244                    err);
1245                return err;
1246            }
1247        }
1248
1249#else
1250        /* Trick, I use pUserData to retrieve aac properties,
1251           waiting for some better implementation... */
1252
1253        if( M4DA_StreamTypeAudioAac == audiotype )
1254            err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec(
1255            &pClipCtxt->pAudioDecCtxt,
1256            pClipCtxt->pAudioStream, &(pClipCtxt->AacProperties));
1257        else
1258            err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec(
1259            &pClipCtxt->pAudioDecCtxt, pClipCtxt->pAudioStream,
1260            M4OSA_NULL /* to be changed with HW interfaces */);
1261
1262        if( M4NO_ERROR != err )
1263        {
1264            M4OSA_TRACE1_1(
1265                "M4VSS3GPP_intClipPrepareAudioDecoder:\
1266                m_pAudioDecoder->m_pFctCreateAudioDec returns 0x%x",
1267                err);
1268            return err;
1269        }
1270
1271#endif
1272
1273    }
1274
1275    if( M4DA_StreamTypeAudioAmrNarrowBand == audiotype ) {
1276        /* AMR DECODER CONFIGURATION */
1277
1278        /* nothing specific to do */
1279    }
1280    else if( M4DA_StreamTypeAudioEvrc == audiotype ) {
1281        /* EVRC DECODER CONFIGURATION */
1282
1283        /* nothing specific to do */
1284    }
1285    else if( M4DA_StreamTypeAudioMp3 == audiotype ) {
1286        /* MP3 DECODER CONFIGURATION */
1287
1288        /* nothing specific to do */
1289    }
1290    else if( M4DA_StreamTypeAudioAac == audiotype )
1291    {
1292        /* AAC DECODER CONFIGURATION */
1293
1294        /* Decode high quality aac but disable PS and SBR */
1295        /* Because we have to mix different kind of AAC so we must take the lowest capability */
1296        /* In MCS it was not needed because there is only one stream */
1297        M4_AacDecoderConfig AacDecParam;
1298
1299        AacDecParam.m_AACDecoderProfile = AAC_kAAC;
1300        AacDecParam.m_DownSamplingMode = AAC_kDS_OFF;
1301
1302        if( M4ENCODER_kMono == pClipCtxt->pAudioStream->m_nbChannels )
1303        {
1304            AacDecParam.m_OutputMode = AAC_kMono;
1305        }
1306        else
1307        {
1308            AacDecParam.m_OutputMode = AAC_kStereo;
1309        }
1310
1311        err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec(
1312            pClipCtxt->pAudioDecCtxt,
1313            M4AD_kOptionID_UserParam, (M4OSA_DataOption) &AacDecParam);
1314    }
1315
1316    if( M4OSA_NULL != pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec ) {
1317        pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec(
1318         pClipCtxt->pAudioDecCtxt, M4AD_kOptionID_3gpReaderInterface,
1319         (M4OSA_DataOption) pClipCtxt->ShellAPI.m_pReaderDataIt);
1320
1321        pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec(
1322         pClipCtxt->pAudioDecCtxt, M4AD_kOptionID_AudioAU,
1323         (M4OSA_DataOption) &pClipCtxt->AudioAU);
1324    }
1325
1326    if( M4OSA_NULL != pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStartAudioDec )
1327    {
1328        /* Not implemented in all decoders */
1329        err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStartAudioDec(
1330            pClipCtxt->pAudioDecCtxt);
1331
1332        if( M4NO_ERROR != err )
1333        {
1334            M4OSA_TRACE1_1(
1335                "M4VSS3GPP_intClipPrepareAudioDecoder:\
1336                m_pAudioDecoder->m_pFctStartAudioDec returns 0x%x",
1337                err);
1338            return err;
1339        }
1340    }
1341
1342    /**
1343    * Allocate output buffer for the audio decoder */
1344    pClipCtxt->AudioDecBufferOut.m_bufferSize =
1345        pClipCtxt->pAudioStream->m_byteFrameLength
1346        * pClipCtxt->pAudioStream->m_byteSampleSize
1347        * pClipCtxt->pAudioStream->m_nbChannels;
1348    pClipCtxt->AudioDecBufferOut.m_dataAddress =
1349        (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(pClipCtxt->AudioDecBufferOut.m_bufferSize
1350        * sizeof(M4OSA_Int16),
1351        M4VSS3GPP, (M4OSA_Char *)"AudioDecBufferOut.m_bufferSize");
1352
1353    if( M4OSA_NULL == pClipCtxt->AudioDecBufferOut.m_dataAddress )
1354    {
1355        M4OSA_TRACE1_0(
1356            "M4VSS3GPP_intClipPrepareAudioDecoder():\
1357            unable to allocate AudioDecBufferOut.m_dataAddress, returning M4ERR_ALLOC");
1358        return M4ERR_ALLOC;
1359    }
1360
1361    return M4NO_ERROR;
1362}
1363
1364/**
1365 ******************************************************************************
1366 * M4OSA_ERR M4VSS3GPP_intClipDecodeCurrentAudioFrame()
1367 * @brief    Decode the current AUDIO frame.
1368 * @note
1369 * @param   pClipCtxt        (IN) internal clip context
1370 * @return    M4NO_ERROR:            No error
1371 ******************************************************************************
1372 */
1373M4OSA_ERR M4VSS3GPP_intClipDecodeCurrentAudioFrame(
1374    M4VSS3GPP_ClipContext *pClipCtxt )
1375{
1376    M4OSA_ERR err;
1377
1378    /**
1379    * Silence mode */
1380    if( pClipCtxt->pSilenceFrameData
1381        == (M4OSA_UInt8 *)pClipCtxt->pAudioFramePtr )
1382    {
1383        if( pClipCtxt->AudioDecBufferOut.m_dataAddress == M4OSA_NULL )
1384        {
1385            /**
1386            * Allocate output buffer for the audio decoder */
1387            pClipCtxt->AudioDecBufferOut.m_bufferSize =
1388                pClipCtxt->uiSilencePcmSize;
1389            pClipCtxt->AudioDecBufferOut.m_dataAddress =
1390                (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(
1391                pClipCtxt->AudioDecBufferOut.m_bufferSize
1392                * sizeof(M4OSA_Int16),
1393                M4VSS3GPP,(M4OSA_Char *) "AudioDecBufferOut.m_bufferSize");
1394
1395            if( M4OSA_NULL == pClipCtxt->AudioDecBufferOut.m_dataAddress )
1396            {
1397                M4OSA_TRACE1_0(
1398                    "M4VSS3GPP_intClipDecodeCurrentAudioFrame():\
1399                    unable to allocate AudioDecBufferOut.m_dataAddress, returning M4ERR_ALLOC");
1400                return M4ERR_ALLOC;
1401            }
1402        }
1403
1404        /* Fill it with 0 (= pcm silence) */
1405        memset(pClipCtxt->AudioDecBufferOut.m_dataAddress,0,
1406             pClipCtxt->AudioDecBufferOut.m_bufferSize * sizeof(M4OSA_Int16));
1407    }
1408    else if (pClipCtxt->pSettings->FileType == M4VIDEOEDITING_kFileType_PCM)
1409    {
1410        pClipCtxt->AudioDecBufferIn.m_dataAddress = (M4OSA_MemAddr8) pClipCtxt->pAudioFramePtr;
1411        pClipCtxt->AudioDecBufferIn.m_bufferSize  = pClipCtxt->uiAudioFrameSize;
1412
1413        memcpy((void *)pClipCtxt->AudioDecBufferOut.m_dataAddress,
1414            (void *)pClipCtxt->AudioDecBufferIn.m_dataAddress, pClipCtxt->AudioDecBufferIn.m_bufferSize);
1415        pClipCtxt->AudioDecBufferOut.m_bufferSize = pClipCtxt->AudioDecBufferIn.m_bufferSize;
1416        /**
1417        * Return with no error */
1418
1419        M4OSA_TRACE3_0("M4VSS3GPP_intClipDecodeCurrentAudioFrame(): returning M4NO_ERROR");
1420        return M4NO_ERROR;
1421    }
1422    /**
1423    * Standard decoding mode */
1424    else
1425    {
1426        /**
1427        * Decode current AMR frame */
1428        if ( pClipCtxt->pAudioFramePtr != M4OSA_NULL ) {
1429            pClipCtxt->AudioDecBufferIn.m_dataAddress =
1430             (M4OSA_MemAddr8)pClipCtxt->pAudioFramePtr;
1431            pClipCtxt->AudioDecBufferIn.m_bufferSize =
1432             pClipCtxt->uiAudioFrameSize;
1433            pClipCtxt->AudioDecBufferIn.m_timeStampUs =
1434             (int64_t) (pClipCtxt->iAudioFrameCts * 1000LL);
1435
1436            err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStepAudioDec(
1437             pClipCtxt->pAudioDecCtxt,
1438             &pClipCtxt->AudioDecBufferIn, &pClipCtxt->AudioDecBufferOut,
1439             M4OSA_FALSE);
1440        } else {
1441            // Pass Null input buffer
1442            // Reader invoked from Audio decoder source
1443            err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStepAudioDec(
1444             pClipCtxt->pAudioDecCtxt,
1445             M4OSA_NULL, &pClipCtxt->AudioDecBufferOut,
1446             M4OSA_FALSE);
1447        }
1448
1449        if( M4NO_ERROR != err )
1450        {
1451            M4OSA_TRACE1_1(
1452                "M4VSS3GPP_intClipDecodeCurrentAudioFrame():\
1453                m_pAudioDecoder->m_pFctStepAudio returns 0x%x",
1454                err);
1455            return err;
1456        }
1457    }
1458
1459    /**
1460    * Return with no error */
1461    M4OSA_TRACE3_0(
1462        "M4VSS3GPP_intClipDecodeCurrentAudioFrame(): returning M4NO_ERROR");
1463    return M4NO_ERROR;
1464}
1465
1466/**
1467 ******************************************************************************
1468 * M4OSA_ERR M4VSS3GPP_intClipJumpAudioAt()
1469 * @brief    Jump in the audio track of the clip.
1470 * @note
1471 * @param   pClipCtxt            (IN) internal clip context
1472 * @param   pJumpCts            (IN/OUT) in:target CTS, out: reached CTS
1473 * @return    M4NO_ERROR:            No error
1474 ******************************************************************************
1475 */
1476M4OSA_ERR M4VSS3GPP_intClipJumpAudioAt( M4VSS3GPP_ClipContext *pClipCtxt,
1477                                       M4OSA_Int32 *pJumpCts )
1478{
1479    M4OSA_ERR err;
1480    M4OSA_Int32 iTargetCts;
1481    M4OSA_Int32 iJumpCtsMs;
1482
1483    /**
1484    *    Check input parameters */
1485    M4OSA_DEBUG_IF2((M4OSA_NULL == pClipCtxt), M4ERR_PARAMETER,
1486        "M4VSS3GPP_intClipJumpAudioAt: pClipCtxt is M4OSA_NULL");
1487    M4OSA_DEBUG_IF2((M4OSA_NULL == pJumpCts), M4ERR_PARAMETER,
1488        "M4VSS3GPP_intClipJumpAudioAt: pJumpCts is M4OSA_NULL");
1489
1490    iTargetCts = *pJumpCts;
1491
1492    /**
1493    * If there is no audio stream, we simulate a jump at the target jump CTS */
1494    if( M4OSA_NULL == pClipCtxt->pAudioStream )
1495    {
1496        /**
1497        * the target CTS will be reached at next ReadFrame call (thus the -20) */
1498        *pJumpCts = iTargetCts - pClipCtxt->iSilenceFrameDuration;
1499
1500        /* Patch because m_CTS is unfortunately rounded in 3gp reader shell */
1501        /* (cts is not an integer with frequency 24 kHz for example) */
1502        *pJumpCts = ( ( *pJumpCts + pClipCtxt->iSilenceFrameDuration / 2)
1503            / pClipCtxt->iSilenceFrameDuration)
1504            * pClipCtxt->iSilenceFrameDuration;
1505        pClipCtxt->iAudioFrameCts =
1506            *
1507            pJumpCts; /* simulate a read at jump position for later silence AUs */
1508    }
1509    else
1510    {
1511        M4OSA_Int32 current_time = 0;
1512        M4OSA_Int32 loop_counter = 0;
1513
1514        if( (M4DA_StreamTypeAudioMp3
1515            == pClipCtxt->pAudioStream->m_basicProperties.m_streamType) )
1516        {
1517            while( ( loop_counter < M4VSS3GPP_MP3_JUMPED_AU_NUMBER_MAX)
1518                && (current_time < iTargetCts) )
1519            {
1520                err = pClipCtxt->ShellAPI.m_pReaderDataIt->m_pFctGetNextAu(
1521                    pClipCtxt->pReaderContext,
1522                    (M4_StreamHandler *)pClipCtxt->pAudioStream,
1523                    &pClipCtxt->AudioAU);
1524
1525                if( M4NO_ERROR != err )
1526                {
1527                    M4OSA_TRACE3_1(
1528                        "M4VSS3GPP_intClipJumpAudioAt: m_pFctGetNextAu() returns 0x%x",
1529                        err);
1530                    return err;
1531                }
1532
1533                current_time = (M4OSA_Int32)pClipCtxt->AudioAU.m_CTS;
1534                loop_counter++;
1535            }
1536
1537            /**
1538            * The current AU is stored */
1539            pClipCtxt->pAudioFramePtr = pClipCtxt->AudioAU.m_dataAddress;
1540            pClipCtxt->uiAudioFrameSize =
1541                (M4OSA_UInt16)pClipCtxt->AudioAU.m_size;
1542            pClipCtxt->iAudioFrameCts =
1543                (M4OSA_Int32)(pClipCtxt->AudioAU.m_CTS * pClipCtxt->scale_audio
1544                + 0.5);
1545
1546            *pJumpCts = pClipCtxt->iAudioFrameCts;
1547        }
1548        else
1549        {
1550            /**
1551            * Jump in the audio stream */
1552            iJumpCtsMs =
1553                (M4OSA_Int32)(*pJumpCts / pClipCtxt->scale_audio + 0.5);
1554
1555            err = pClipCtxt->ShellAPI.m_pReader->m_pFctJump(
1556                pClipCtxt->pReaderContext,
1557                (M4_StreamHandler *)pClipCtxt->pAudioStream,
1558                &iJumpCtsMs);
1559
1560            if( M4NO_ERROR != err )
1561            {
1562                M4OSA_TRACE1_1(
1563                    "M4VSS3GPP_intClipJumpAudioAt(): m_pFctJump() returns 0x%x",
1564                    err);
1565                return err;
1566            }
1567
1568            *pJumpCts =
1569                (M4OSA_Int32)(iJumpCtsMs * pClipCtxt->scale_audio + 0.5);
1570
1571            /* Patch because m_CTS is unfortunately rounded in 3gp reader shell */
1572            /* (cts is not an integer with frequency 24 kHz for example) */
1573            *pJumpCts = ( ( *pJumpCts + pClipCtxt->iSilenceFrameDuration / 2)
1574                / pClipCtxt->iSilenceFrameDuration)
1575                * pClipCtxt->iSilenceFrameDuration;
1576            pClipCtxt->iAudioFrameCts = 0; /* No frame read yet */
1577
1578            /**
1579            * To detect some may-be bugs, I prefer to reset all these after a jump */
1580            pClipCtxt->bAudioFrameAvailable = M4OSA_FALSE;
1581            pClipCtxt->pAudioFramePtr = M4OSA_NULL;
1582
1583            /**
1584            * In AMR, we have to manage multi-framed AUs,
1585            but also in AAC the jump can be 1 AU too much backward */
1586            if( *pJumpCts < iTargetCts )
1587            {
1588                /**
1589                * Jump doesn't read any AU, we must read at least one */
1590                err = M4VSS3GPP_intClipReadNextAudioFrame(pClipCtxt);
1591
1592                if( M4OSA_ERR_IS_ERROR(err) )
1593                {
1594                    M4OSA_TRACE1_1(
1595                        "M4VSS3GPP_intClipJumpAudioAt():\
1596                        M4VSS3GPP_intClipReadNextAudioFrame(a) returns 0x%x",
1597                        err);
1598                    return err;
1599                }
1600
1601                /**
1602                * Read AU frames as long as we reach the AU before the target CTS
1603                * (so the target will be reached when the user call ReadNextAudioFrame). */
1604                while( pClipCtxt->iAudioFrameCts
1605                    < (iTargetCts - pClipCtxt->iSilenceFrameDuration) )
1606                {
1607                    err = M4VSS3GPP_intClipReadNextAudioFrame(pClipCtxt);
1608
1609                    if( M4OSA_ERR_IS_ERROR(err) )
1610                    {
1611                        M4OSA_TRACE1_1(
1612                            "M4VSS3GPP_intClipJumpAudioAt():\
1613                            M4VSS3GPP_intClipReadNextAudioFrame(b) returns 0x%x",
1614                            err);
1615                        return err;
1616                    }
1617                }
1618
1619                /**
1620                * Return the CTS that will be reached at next ReadFrame */
1621                *pJumpCts = pClipCtxt->iAudioFrameCts
1622                    + pClipCtxt->iSilenceFrameDuration;
1623            }
1624        }
1625    }
1626
1627    /**
1628    * Return with no error */
1629    M4OSA_TRACE3_0("M4VSS3GPP_intClipJumpAudioAt(): returning M4NO_ERROR");
1630    return M4NO_ERROR;
1631}
1632
1633/**
1634 ******************************************************************************
1635 * M4OSA_ERR M4VSS3GPP_intClipClose()
1636 * @brief    Close a clip. Destroy the context.
1637 * @note
1638 * @param   pClipCtxt            (IN) Internal clip context
1639 * @return    M4NO_ERROR:            No error
1640 ******************************************************************************
1641 */
1642M4OSA_ERR M4VSS3GPP_intClipClose( M4VSS3GPP_ClipContext *pClipCtxt )
1643{
1644    M4OSA_ERR err;
1645
1646    /**
1647    *    Check input parameters */
1648    M4OSA_DEBUG_IF2((M4OSA_NULL == pClipCtxt), M4ERR_PARAMETER,
1649        "M4VSS3GPP_intClipClose: pClipCtxt is M4OSA_NULL");
1650
1651    /**
1652    * Free the video decoder context */
1653    if( M4OSA_NULL != pClipCtxt->pViDecCtxt )
1654    {
1655        pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctDestroy(
1656            pClipCtxt->pViDecCtxt);
1657        pClipCtxt->pViDecCtxt = M4OSA_NULL;
1658    }
1659
1660    /**
1661    * Free the audio decoder context  */
1662    if( M4OSA_NULL != pClipCtxt->pAudioDecCtxt )
1663    {
1664        err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctDestroyAudioDec(
1665            pClipCtxt->pAudioDecCtxt);
1666
1667        if( M4NO_ERROR != err )
1668        {
1669            M4OSA_TRACE1_1(
1670                "M4VSS3GPP_intClipClose: m_pAudioDecoder->m_pFctDestroyAudioDec returns 0x%x",
1671                err);
1672            /**< don't return, we still have stuff to free */
1673        }
1674
1675        pClipCtxt->pAudioDecCtxt = M4OSA_NULL;
1676    }
1677
1678    /**
1679    * Free the decoded audio buffer */
1680    if( M4OSA_NULL != pClipCtxt->AudioDecBufferOut.m_dataAddress )
1681    {
1682        free(pClipCtxt->AudioDecBufferOut.m_dataAddress);
1683        pClipCtxt->AudioDecBufferOut.m_dataAddress = M4OSA_NULL;
1684    }
1685
1686    /**
1687    * Audio AU is allocated by reader.
1688    * If no audio track, audio AU is set at 'silent' (SID) by VSS.
1689    * As a consequence, if audio AU is set to 'silent' (static)
1690    it can't be free unless it is set to NULL */
1691    if( ( (M4OSA_MemAddr8)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048
1692        == pClipCtxt->AudioAU.m_dataAddress)
1693        || ((M4OSA_MemAddr8)pClipCtxt->pSilenceFrameData
1694        == pClipCtxt->AudioAU.m_dataAddress) )
1695    {
1696        pClipCtxt->AudioAU.m_dataAddress = M4OSA_NULL;
1697    }
1698
1699    if( M4OSA_NULL != pClipCtxt->pReaderContext )
1700    {
1701        /**
1702        * Close the 3GPP or MP3 reader */
1703        err = pClipCtxt->ShellAPI.m_pReader->m_pFctClose(
1704            pClipCtxt->pReaderContext);
1705
1706        if( M4NO_ERROR != err )
1707        {
1708            M4OSA_TRACE1_1(
1709                "M4VSS3GPP_intClipClose(): m_pReader->m_pFctClose returns 0x%x",
1710                err);
1711        }
1712
1713        /**
1714        * Destroy the 3GPP or MP3 reader context */
1715        err = pClipCtxt->ShellAPI.m_pReader->m_pFctDestroy(
1716            pClipCtxt->pReaderContext);
1717
1718        if( M4NO_ERROR != err )
1719        {
1720            M4OSA_TRACE1_1(
1721                "M4VSS3GPP_intClipClose(): m_pReader->m_pFctDestroy returns 0x%x",
1722                err);
1723        }
1724
1725        pClipCtxt->pReaderContext = M4OSA_NULL;
1726    }
1727
1728    /**
1729    * Return with no error */
1730    M4OSA_TRACE3_1("M4VSS3GPP_intClipClose(Ctxt=0x%x): returning M4NO_ERROR",
1731        pClipCtxt);
1732    return M4NO_ERROR;
1733}
1734
1735M4OSA_ERR M4VSS3GPP_intClipCleanUp( M4VSS3GPP_ClipContext *pClipCtxt )
1736{
1737    M4OSA_ERR err = M4NO_ERROR, err2;
1738
1739    /**
1740    *    Check input parameters */
1741    M4OSA_DEBUG_IF2((M4OSA_NULL == pClipCtxt), M4ERR_PARAMETER,
1742        "M4VSS3GPP_intClipCleanUp: pClipCtxt is M4OSA_NULL");
1743
1744    /**
1745    * Free the video decoder context */
1746    if( M4OSA_NULL != pClipCtxt->pViDecCtxt )
1747    {
1748        pClipCtxt->ShellAPI.m_pVideoDecoder->m_pFctDestroy(
1749            pClipCtxt->pViDecCtxt);
1750        pClipCtxt->pViDecCtxt = M4OSA_NULL;
1751    }
1752
1753    /**
1754    * Free the audio decoder context  */
1755    if( M4OSA_NULL != pClipCtxt->pAudioDecCtxt )
1756    {
1757        err2 = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctDestroyAudioDec(
1758            pClipCtxt->pAudioDecCtxt);
1759
1760        if( M4NO_ERROR != err2 )
1761        {
1762            M4OSA_TRACE1_1(
1763                "M4VSS3GPP_intClipCleanUp: m_pAudioDecoder->m_pFctDestroyAudioDec returns 0x%x",
1764                err);
1765            /**< don't return, we still have stuff to free */
1766            if( M4NO_ERROR != err )
1767                err = err2;
1768        }
1769
1770        pClipCtxt->pAudioDecCtxt = M4OSA_NULL;
1771    }
1772
1773    /**
1774    * Free the decoded audio buffer */
1775    if( M4OSA_NULL != pClipCtxt->AudioDecBufferOut.m_dataAddress )
1776    {
1777        free(pClipCtxt->AudioDecBufferOut.m_dataAddress);
1778        pClipCtxt->AudioDecBufferOut.m_dataAddress = M4OSA_NULL;
1779    }
1780
1781    /**
1782    * Audio AU is allocated by reader.
1783    * If no audio track, audio AU is set at 'silent' (SID) by VSS.
1784    * As a consequence, if audio AU is set to 'silent' (static)
1785    it can't be free unless it is set to NULL */
1786    if( ( (M4OSA_MemAddr8)M4VSS3GPP_AMR_AU_SILENCE_FRAME_048
1787        == pClipCtxt->AudioAU.m_dataAddress)
1788        || ((M4OSA_MemAddr8)pClipCtxt->pSilenceFrameData
1789        == pClipCtxt->AudioAU.m_dataAddress) )
1790    {
1791        pClipCtxt->AudioAU.m_dataAddress = M4OSA_NULL;
1792    }
1793
1794    if( M4OSA_NULL != pClipCtxt->pReaderContext )
1795    {
1796        /**
1797        * Close the 3GPP or MP3 reader */
1798        err2 = pClipCtxt->ShellAPI.m_pReader->m_pFctClose(
1799            pClipCtxt->pReaderContext);
1800
1801        if( M4NO_ERROR != err2 )
1802        {
1803            M4OSA_TRACE1_1(
1804                "M4VSS3GPP_intClipCleanUp(): m_pReader->m_pFctClose returns 0x%x",
1805                err);
1806
1807            if( M4NO_ERROR != err )
1808                err = err2;
1809        }
1810
1811        /**
1812        * Destroy the 3GPP or MP3 reader context */
1813        err2 = pClipCtxt->ShellAPI.m_pReader->m_pFctDestroy(
1814            pClipCtxt->pReaderContext);
1815
1816        if( M4NO_ERROR != err2 )
1817        {
1818            M4OSA_TRACE1_1(
1819                "M4VSS3GPP_intClipCleanUp(): m_pReader->m_pFctDestroy returns 0x%x",
1820                err);
1821
1822            if( M4NO_ERROR != err )
1823                err = err2;
1824        }
1825
1826        pClipCtxt->pReaderContext = M4OSA_NULL;
1827    }
1828
1829    /**
1830    * Free the shells interfaces */
1831    M4VSS3GPP_unRegisterAllWriters(&pClipCtxt->ShellAPI);
1832    M4VSS3GPP_unRegisterAllEncoders(&pClipCtxt->ShellAPI);
1833    M4VSS3GPP_unRegisterAllReaders(&pClipCtxt->ShellAPI);
1834    M4VSS3GPP_unRegisterAllDecoders(&pClipCtxt->ShellAPI);
1835
1836    M4OSA_TRACE3_1("M4VSS3GPP_intClipCleanUp: pClipCtxt=0x%x", pClipCtxt);
1837    /**
1838    * Free the clip context */
1839    free(pClipCtxt);
1840
1841    return err;
1842}
1843
1844/**
1845 ******************************************************************************
1846 * M4OSA_UInt32 M4VSS3GPP_intGetFrameSize_AMRNB()
1847 * @brief   Return the length, in bytes, of the AMR Narrow-Band frame contained in the given buffer
1848 * @note
1849 * @param   pAudioFrame   (IN) AMRNB frame
1850 * @return  M4NO_ERROR: No error
1851 ******************************************************************************
1852 */
1853
1854M4OSA_UInt32 M4VSS3GPP_intGetFrameSize_AMRNB( M4OSA_MemAddr8 pAudioFrame )
1855{
1856    M4OSA_UInt32 frameSize = 0;
1857    M4OSA_UInt32 frameType = ( ( *pAudioFrame) &(0xF << 3)) >> 3;
1858
1859    switch( frameType )
1860    {
1861        case 0:
1862            frameSize = 95;
1863            break; /*  4750 bps */
1864
1865        case 1:
1866            frameSize = 103;
1867            break; /*  5150 bps */
1868
1869        case 2:
1870            frameSize = 118;
1871            break; /*  5900 bps */
1872
1873        case 3:
1874            frameSize = 134;
1875            break; /*  6700 bps */
1876
1877        case 4:
1878            frameSize = 148;
1879            break; /*  7400 bps */
1880
1881        case 5:
1882            frameSize = 159;
1883            break; /*  7950 bps */
1884
1885        case 6:
1886            frameSize = 204;
1887            break; /* 10200 bps */
1888
1889        case 7:
1890            frameSize = 244;
1891            break; /* 12000 bps */
1892
1893        case 8:
1894            frameSize = 39;
1895            break; /* SID (Silence) */
1896
1897        case 15:
1898            frameSize = 0;
1899            break; /* No data */
1900
1901        default:
1902            M4OSA_TRACE3_0(
1903                "M4VSS3GPP_intGetFrameSize_AMRNB(): Corrupted AMR frame! returning 0.");
1904            return 0;
1905    }
1906
1907    return (1 + (( frameSize + 7) / 8));
1908}
1909
1910/**
1911 ******************************************************************************
1912 * M4OSA_UInt32 M4VSS3GPP_intGetFrameSize_EVRC()
1913 * @brief   Return the length, in bytes, of the EVRC frame contained in the given buffer
1914 * @note
1915 *     0 1 2 3
1916 *    +-+-+-+-+
1917 *    |fr type|              RFC 3558
1918 *    +-+-+-+-+
1919 *
1920 * Frame Type: 4 bits
1921 *    The frame type indicates the type of the corresponding codec data
1922 *    frame in the RTP packet.
1923 *
1924 * For EVRC and SMV codecs, the frame type values and size of the
1925 * associated codec data frame are described in the table below:
1926 *
1927 * Value   Rate      Total codec data frame size (in octets)
1928 * ---------------------------------------------------------
1929 *   0     Blank      0    (0 bit)
1930 *   1     1/8        2    (16 bits)
1931 *   2     1/4        5    (40 bits; not valid for EVRC)
1932 *   3     1/2       10    (80 bits)
1933 *   4     1         22    (171 bits; 5 padded at end with zeros)
1934 *   5     Erasure    0    (SHOULD NOT be transmitted by sender)
1935 *
1936 * @param   pCpAudioFrame   (IN) EVRC frame
1937 * @return  M4NO_ERROR: No error
1938 ******************************************************************************
1939 */
1940M4OSA_UInt32 M4VSS3GPP_intGetFrameSize_EVRC( M4OSA_MemAddr8 pAudioFrame )
1941{
1942    M4OSA_UInt32 frameSize = 0;
1943    M4OSA_UInt32 frameType = ( *pAudioFrame) &0x0F;
1944
1945    switch( frameType )
1946    {
1947        case 0:
1948            frameSize = 0;
1949            break; /*  blank */
1950
1951        case 1:
1952            frameSize = 16;
1953            break; /*  1/8 */
1954
1955        case 2:
1956            frameSize = 40;
1957            break; /*  1/4 */
1958
1959        case 3:
1960            frameSize = 80;
1961            break; /*  1/2 */
1962
1963        case 4:
1964            frameSize = 171;
1965            break; /*  1 */
1966
1967        case 5:
1968            frameSize = 0;
1969            break; /*  erasure */
1970
1971        default:
1972            M4OSA_TRACE3_0(
1973                "M4VSS3GPP_intGetFrameSize_EVRC(): Corrupted EVRC frame! returning 0.");
1974            return 0;
1975    }
1976
1977    return (1 + (( frameSize + 7) / 8));
1978}
1979
1980M4OSA_ERR M4VSS3GPP_intCheckAndGetCodecAacProperties(
1981                                 M4VSS3GPP_ClipContext *pClipCtxt) {
1982
1983    M4OSA_ERR err = M4NO_ERROR;
1984    M4AD_Buffer outputBuffer;
1985    uint32_t optionValue =0;
1986
1987    // Decode first audio frame from clip to get properties from codec
1988
1989    err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctCreateAudioDec(
1990                    &pClipCtxt->pAudioDecCtxt,
1991                    pClipCtxt->pAudioStream, &(pClipCtxt->AacProperties));
1992
1993    pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec(
1994     pClipCtxt->pAudioDecCtxt, M4AD_kOptionID_3gpReaderInterface,
1995     (M4OSA_DataOption) pClipCtxt->ShellAPI.m_pReaderDataIt);
1996
1997    pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctSetOptionAudioDec(
1998     pClipCtxt->pAudioDecCtxt, M4AD_kOptionID_AudioAU,
1999     (M4OSA_DataOption) &pClipCtxt->AudioAU);
2000
2001    if( pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStartAudioDec != M4OSA_NULL ) {
2002
2003        err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStartAudioDec(
2004         pClipCtxt->pAudioDecCtxt);
2005        if( M4NO_ERROR != err ) {
2006
2007            M4OSA_TRACE1_1(
2008                "M4VSS3GPP_intCheckAndGetCodecAacProperties: \
2009                 m_pFctStartAudioDec returns 0x%x", err);
2010            return err;
2011        }
2012    }
2013
2014    /**
2015    * Allocate output buffer for the audio decoder */
2016    outputBuffer.m_bufferSize =
2017        pClipCtxt->pAudioStream->m_byteFrameLength
2018        * pClipCtxt->pAudioStream->m_byteSampleSize
2019        * pClipCtxt->pAudioStream->m_nbChannels;
2020
2021    if( outputBuffer.m_bufferSize > 0 ) {
2022
2023        outputBuffer.m_dataAddress =
2024            (M4OSA_MemAddr8)M4OSA_32bitAlignedMalloc(outputBuffer.m_bufferSize \
2025            *sizeof(short), M4VSS3GPP, (M4OSA_Char *)"outputBuffer.m_bufferSize");
2026
2027        if( M4OSA_NULL == outputBuffer.m_dataAddress ) {
2028
2029            M4OSA_TRACE1_0(
2030                "M4VSS3GPP_intCheckAndGetCodecAacProperties():\
2031                 unable to allocate outputBuffer.m_dataAddress");
2032            return M4ERR_ALLOC;
2033        }
2034    }
2035
2036    err = pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctStepAudioDec(
2037            pClipCtxt->pAudioDecCtxt, M4OSA_NULL, &outputBuffer, M4OSA_FALSE);
2038
2039    if ( err == M4WAR_INFO_FORMAT_CHANGE ) {
2040
2041        // Get the properties from codec node
2042        pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctGetOptionAudioDec(
2043         pClipCtxt->pAudioDecCtxt,
2044           M4AD_kOptionID_AudioNbChannels, (M4OSA_DataOption) &optionValue);
2045
2046        pClipCtxt->AacProperties.aNumChan = optionValue;
2047        // Reset Reader structure value also
2048        pClipCtxt->pAudioStream->m_nbChannels = optionValue;
2049
2050        pClipCtxt->ShellAPI.m_pAudioDecoder->m_pFctGetOptionAudioDec(
2051         pClipCtxt->pAudioDecCtxt,
2052          M4AD_kOptionID_AudioSampFrequency, (M4OSA_DataOption) &optionValue);
2053
2054        pClipCtxt->AacProperties.aSampFreq = optionValue;
2055        // Reset Reader structure value also
2056        pClipCtxt->pAudioStream->m_samplingFrequency = optionValue;
2057
2058    } else if( err != M4NO_ERROR) {
2059        M4OSA_TRACE1_1("M4VSS3GPP_intCheckAndGetCodecAacProperties:\
2060            m_pFctStepAudioDec returns err = 0x%x", err);
2061    }
2062
2063    free(outputBuffer.m_dataAddress);
2064
2065    // Reset the stream reader
2066    err = pClipCtxt->ShellAPI.m_pReader->m_pFctReset(
2067     pClipCtxt->pReaderContext,
2068     (M4_StreamHandler *)pClipCtxt->pAudioStream);
2069
2070    if (M4NO_ERROR != err) {
2071        M4OSA_TRACE1_1("M4VSS3GPP_intCheckAndGetCodecAacProperties\
2072            Error in reseting reader: 0x%x", err);
2073    }
2074
2075    return err;
2076
2077}
2078