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