• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
M4VSS3GPP_editAnalyseClip(M4OSA_Void * pClip,M4VIDEOEDITING_FileType FileType,M4VIDEOEDITING_ClipProperties * pClipProperties,M4OSA_FileReadPointer * pFileReadPtrFct)67 M4OSA_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  */
M4VSS3GPP_editCheckClipCompatibility(M4VIDEOEDITING_ClipProperties * pClip1Properties,M4VIDEOEDITING_ClipProperties * pClip2Properties)211 M4OSA_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 
250 audio_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 
333 analysis_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  */
M4VSS3GPP_intBuildAnalysis(M4VSS3GPP_ClipContext * pClipCtxt,M4VIDEOEDITING_ClipProperties * pClipProperties)356 M4OSA_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  */
M4VSS3GPP_intCheckClipCompatibleWithVssEditing(M4VIDEOEDITING_ClipProperties * pClipProperties)689 M4OSA_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  */
835 M4OSA_ERR
M4VSS3GPP_intAudioMixingCompatibility(M4VSS3GPP_InternalAudioMixingContext * pC,M4VIDEOEDITING_ClipProperties * pInputClipProperties,M4VIDEOEDITING_ClipProperties * pAddedClipProperties)836 M4VSS3GPP_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