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_ClipAnalysis.c
19 * @brief    Implementation of functions related to analysis of input clips
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#include "M4VD_EXTERNAL_Interface.h"
37
38
39/**
40 *    OSAL headers */
41#include "M4OSA_Memory.h" /* OSAL memory management */
42#include "M4OSA_Debug.h"  /* OSAL debug management */
43
44/**
45 ******************************************************************************
46 * M4OSA_ERR M4VSS3GPP_editAnalyseClip()
47 * @brief    This function allows checking if a clip is compatible with VSS 3GPP editing
48 * @note    It also fills a ClipAnalysis structure, which can be used to check if two
49 *        clips are compatible
50 * @param    pClip                (IN) File descriptor of the input 3GPP/MP3 clip file.
51 * @param    pClipProperties        (IN) Pointer to a valid ClipProperties structure.
52 * @param    FileType            (IN) Type of the input file (.3gp, .amr, .mp3)
53 * @return    M4NO_ERROR:            No error
54 * @return    M4ERR_PARAMETER:    At least one parameter is M4OSA_NULL (debug only)
55 * @return   M4VSS3GPP_ERR_H263_PROFILE_NOT_SUPPORTED
56 * @return   M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION
57 * @return   M4VSS3GPP_ERR_AMR_EDITING_UNSUPPORTED
58 * @return   M4VSS3GPP_ERR_EDITING_UNSUPPORTED_H263_PROFILE
59 * @return   M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_PROFILE
60 * @return   M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_RVLC
61 * @return   M4VSS3GPP_ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT
62 * @return   M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE
63 * @return   M4VSS3GPP_ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT
64 * @return   M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE
65 ******************************************************************************
66 */
67M4OSA_ERR M4VSS3GPP_editAnalyseClip( M4OSA_Void *pClip,
68                                    M4VIDEOEDITING_FileType FileType,
69                                    M4VIDEOEDITING_ClipProperties *pClipProperties,
70                                    M4OSA_FileReadPointer *pFileReadPtrFct )
71{
72    M4OSA_ERR err;
73    M4VSS3GPP_ClipContext *pClipContext;
74    M4VSS3GPP_ClipSettings ClipSettings;
75
76    M4OSA_TRACE3_2(
77        "M4VSS3GPP_editAnalyseClip called with pClip=0x%x, pClipProperties=0x%x",
78        pClip, pClipProperties);
79
80    /**
81    *    Check input parameter */
82    M4OSA_DEBUG_IF2((M4OSA_NULL == pClip), M4ERR_PARAMETER,
83        "M4VSS3GPP_editAnalyseClip: pClip is M4OSA_NULL");
84    M4OSA_DEBUG_IF2((M4OSA_NULL == pClipProperties), M4ERR_PARAMETER,
85        "M4VSS3GPP_editAnalyseClip: pClipProperties is M4OSA_NULL");
86
87    /**
88    * Build dummy clip settings, in order to use the editClipOpen function */
89    ClipSettings.pFile = pClip;
90    ClipSettings.FileType = FileType;
91    ClipSettings.uiBeginCutTime = 0;
92    ClipSettings.uiEndCutTime = 0;
93
94    /* Clip properties not build yet, set at least this flag */
95    ClipSettings.ClipProperties.bAnalysed = M4OSA_FALSE;
96
97    /**
98    * Open the clip in fast open mode */
99    err = M4VSS3GPP_intClipInit(&pClipContext, pFileReadPtrFct);
100
101    if( M4NO_ERROR != err )
102    {
103        M4OSA_TRACE1_1(
104            "M4VSS3GPP_editAnalyseClip: M4VSS3GPP_intClipInit() returns 0x%x!",
105            err);
106
107        /**
108        * Free the clip */
109        if( M4OSA_NULL != pClipContext )
110        {
111            M4VSS3GPP_intClipCleanUp(pClipContext);
112        }
113        return err;
114    }
115
116    err = M4VSS3GPP_intClipOpen(pClipContext, &ClipSettings, M4OSA_FALSE,
117        M4OSA_TRUE, M4OSA_TRUE);
118
119    if( M4NO_ERROR != err )
120    {
121        M4OSA_TRACE1_1(
122            "M4VSS3GPP_editAnalyseClip: M4VSS3GPP_intClipOpen() returns 0x%x!",
123            err);
124
125        M4VSS3GPP_intClipCleanUp(pClipContext);
126
127        /**
128        * Here it is better to return the Editing specific error code */
129        if( ( ((M4OSA_UInt32)M4ERR_DECODER_H263_PROFILE_NOT_SUPPORTED) == err)
130            || (((M4OSA_UInt32)M4ERR_DECODER_H263_NOT_BASELINE) == err) )
131        {
132            M4OSA_TRACE1_0(
133                "M4VSS3GPP_editAnalyseClip:\
134                M4VSS3GPP_intClipOpen() returns M4VSS3GPP_ERR_H263_PROFILE_NOT_SUPPORTED");
135            return M4VSS3GPP_ERR_H263_PROFILE_NOT_SUPPORTED;
136        }
137        return err;
138    }
139
140    /**
141    * Analyse the clip */
142    if(M4VIDEOEDITING_kFileType_ARGB8888 != pClipContext->pSettings->FileType) {
143        err = M4VSS3GPP_intBuildAnalysis(pClipContext, pClipProperties);
144
145        if( M4NO_ERROR != err )
146        {
147            M4OSA_TRACE1_1(
148                "M4VSS3GPP_editAnalyseClip: M4VSS3GPP_intBuildAnalysis() returns 0x%x!",
149                err);
150
151            /**
152            * Free the clip */
153            M4VSS3GPP_intClipCleanUp(pClipContext);
154            return err;
155        }
156    }
157    /**
158    * Free the clip */
159    err = M4VSS3GPP_intClipClose(pClipContext);
160
161    if( M4NO_ERROR != err )
162    {
163        M4OSA_TRACE1_1(
164            "M4VSS3GPP_editAnalyseClip: M4VSS_intClipClose() returns 0x%x!",
165            err);
166        M4VSS3GPP_intClipCleanUp(pClipContext);
167        return err;
168    }
169
170    M4VSS3GPP_intClipCleanUp(pClipContext);
171
172    /**
173    * Check the clip is compatible with VSS editing */
174    if(M4VIDEOEDITING_kFileType_ARGB8888 != ClipSettings.FileType) {
175        err = M4VSS3GPP_intCheckClipCompatibleWithVssEditing(pClipProperties);
176
177        if( M4NO_ERROR != err )
178        {
179            M4OSA_TRACE1_1(
180                "M4VSS3GPP_editAnalyseClip:\
181                M4VSS3GPP_intCheckClipCompatibleWithVssEditing() returns 0x%x!",
182                err);
183            return err;
184        }
185    }
186    /**
187    * Return with no error */
188    M4OSA_TRACE3_0("M4VSS3GPP_editAnalyseClip(): returning M4NO_ERROR");
189    return M4NO_ERROR;
190}
191
192/**
193 ******************************************************************************
194 * M4OSA_ERR M4VSS3GPP_editCheckClipCompatibility()
195 * @brief    This function allows checking if two clips are compatible with each other for
196 *        VSS 3GPP editing assembly feature.
197 * @note
198 * @param    pClip1Properties        (IN) Clip analysis of the first clip
199 * @param    pClip2Properties        (IN) Clip analysis of the second clip
200 * @return    M4NO_ERROR:            No error
201 * @return    M4ERR_PARAMETER:    At least one parameter is M4OSA_NULL (debug only)
202 * @return    M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION
203 * @return    M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FORMAT
204 * @return    M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FRAME_SIZE
205 * @return    M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_TIME_SCALE
206 * @return    M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_DATA_PARTITIONING
207 * @return  M4VSS3GPP_ERR_UNSUPPORTED_MP3_ASSEMBLY
208 * @return  M4VSS3GPP_ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT
209 ******************************************************************************
210 */
211M4OSA_ERR M4VSS3GPP_editCheckClipCompatibility( M4VIDEOEDITING_ClipProperties *pClip1Properties,
212                                                M4VIDEOEDITING_ClipProperties *pClip2Properties )
213{
214    M4OSA_ERR err = M4NO_ERROR;
215    M4OSA_ERR video_err = M4NO_ERROR;
216    M4OSA_ERR audio_err = M4NO_ERROR;
217
218    M4OSA_Bool bClip1IsAAC = M4OSA_FALSE;
219    M4OSA_Bool bClip2IsAAC = M4OSA_FALSE;
220
221    M4OSA_TRACE3_2("M4VSS3GPP_editCheckClipCompatibility called with pClip1Analysis=0x%x,\
222                   pClip2Analysis=0x%x", pClip1Properties, pClip2Properties);
223
224    /**
225    *    Check input parameter */
226    M4OSA_DEBUG_IF2((M4OSA_NULL == pClip1Properties), M4ERR_PARAMETER,
227        "M4VSS3GPP_editCheckClipCompatibility: pClip1Properties is M4OSA_NULL");
228    M4OSA_DEBUG_IF2((M4OSA_NULL == pClip2Properties), M4ERR_PARAMETER,
229        "M4VSS3GPP_editCheckClipCompatibility: pClip2Properties is M4OSA_NULL");
230
231    if( ( M4VIDEOEDITING_kFileType_MP3 == pClip1Properties->FileType)
232        || (M4VIDEOEDITING_kFileType_AMR == pClip1Properties->FileType) )
233    {
234        if( pClip1Properties != pClip2Properties )
235        {
236            M4OSA_TRACE1_0(
237                "M4VSS3GPP_editCheckClipCompatibility: MP3 CAN ONLY BE CUT,\
238                returning M4VSS3GPP_ERR_UNSUPPORTED_MP3_ASSEMBLY");
239            return M4VSS3GPP_ERR_UNSUPPORTED_MP3_ASSEMBLY;
240        }
241        else
242        {
243            /* We are in VSS Splitter mode */
244            goto audio_analysis;
245        }
246    }
247
248    /********** Audio ************/
249
250audio_analysis:
251    if( M4VIDEOEDITING_kNoneAudio != pClip1Properties->
252        AudioStreamType ) /**< if there is an audio stream */
253    {
254        /**
255        * Check audio format is AAC */
256        switch( pClip1Properties->AudioStreamType )
257        {
258            case M4VIDEOEDITING_kAAC:
259            case M4VIDEOEDITING_kAACplus:
260            case M4VIDEOEDITING_keAACplus:
261                bClip1IsAAC = M4OSA_TRUE;
262                break;
263            default:
264                break;
265        }
266    }
267
268    if( M4VIDEOEDITING_kNoneAudio != pClip2Properties->
269        AudioStreamType ) /**< if there is an audio stream */
270    {
271        /**
272        * Check audio format is AAC */
273        switch( pClip2Properties->AudioStreamType )
274        {
275            case M4VIDEOEDITING_kAAC:
276            case M4VIDEOEDITING_kAACplus:
277            case M4VIDEOEDITING_keAACplus:
278                bClip2IsAAC = M4OSA_TRUE;
279                break;
280            default:
281                break;
282        }
283    }
284
285    /**
286    * If there is no audio, the clips are compatibles ... */
287    if( ( pClip1Properties->AudioStreamType != M4VIDEOEDITING_kNoneAudio)
288        && (pClip2Properties->AudioStreamType != M4VIDEOEDITING_kNoneAudio) )
289    {
290        /**
291        * Check both clips have same audio stream type
292        * And let_s say AAC, AAC+ and eAAC+ are mixable */
293        if( ( pClip1Properties->AudioStreamType
294            != pClip2Properties->AudioStreamType)
295            && (( M4OSA_FALSE == bClip1IsAAC) || (M4OSA_FALSE == bClip2IsAAC)) )
296        {
297            M4OSA_TRACE1_0(
298                "M4VSS3GPP_editCheckClipCompatibility:\
299                Clips don't have the same Audio Stream Type");
300
301            audio_err = M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_STREAM_TYPE;
302            goto analysis_done;
303        }
304
305        /**
306        * Check both clips have same number of channels */
307        if( pClip1Properties->uiNbChannels != pClip2Properties->uiNbChannels )
308        {
309            M4OSA_TRACE1_0(
310                "M4VSS3GPP_editCheckClipCompatibility: Clips don't have the same Nb of Channels");
311            audio_err = M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_NB_OF_CHANNELS;
312            goto analysis_done;
313        }
314
315        /**
316        * Check both clips have same sampling frequency */
317        if( pClip1Properties->uiSamplingFrequency
318            != pClip2Properties->uiSamplingFrequency )
319        {
320            M4OSA_TRACE1_0(
321                "M4VSS3GPP_editCheckClipCompatibility:\
322                Clips don't have the same Sampling Frequency");
323            audio_err = M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_SAMPLING_FREQUENCY;
324            goto analysis_done;
325        }
326    }
327
328    pClip2Properties->bAudioIsCompatibleWithMasterClip = M4OSA_TRUE;
329
330    /**
331    * Return with no error */
332
333analysis_done:
334    if( video_err != M4NO_ERROR )
335        return video_err;
336
337    if( audio_err != M4NO_ERROR )
338        return audio_err;
339
340    M4OSA_TRACE3_0(
341        "M4VSS3GPP_editCheckClipCompatibility(): returning M4NO_ERROR");
342    return M4NO_ERROR;
343}
344
345/**
346 ******************************************************************************
347 * M4OSA_ERR M4VSS3GPP_intBuildAnalysis()
348 * @brief    Get video and audio properties from the clip streams
349 * @note    This function must return fatal errors only (errors that should not happen
350 *        in the final integrated product).
351 * @param   pClipCtxt            (IN) internal clip context
352 * @param    pClipProperties        (OUT) Pointer to a valid ClipProperties structure.
353 * @return    M4NO_ERROR:            No error
354 ******************************************************************************
355 */
356M4OSA_ERR M4VSS3GPP_intBuildAnalysis( M4VSS3GPP_ClipContext *pClipCtxt,
357                                     M4VIDEOEDITING_ClipProperties *pClipProperties )
358{
359    M4OSA_ERR err;
360    M4DECODER_MPEG4_DecoderConfigInfo DecConfigInfo;
361    M4DECODER_VideoSize dummySize;
362    M4DECODER_AVCProfileLevel AVCProfle;
363
364    pClipProperties->bAnalysed = M4OSA_FALSE;
365
366    /**
367    * Reset video characteristics */
368    pClipProperties->VideoStreamType = M4VIDEOEDITING_kNoneVideo;
369    pClipProperties->uiClipVideoDuration = 0;
370    pClipProperties->uiVideoBitrate = 0;
371    pClipProperties->uiVideoMaxAuSize = 0;
372    pClipProperties->uiVideoWidth = 0;
373    pClipProperties->uiVideoHeight = 0;
374    pClipProperties->uiVideoTimeScale = 0;
375    pClipProperties->fAverageFrameRate = 0.0;
376    pClipProperties->uiVideoProfile =
377        M4VIDEOEDITING_VIDEO_UNKNOWN_PROFILE;
378    pClipProperties->uiVideoLevel =
379        M4VIDEOEDITING_VIDEO_UNKNOWN_LEVEL;
380    pClipProperties->bMPEG4dataPartition = M4OSA_FALSE;
381    pClipProperties->bMPEG4rvlc = M4OSA_FALSE;
382    pClipProperties->bMPEG4resynchMarker = M4OSA_FALSE;
383
384    memset((void *) &pClipProperties->ftyp,0,
385        sizeof(pClipProperties->ftyp));
386
387    /**
388    * Video Analysis */
389    if( M4OSA_NULL != pClipCtxt->pVideoStream )
390    {
391        pClipProperties->uiVideoWidth = pClipCtxt->pVideoStream->m_videoWidth;
392        pClipProperties->uiVideoHeight = pClipCtxt->pVideoStream->m_videoHeight;
393        pClipProperties->fAverageFrameRate =
394            pClipCtxt->pVideoStream->m_averageFrameRate;
395
396        switch( pClipCtxt->pVideoStream->m_basicProperties.m_streamType )
397        {
398            case M4DA_StreamTypeVideoMpeg4:
399
400                pClipProperties->VideoStreamType = M4VIDEOEDITING_kMPEG4;
401
402   /* This issue is so incredibly stupid that it's depressing. Basically, a file can be analysed
403   outside of any context (besides that of the clip itself), so that for instance two clips can
404   be checked for compatibility before allocating an edit context for editing them. But this
405   means there is no way in heck to pass an external video decoder (to begin with) to this
406   function, as they work by being registered in an existing context; furthermore, it is actually
407   pretty overkill to use a full decoder for that, moreso a HARDWARE decoder just to get the
408   clip config info. In fact, the hardware itself doesn't provide this service, in the case of a
409   HW decoder, the shell builds the config info itself, so we don't need the actual decoder, only
410   a detached functionality of it. So in case HW/external decoders may be present, we instead use
411   directly the DSI parsing function of the shell HW decoder (which we know to be present, since
412   HW decoders are possible) to get the config info. Notice this function is used even if the
413   software decoder is actually present and even if it will end up being actually used: figuring
414   out the config does not involve actual decoding nor the particularities of a specific decoder,
415   it's the fact that it's MPEG4 that matters, so it should not be functionally any different
416   from the way it was done before (and it's light enough for performance not to be any problem
417         whatsoever). */
418
419                err = M4DECODER_EXTERNAL_ParseVideoDSI(pClipCtxt->pVideoStream->
420                            m_basicProperties.m_pDecoderSpecificInfo,
421                            pClipCtxt->pVideoStream->m_basicProperties.m_decoderSpecificInfoSize,
422                            &DecConfigInfo, &dummySize);
423
424                if( M4NO_ERROR != err )
425                {
426                    M4OSA_TRACE1_1(
427                        "M4VSS3GPP_intBuildAnalysis():\
428                        M4DECODER_EXTERNAL_ParseVideoDSI returns 0x%08X", err);
429                    return err;
430                }
431
432                pClipProperties->uiVideoTimeScale =
433                    DecConfigInfo.uiTimeScale;
434                pClipProperties->bMPEG4dataPartition =
435                    DecConfigInfo.bDataPartition;
436                pClipProperties->bMPEG4rvlc =
437                    DecConfigInfo.bUseOfRVLC;
438                pClipProperties->bMPEG4resynchMarker =
439                    DecConfigInfo.uiUseOfResynchMarker;
440                err = getMPEG4ProfileAndLevel(DecConfigInfo.uiProfile,
441                            &(pClipProperties->uiVideoProfile),
442                            &(pClipProperties->uiVideoLevel));
443               if (M4NO_ERROR != err) {
444                    M4OSA_TRACE1_1("M4VSS3GPP_intBuildAnalysis(): \
445                         getMPEG4ProfileAndLevel returns 0x%08X", err);
446                    return err;
447                }
448                break;
449
450            case M4DA_StreamTypeVideoH263:
451
452                pClipProperties->VideoStreamType = M4VIDEOEDITING_kH263;
453                /* H263 time scale is always 30000 */
454                pClipProperties->uiVideoTimeScale = 30000;
455
456                err = getH263ProfileAndLevel(pClipCtxt->pVideoStream->
457                            m_basicProperties.m_pDecoderSpecificInfo,
458                            pClipCtxt->pVideoStream->m_basicProperties.m_decoderSpecificInfoSize,
459                            &pClipProperties->uiVideoProfile,
460                            &pClipProperties->uiVideoLevel);
461                if (M4NO_ERROR != err) {
462                    M4OSA_TRACE1_1("M4VSS3GPP_intBuildAnalysis(): \
463                         getH263ProfileAndLevel returns 0x%08X", err);
464                    return err;
465                }
466                break;
467
468            case M4DA_StreamTypeVideoMpeg4Avc:
469
470                pClipProperties->VideoStreamType = M4VIDEOEDITING_kH264;
471                err = getAVCProfileAndLevel(pClipCtxt->pVideoStream->
472                            m_basicProperties.m_pDecoderSpecificInfo,
473                            pClipCtxt->pVideoStream->m_basicProperties.m_decoderSpecificInfoSize,
474                            &pClipProperties->uiVideoProfile,
475                            &pClipProperties->uiVideoLevel);
476                if (M4NO_ERROR != err) {
477                    M4OSA_TRACE1_1("M4VSS3GPP_intBuildAnalysis(): \
478                         getAVCProfileAndLevel returns 0x%08X", err);
479                    return err;
480                }
481                break;
482
483            default:
484                M4OSA_TRACE1_1(
485                    "M4VSS3GPP_intBuildAnalysis: unknown input video format (0x%x),\
486                     returning M4NO_ERROR",
487                    pClipCtxt->pVideoStream->m_basicProperties.m_streamType);
488
489                 /** We do not return error here.
490                   *  The video format compatibility check will be done latter */
491                return M4NO_ERROR;
492        }
493
494        pClipProperties->uiClipVideoDuration =
495            (M4OSA_UInt32)pClipCtxt->pVideoStream->m_basicProperties.m_duration;
496        pClipProperties->uiVideoMaxAuSize =
497            pClipCtxt->pVideoStream->m_basicProperties.m_maxAUSize;
498
499        /* if video bitrate not available retrieve an estimation of the overall bitrate */
500        pClipProperties->uiVideoBitrate =
501            (M4OSA_UInt32)pClipCtxt->pVideoStream->
502            m_basicProperties.m_averageBitRate;
503
504        if( 0 == pClipProperties->uiVideoBitrate )
505        {
506            pClipCtxt->ShellAPI.m_pReader->m_pFctGetOption(
507                pClipCtxt->pReaderContext, M4READER_kOptionID_Bitrate,
508                &pClipProperties->uiVideoBitrate);
509
510            if( M4OSA_NULL != pClipCtxt->pAudioStream )
511            {
512                /* we get the overall bitrate, substract the audio bitrate if any */
513                pClipProperties->uiVideoBitrate -=
514                    pClipCtxt->pAudioStream->m_basicProperties.m_averageBitRate;
515            }
516        }
517    }
518
519    /**
520    * Reset audio characteristics */
521    pClipProperties->AudioStreamType = M4VIDEOEDITING_kNoneAudio;
522    pClipProperties->uiClipAudioDuration = 0;
523    pClipProperties->uiAudioBitrate = 0;
524    pClipProperties->uiAudioMaxAuSize = 0;
525    pClipProperties->uiNbChannels = 0;
526    pClipProperties->uiSamplingFrequency = 0;
527    pClipProperties->uiExtendedSamplingFrequency = 0;
528    pClipProperties->uiDecodedPcmSize = 0;
529
530    /**
531    * Audio Analysis */
532    if( M4OSA_NULL != pClipCtxt->pAudioStream )
533    {
534        switch( pClipCtxt->pAudioStream->m_basicProperties.m_streamType )
535        {
536            case M4DA_StreamTypeAudioAmrNarrowBand:
537
538                pClipProperties->AudioStreamType = M4VIDEOEDITING_kAMR_NB;
539                break;
540
541            case M4DA_StreamTypeAudioAac:
542
543                pClipProperties->AudioStreamType = M4VIDEOEDITING_kAAC;
544                break;
545
546            case M4DA_StreamTypeAudioMp3:
547
548                pClipProperties->AudioStreamType = M4VIDEOEDITING_kMP3;
549                break;
550
551            case M4DA_StreamTypeAudioEvrc:
552
553                pClipProperties->AudioStreamType = M4VIDEOEDITING_kEVRC;
554                break;
555
556            case M4DA_StreamTypeAudioPcm:
557
558                pClipProperties->AudioStreamType = M4VIDEOEDITING_kPCM;
559                break;
560
561            default:
562
563                M4OSA_TRACE1_1(
564                    "M4VSS3GPP_intBuildAnalysis: unknown input audio format (0x%x),\
565                    returning M4NO_ERROR!",
566                    pClipCtxt->pAudioStream->m_basicProperties.m_streamType);
567                return
568                    M4NO_ERROR; /**< We do not return error here.
569                                The audio format compatibility check will be done latter */
570        }
571
572        pClipProperties->uiAudioMaxAuSize =
573            pClipCtxt->pAudioStream->m_basicProperties.m_maxAUSize;
574        pClipProperties->uiClipAudioDuration =
575            (M4OSA_UInt32)pClipCtxt->pAudioStream->m_basicProperties.m_duration;
576
577        pClipProperties->uiNbChannels = pClipCtxt->pAudioStream->m_nbChannels;
578        pClipProperties->uiSamplingFrequency =
579            pClipCtxt->pAudioStream->m_samplingFrequency;
580        pClipProperties->uiDecodedPcmSize =
581            pClipCtxt->pAudioStream->m_byteFrameLength
582            * pClipCtxt->pAudioStream->m_byteSampleSize
583            * pClipCtxt->pAudioStream->m_nbChannels;
584
585        /**
586        * Bugfix P4ME00001128: With some IMTC files, the AMR bit rate is 0 kbps
587        according the GetProperties function */
588        pClipProperties->uiAudioBitrate =
589            (M4OSA_UInt32)pClipCtxt->pAudioStream->
590            m_basicProperties.m_averageBitRate;
591
592        if( 0 == pClipProperties->uiAudioBitrate )
593        {
594            if( M4VIDEOEDITING_kAMR_NB == pClipProperties->AudioStreamType )
595            {
596                /**
597                *Better returning a guessed 12.2 kbps value than a sure-to-be-false 0 kbps value!*/
598                pClipProperties->uiAudioBitrate = M4VSS3GPP_AMR_DEFAULT_BITRATE;
599            }
600            else if( M4VIDEOEDITING_kEVRC == pClipProperties->AudioStreamType )
601            {
602                /**
603                *Better returning a guessed 9.2 kbps value than a sure-to-be-false 0 kbps value!*/
604                pClipProperties->uiAudioBitrate =
605                    M4VSS3GPP_EVRC_DEFAULT_BITRATE;
606            }
607            else
608            {
609                pClipCtxt->ShellAPI.m_pReader->m_pFctGetOption(
610                    pClipCtxt->pReaderContext, M4READER_kOptionID_Bitrate,
611                    &pClipProperties->uiAudioBitrate);
612
613                if( M4OSA_NULL != pClipCtxt->pVideoStream )
614                {
615                    /* we get the overall bitrate, substract the video bitrate if any */
616                    pClipProperties->uiAudioBitrate -= pClipCtxt->pVideoStream->
617                        m_basicProperties.m_averageBitRate;
618                }
619            }
620        }
621
622        /* New aac properties */
623        if( M4DA_StreamTypeAudioAac
624            == pClipCtxt->pAudioStream->m_basicProperties.m_streamType )
625        {
626            pClipProperties->uiNbChannels = pClipCtxt->AacProperties.aNumChan;
627            pClipProperties->uiSamplingFrequency =
628                pClipCtxt->AacProperties.aSampFreq;
629
630            if( pClipCtxt->AacProperties.aSBRPresent )
631            {
632                pClipProperties->AudioStreamType = M4VIDEOEDITING_kAACplus;
633                pClipProperties->uiExtendedSamplingFrequency =
634                    pClipCtxt->AacProperties.aExtensionSampFreq;
635            }
636
637            if( pClipCtxt->AacProperties.aPSPresent )
638            {
639                pClipProperties->AudioStreamType = M4VIDEOEDITING_keAACplus;
640            }
641        }
642    }
643
644    /* Get 'ftyp' atom */
645    err = pClipCtxt->ShellAPI.m_pReader->m_pFctGetOption(
646        pClipCtxt->pReaderContext,
647        M4READER_kOptionID_3gpFtypBox, &pClipProperties->ftyp);
648
649    /**
650    * We write the VSS 3GPP version in the clip analysis to be sure the integrator doesn't
651    * mix older analysis results with newer libraries */
652    pClipProperties->Version[0] = M4VIDEOEDITING_VERSION_MAJOR;
653    pClipProperties->Version[1] = M4VIDEOEDITING_VERSION_MINOR;
654    pClipProperties->Version[2] = M4VIDEOEDITING_VERSION_REVISION;
655
656    pClipProperties->FileType = pClipCtxt->pSettings->FileType;
657
658    if( pClipProperties->uiClipVideoDuration
659        > pClipProperties->uiClipAudioDuration )
660        pClipProperties->uiClipDuration = pClipProperties->uiClipVideoDuration;
661    else
662        pClipProperties->uiClipDuration = pClipProperties->uiClipAudioDuration;
663
664    /* Reset compatibility chart */
665    pClipProperties->bVideoIsEditable = M4OSA_FALSE;
666    pClipProperties->bAudioIsEditable = M4OSA_FALSE;
667    pClipProperties->bVideoIsCompatibleWithMasterClip = M4OSA_FALSE;
668    pClipProperties->bAudioIsCompatibleWithMasterClip = M4OSA_FALSE;
669
670    /* Analysis successfully completed */
671    pClipProperties->bAnalysed = M4OSA_TRUE;
672
673    /**
674    * Return with no error */
675    M4OSA_TRACE3_0("M4VSS3GPP_intBuildAnalysis(): returning M4NO_ERROR");
676    return M4NO_ERROR;
677}
678
679/**
680 ******************************************************************************
681 * M4OSA_ERR M4VSS3GPP_intCheckClipCompatibleWithVssEditing()
682 * @brief    Check if the clip is compatible with VSS editing
683 * @note
684 * @param   pClipCtxt            (IN) internal clip context
685 * @param    pClipProperties     (OUT) Pointer to a valid ClipProperties structure.
686 * @return    M4NO_ERROR:            No error
687 ******************************************************************************
688 */
689M4OSA_ERR M4VSS3GPP_intCheckClipCompatibleWithVssEditing(
690    M4VIDEOEDITING_ClipProperties *pClipProperties )
691{
692    M4OSA_UInt32 uiNbOfValidStreams = 0;
693    M4OSA_ERR video_err = M4NO_ERROR;
694    M4OSA_ERR audio_err = M4NO_ERROR;
695    /********* file type *********/
696
697    if( M4VIDEOEDITING_kFileType_AMR == pClipProperties->FileType )
698    {
699        M4OSA_TRACE1_0(
700            "M4VSS3GPP_intCheckClipCompatibleWithVssEditing:\
701            returning M4VSS3GPP_ERR_AMR_EDITING_UNSUPPORTED");
702        return M4VSS3GPP_ERR_AMR_EDITING_UNSUPPORTED;
703    }
704
705    if( M4VIDEOEDITING_kFileType_MP3 == pClipProperties->FileType )
706    {
707        M4OSA_TRACE3_0(
708            "M4VSS3GPP_intCheckClipCompatibleWithVssEditing(): returning M4NO_ERROR");
709        return M4NO_ERROR;
710    }
711
712    /********* Video *********/
713
714    if( M4VIDEOEDITING_kNoneVideo
715        != pClipProperties->VideoStreamType ) /**< if there is a video stream */
716    {
717        /* Check video format is MPEG-4, H263 or H264 */
718        switch( pClipProperties->VideoStreamType )
719        {
720            case M4VIDEOEDITING_kH263:
721            case M4VIDEOEDITING_kMPEG4:
722            case M4VIDEOEDITING_kH264:
723                uiNbOfValidStreams++;
724                pClipProperties->bVideoIsEditable = M4OSA_TRUE;
725                break;
726
727            default: /*< KO, we return error */
728                M4OSA_TRACE1_0(
729                    "M4VSS3GPP_intCheckClipCompatibleWithVssEditing(): unsupported video format");
730                video_err = M4VSS3GPP_ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT;
731                break;
732        }
733    }
734    else
735    {
736        /**
737        * Audio only stream are currently not supported by the VSS editing feature
738        (unless in the MP3 case) */
739        M4OSA_TRACE1_0(
740            "M4VSS3GPP_intCheckClipCompatibleWithVssEditing(): No video stream in clip");
741        video_err = M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE;
742    }
743
744    /********* Audio *********/
745    if( M4VIDEOEDITING_kNoneAudio != pClipProperties->
746        AudioStreamType ) /**< if there is an audio stream */
747    {
748        /**
749        * Check audio format is AMR-NB, EVRC or AAC */
750        switch( pClipProperties->AudioStreamType )
751        {
752            case M4VIDEOEDITING_kAMR_NB:
753                pClipProperties->bAudioIsEditable = M4OSA_TRUE;
754                uiNbOfValidStreams++;
755                break;
756
757            case M4VIDEOEDITING_kAAC:
758            case M4VIDEOEDITING_kAACplus:
759            case M4VIDEOEDITING_keAACplus:
760                switch( pClipProperties->uiSamplingFrequency )
761                {
762                case 8000:
763                case 16000:
764                case 22050:
765                case 24000:
766                case 32000:
767                case 44100:
768                case 48000:
769                    pClipProperties->bAudioIsEditable = M4OSA_TRUE;
770                    break;
771
772                default:
773                    break;
774                }
775                uiNbOfValidStreams++;
776                break;
777
778            case M4VIDEOEDITING_kEVRC:
779                /*< OK, we proceed, no return */
780                uiNbOfValidStreams++;
781                break;
782
783            default: /*< KO, we return error */
784                M4OSA_TRACE1_0(
785                    "M4VSS3GPP_intCheckClipCompatibleWithVssEditing(): unsupported audio format");
786                audio_err = M4VSS3GPP_ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT;
787                break;
788        }
789    }
790    else
791    {
792        /* Silence is always editable */
793        pClipProperties->bAudioIsEditable = M4OSA_TRUE;
794    }
795
796    /**
797    * Check there is at least one valid stream in the file... */
798    if( video_err != M4NO_ERROR )
799        return video_err;
800
801    if( audio_err != M4NO_ERROR )
802        return audio_err;
803
804    if( 0 == uiNbOfValidStreams )
805    {
806        M4OSA_TRACE1_0(
807            "M4VSS3GPP_intCheckClipCompatibleWithVssEditing(): File contains no supported stream,\
808            returning M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE");
809        return M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE;
810    }
811
812    /**
813    * Return with no error */
814    M4OSA_TRACE3_0(
815        "M4VSS3GPP_intCheckClipCompatibleWithVssEditing(): returning M4NO_ERROR");
816    return M4NO_ERROR;
817}
818
819/**
820 ******************************************************************************
821 * M4OSA_ERR M4VSS3GPP_intAudioMixingCompatibility()
822 * @brief    This function allows checking if two clips are compatible with each other for
823 *        VSS 3GPP audio mixing feature.
824 * @note
825 * @param    pC                            (IN) Context of the audio mixer
826 * @param    pInputClipProperties        (IN) Clip analysis of the first clip
827 * @param    pAddedClipProperties        (IN) Clip analysis of the second clip
828 * @return    M4NO_ERROR:            No error
829 * @return    M4ERR_PARAMETER:    At least one parameter is M4OSA_NULL (debug only)
830 * @return    M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION
831 * @return  M4VSS3GPP_ERR_INPUT_CLIP_IS_NOT_A_3GPP
832 * @return  M4NO_ERROR
833 ******************************************************************************
834 */
835M4OSA_ERR
836M4VSS3GPP_intAudioMixingCompatibility( M4VSS3GPP_InternalAudioMixingContext
837                                      *pC, M4VIDEOEDITING_ClipProperties *pInputClipProperties,
838                                      M4VIDEOEDITING_ClipProperties *pAddedClipProperties )
839{
840    M4OSA_Bool bClip1IsAAC = M4OSA_FALSE;
841    M4OSA_Bool bClip2IsAAC = M4OSA_FALSE;
842
843    /**
844    * Reset settings */
845    pInputClipProperties->bAudioIsEditable = M4OSA_FALSE;
846    pAddedClipProperties->bAudioIsEditable = M4OSA_FALSE;
847    pInputClipProperties->bAudioIsCompatibleWithMasterClip = M4OSA_FALSE;
848    pAddedClipProperties->bAudioIsCompatibleWithMasterClip = M4OSA_FALSE;
849
850    /**
851    * Check that analysis has been generated by this version of the VSS3GPP library */
852    if( ( pInputClipProperties->Version[0] != M4VIDEOEDITING_VERSION_MAJOR)
853        || (pInputClipProperties->Version[1] != M4VIDEOEDITING_VERSION_MINOR)
854        || (pInputClipProperties->Version[2]
855    != M4VIDEOEDITING_VERSION_REVISION) )
856    {
857        M4OSA_TRACE1_0(
858            "M4VSS3GPP_intAudioMixingCompatibility: The clip analysis has been generated\
859            by another version, returning M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION");
860        return M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION;
861    }
862
863    if( ( pAddedClipProperties->Version[0] != M4VIDEOEDITING_VERSION_MAJOR)
864        || (pAddedClipProperties->Version[1] != M4VIDEOEDITING_VERSION_MINOR)
865        || (pAddedClipProperties->Version[2]
866    != M4VIDEOEDITING_VERSION_REVISION) )
867    {
868        M4OSA_TRACE1_0(
869            "M4VSS3GPP_intAudioMixingCompatibility: The clip analysis has been generated\
870            by another version, returning M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION");
871        return M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION;
872    }
873
874    /********* input file type *********/
875
876    if( M4VIDEOEDITING_kFileType_3GPP != pInputClipProperties->FileType )
877    {
878        M4OSA_TRACE1_0(
879            "M4VSS3GPP_intAudioMixingCompatibility:\
880            returning M4VSS3GPP_ERR_INPUT_CLIP_IS_NOT_A_3GPP");
881        return M4VSS3GPP_ERR_INPUT_CLIP_IS_NOT_A_3GPP;
882    }
883
884    /********* input audio *********/
885
886    if( M4VIDEOEDITING_kNoneAudio != pInputClipProperties->
887        AudioStreamType ) /**< if there is an audio stream */
888    {
889        /**
890        * Check audio format is AMR-NB or AAC */
891        switch( pInputClipProperties->AudioStreamType )
892        {
893            case M4VIDEOEDITING_kAMR_NB:
894                pInputClipProperties->bAudioIsEditable = M4OSA_TRUE;
895                break;
896
897            case M4VIDEOEDITING_kAAC:
898            case M4VIDEOEDITING_kAACplus:
899            case M4VIDEOEDITING_keAACplus:
900                switch( pInputClipProperties->uiSamplingFrequency )
901                {
902                case 8000:
903                case 16000:
904                case 22050:
905                case 24000:
906                case 32000:
907                case 44100:
908                case 48000:
909                    pInputClipProperties->bAudioIsEditable = M4OSA_TRUE;
910                    break;
911
912                default:
913                    break;
914            }
915            bClip1IsAAC = M4OSA_TRUE;
916            break;
917          default:
918            break;
919        }
920    }
921    else
922    {
923        /* Silence is always editable */
924        pInputClipProperties->bAudioIsEditable = M4OSA_TRUE;
925    }
926
927    /********* added audio *********/
928
929    if( M4VIDEOEDITING_kNoneAudio != pAddedClipProperties->
930        AudioStreamType ) /**< if there is an audio stream */
931    {
932        /**
933        * Check audio format is AMR-NB or AAC */
934        switch( pAddedClipProperties->AudioStreamType )
935        {
936            case M4VIDEOEDITING_kAMR_NB:
937                pAddedClipProperties->bAudioIsEditable = M4OSA_TRUE;
938                pAddedClipProperties->bAudioIsCompatibleWithMasterClip =
939                    M4OSA_TRUE; /* I use this field to know if silence supported */
940                break;
941
942            case M4VIDEOEDITING_kAAC:
943            case M4VIDEOEDITING_kAACplus:
944            case M4VIDEOEDITING_keAACplus:
945                switch( pAddedClipProperties->uiSamplingFrequency )
946                {
947                case 8000:
948                case 16000:
949                case 22050:
950                case 24000:
951                case 32000:
952                case 44100:
953                case 48000:
954                    pAddedClipProperties->bAudioIsEditable = M4OSA_TRUE;
955                    break;
956
957                default:
958                    break;
959                }
960                pAddedClipProperties->bAudioIsCompatibleWithMasterClip =
961                    M4OSA_TRUE; /* I use this field to know if silence supported */
962                bClip2IsAAC = M4OSA_TRUE;
963                break;
964
965            case M4VIDEOEDITING_kEVRC:
966                break;
967
968            case M4VIDEOEDITING_kPCM:
969                pAddedClipProperties->bAudioIsEditable = M4OSA_TRUE;
970                pAddedClipProperties->bAudioIsCompatibleWithMasterClip =
971                    M4OSA_TRUE; /* I use this field to know if silence supported */
972
973                if( pAddedClipProperties->uiSamplingFrequency == 16000 )
974                {
975                    bClip2IsAAC = M4OSA_TRUE;
976                }
977                break;
978
979            case M4VIDEOEDITING_kMP3: /*RC*/
980                pAddedClipProperties->bAudioIsEditable = M4OSA_TRUE;
981                pAddedClipProperties->bAudioIsCompatibleWithMasterClip =
982                    M4OSA_TRUE; /* I use this field to know if silence supported */
983                break;
984
985            default:
986                /* The writer cannot write this  into a 3gpp */
987                M4OSA_TRACE1_0(
988                    "M4VSS3GPP_intAudioMixingCompatibility:\
989                    returning M4VSS3GPP_ERR_UNSUPPORTED_ADDED_AUDIO_STREAM");
990                return M4VSS3GPP_ERR_UNSUPPORTED_ADDED_AUDIO_STREAM;
991        }
992    }
993    else
994    {
995        /* Silence is always editable */
996        pAddedClipProperties->bAudioIsEditable = M4OSA_TRUE;
997        pAddedClipProperties->bAudioIsCompatibleWithMasterClip =
998            M4OSA_TRUE; /* I use this field to know if silence supported */
999    }
1000
1001    if( pC->bRemoveOriginal == M4OSA_FALSE )
1002    {
1003        if( pInputClipProperties->uiSamplingFrequency
1004            != pAddedClipProperties->uiSamplingFrequency )
1005        {
1006            /* We need to call SSRC in order to align ASF and/or nb of channels */
1007            /* Moreover, audio encoder may be needed in case of audio replacing... */
1008            pC->b_SSRCneeded = M4OSA_TRUE;
1009        }
1010
1011        if( pInputClipProperties->uiNbChannels
1012            < pAddedClipProperties->uiNbChannels )
1013        {
1014            /* Stereo to Mono */
1015            pC->ChannelConversion = 1;
1016        }
1017        else if( pInputClipProperties->uiNbChannels
1018            > pAddedClipProperties->uiNbChannels )
1019        {
1020            /* Mono to Stereo */
1021            pC->ChannelConversion = 2;
1022        }
1023    }
1024
1025    pInputClipProperties->bAudioIsCompatibleWithMasterClip = M4OSA_TRUE;
1026
1027    /**
1028    * Return with no error */
1029    M4OSA_TRACE3_0(
1030        "M4VSS3GPP_intAudioMixingCompatibility(): returning M4NO_ERROR");
1031    return M4NO_ERROR;
1032}
1033