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