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