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