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