M4PTO3GPP_API.c revision 32ed3f4dad00f8a65f7e6b38402c70d5341c57eb
1/*
2 * Copyright (C) 2004-2011 NXP Software
3 * Copyright (C) 2011 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17/**
18 ******************************************************************************
19 * @file    M4PTO3GPP_API.c
20 * @brief   Picture to 3gpp Service implementation.
21 * @note
22 ******************************************************************************
23*/
24
25/*16 bytes signature to be written in the generated 3gp files */
26#define M4PTO3GPP_SIGNATURE     "NXP-SW : PTO3GPP"
27
28/****************/
29/*** Includes ***/
30/****************/
31
32/**
33 *  Our header */
34#include "M4PTO3GPP_InternalTypes.h"
35#include "M4PTO3GPP_API.h"
36
37/**
38 *  Our errors */
39#include "M4PTO3GPP_ErrorCodes.h"
40
41#ifdef M4VSS_SUPPORT_ENCODER_MPEG4
42#include "VideoEditorVideoEncoder.h"
43#endif
44
45
46/**
47 *  OSAL headers */
48#include "M4OSA_Memory.h"       /* OSAL memory management */
49#include "M4OSA_Debug.h"        /* OSAL debug management */
50
51
52/************************/
53/*** Various Magicals ***/
54/************************/
55
56#define M4PTO3GPP_WRITER_AUDIO_STREAM_ID                1
57#define M4PTO3GPP_WRITER_VIDEO_STREAM_ID                2
58#define M4PTO3GPP_QUANTIZER_STEP                        4       /**< Quantizer step */
59#define M4PTO3GPP_WRITER_AUDIO_PROFILE_LEVEL            0xFF    /**< No specific profile and
60                                                                     level */
61#define M4PTO3GPP_WRITER_AUDIO_AMR_TIME_SCALE           8000    /**< AMR */
62#define M4PTO3GPP_BITRATE_REGULATION_CTS_PERIOD_IN_MS   500     /**< MAGICAL */
63#define M4PTO3GPP_MARGE_OF_FILE_SIZE                    25000   /**< MAGICAL */
64/**
65 ******************************************************************************
66 * define   AMR 12.2 kbps silence frame
67 ******************************************************************************
68*/
69#define M4PTO3GPP_AMR_AU_SILENCE_FRAME_122_SIZE     32
70#define M4PTO3GPP_AMR_AU_SILENCE_FRAME_122_DURATION 20
71const M4OSA_UInt8 M4PTO3GPP_AMR_AU_SILENCE_122_FRAME[M4PTO3GPP_AMR_AU_SILENCE_FRAME_122_SIZE]=
72{ 0x3C, 0x91, 0x17, 0x16, 0xBE, 0x66, 0x78, 0x00, 0x00, 0x01, 0xE7, 0xAF,
73  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
75
76#define M4PTO3GPP_AMR_AU_SILENCE_FRAME_048_SIZE     13
77#define M4PTO3GPP_AMR_AU_SILENCE_FRAME_048_DURATION 20
78const M4OSA_UInt8 M4PTO3GPP_AMR_AU_SILENCE_048_FRAME[M4PTO3GPP_AMR_AU_SILENCE_FRAME_048_SIZE] =
79{ 0x04, 0xFF, 0x18, 0xC7, 0xF0, 0x0D, 0x04, 0x33, 0xFF, 0xE0, 0x00, 0x00, 0x00 };
80
81/***************************/
82/*** "Private" functions ***/
83/***************************/
84static M4OSA_ERR M4PTO3GPP_Ready4Processing(M4PTO3GPP_InternalContext* pC);
85
86/****************************/
87/*** "External" functions ***/
88/****************************/
89extern M4OSA_ERR M4WRITER_3GP_getInterfaces(M4WRITER_OutputFileType* pType,
90                                            M4WRITER_GlobalInterface** SrcGlobalInterface,
91                                            M4WRITER_DataInterface** SrcDataInterface);
92extern M4OSA_ERR M4READER_AMR_getInterfaces(M4READER_MediaType *pMediaType,
93                                            M4READER_GlobalInterface **pRdrGlobalInterface,
94                                            M4READER_DataInterface **pRdrDataInterface);
95extern M4OSA_ERR M4READER_3GP_getInterfaces(M4READER_MediaType *pMediaType,
96                                            M4READER_GlobalInterface **pRdrGlobalInterface,
97                                            M4READER_DataInterface **pRdrDataInterface);
98
99/****************************/
100/*** "Static" functions ***/
101/****************************/
102static M4OSA_ERR M4PTO3GPP_writeAmrSilence122Frame(
103                                    M4WRITER_DataInterface* pWriterDataIntInterface,
104                                    M4WRITER_Context* pWriterContext,
105                                    M4SYS_AccessUnit* pWriterAudioAU,
106                                    M4OSA_Time mtIncCts);
107static M4OSA_ERR M4PTO3GPP_writeAmrSilence048Frame(
108                                   M4WRITER_DataInterface* pWriterDataIntInterface,
109                                   M4WRITER_Context* pWriterContext,
110                                   M4SYS_AccessUnit* pWriterAudioAU,
111                                   M4OSA_Time mtIncCts);
112/**
113 ******************************************************************************
114 * M4OSA_ERR M4PTO3GPP_GetVersion(M4_VersionInfo* pVersionInfo);
115 * @brief   Get the M4PTO3GPP version.
116 * @note    Can be called anytime. Do not need any context.
117 * @param   pVersionInfo        (OUT) Pointer to a version info structure
118 * @return  M4NO_ERROR:         No error
119 * @return  M4ERR_PARAMETER:    pVersionInfo is M4OSA_NULL (If Debug Level >= 2)
120 ******************************************************************************
121*/
122
123/*********************************************************/
124M4OSA_ERR M4PTO3GPP_GetVersion(M4_VersionInfo* pVersionInfo)
125/*********************************************************/
126{
127    M4OSA_TRACE3_1("M4PTO3GPP_GetVersion called with pVersionInfo=0x%x", pVersionInfo);
128
129    /**
130     *  Check input parameters */
131    M4OSA_DEBUG_IF2((M4OSA_NULL==pVersionInfo),M4ERR_PARAMETER,
132            "M4PTO3GPP_GetVersion: pVersionInfo is M4OSA_NULL");
133
134    pVersionInfo->m_major       = M4PTO3GPP_VERSION_MAJOR;
135    pVersionInfo->m_minor       = M4PTO3GPP_VERSION_MINOR;
136    pVersionInfo->m_revision    = M4PTO3GPP_VERSION_REVISION;
137
138    return M4NO_ERROR;
139}
140
141/**
142 ******************************************************************************
143 * M4OSA_ERR M4PTO3GPP_Init(M4PTO3GPP_Context* pContext);
144 * @brief   Initializes the M4PTO3GPP (allocates an execution context).
145 * @note
146 * @param   pContext            (OUT) Pointer on the M4PTO3GPP context to allocate
147 * @param   pFileReadPtrFct     (IN) Pointer to OSAL file reader functions
148 * @param   pFileWritePtrFct    (IN) Pointer to OSAL file writer functions
149 * @return  M4NO_ERROR:         No error
150 * @return  M4ERR_PARAMETER:    At least one parameter is M4OSA_NULL (If Debug Level >= 2)
151 * @return  M4ERR_ALLOC:        There is no more available memory
152 ******************************************************************************
153*/
154/*********************************************************/
155M4OSA_ERR M4PTO3GPP_Init(   M4PTO3GPP_Context* pContext,
156                            M4OSA_FileReadPointer* pFileReadPtrFct,
157                            M4OSA_FileWriterPointer* pFileWritePtrFct)
158/*********************************************************/
159{
160    M4PTO3GPP_InternalContext *pC;
161    M4OSA_UInt32 i;
162
163    M4OSA_TRACE3_1("M4PTO3GPP_Init called with pContext=0x%x", pContext);
164
165    /**
166     *  Check input parameters */
167    M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER,
168            "M4PTO3GPP_Init: pContext is M4OSA_NULL");
169
170    /**
171     *  Allocate the M4PTO3GPP context and return it to the user */
172    pC = (M4PTO3GPP_InternalContext*)M4OSA_malloc(sizeof(M4PTO3GPP_InternalContext), M4PTO3GPP,
173        (M4OSA_Char *)"M4PTO3GPP_InternalContext");
174    *pContext = pC;
175    if (M4OSA_NULL == pC)
176    {
177        M4OSA_TRACE1_0("M4PTO3GPP_Step(): unable to allocate M4PTO3GPP_InternalContext,\
178                       returning M4ERR_ALLOC");
179        return M4ERR_ALLOC;
180    }
181
182    /**
183     *  Init the context. All pointers must be initialized to M4OSA_NULL because CleanUp()
184        can be called just after Init(). */
185    pC->m_State = M4PTO3GPP_kState_CREATED;
186    pC->m_VideoState = M4PTO3GPP_kStreamState_NOSTREAM;
187    pC->m_AudioState = M4PTO3GPP_kStreamState_NOSTREAM;
188
189    /**
190     *  Reader stuff */
191    pC->m_pReaderAudioAU        = M4OSA_NULL;
192    pC->m_pReaderAudioStream    = M4OSA_NULL;
193
194    /**
195     *  Writer stuff */
196    pC->m_pEncoderHeader        = M4OSA_NULL;
197    pC->m_pWriterVideoStream    = M4OSA_NULL;
198    pC->m_pWriterAudioStream    = M4OSA_NULL;
199    pC->m_pWriterVideoStreamInfo= M4OSA_NULL;
200    pC->m_pWriterAudioStreamInfo= M4OSA_NULL;
201
202    /**
203     *  Contexts of the used modules  */
204    pC->m_pAudioReaderContext    = M4OSA_NULL;
205    pC->m_p3gpWriterContext  = M4OSA_NULL;
206    pC->m_pMp4EncoderContext = M4OSA_NULL;
207    pC->m_eEncoderState = M4PTO3GPP_kNoEncoder;
208
209    /**
210     *  Interfaces of the used modules */
211    pC->m_pReaderGlobInt    = M4OSA_NULL;
212    pC->m_pReaderDataInt    = M4OSA_NULL;
213    pC->m_pWriterGlobInt    = M4OSA_NULL;
214    pC->m_pWriterDataInt    = M4OSA_NULL;
215    pC->m_pEncoderInt       = M4OSA_NULL;
216    pC->m_pEncoderExternalAPI = M4OSA_NULL;
217    pC->m_pEncoderUserData = M4OSA_NULL;
218
219    /**
220     * Fill the OSAL file function set */
221    pC->pOsalFileRead = pFileReadPtrFct;
222    pC->pOsalFileWrite = pFileWritePtrFct;
223
224    /**
225     *  Video rate control stuff */
226    pC->m_mtCts             = 0.0F;
227    pC->m_mtNextCts         = 0.0F;
228    pC->m_mtAudioCts        = 0.0F;
229    pC->m_AudioOffSet       = 0.0F;
230    pC->m_dLastVideoRegulCts= 0.0F;
231    pC->m_PrevAudioCts      = 0.0F;
232    pC->m_DeltaAudioCts     = 0.0F;
233
234    pC->m_MaxFileSize       = 0;
235    pC->m_CurrentFileSize   = 0;
236
237    pC->m_IsLastPicture         = M4OSA_FALSE;
238    pC->m_bAudioPaddingSilence  = M4OSA_FALSE;
239    pC->m_bLastInternalCallBack = M4OSA_FALSE;
240    pC->m_NbCurrentFrame        = 0;
241
242    pC->pSavedPlane = M4OSA_NULL;
243    pC->uiSavedDuration = 0;
244
245    for (i=0; i<M4VE_kEncoderType_NB; i++)
246    {
247        pC->registeredExternalEncs[i].pEncoderInterface = M4OSA_NULL;
248        pC->registeredExternalEncs[i].pUserData = M4OSA_NULL;
249        pC->registeredExternalEncs[i].registered = M4OSA_FALSE;
250    }
251
252    M4OSA_TRACE3_0("M4PTO3GPP_Init(): returning M4NO_ERROR");
253    return M4NO_ERROR;
254}
255
256/**
257 ******************************************************************************
258 * M4OSA_ERR M4PTO3GPP_Open(M4PTO3GPP_Context pContext, M4PTO3GPP_Params* pParams);
259 * @brief   Set the M4PTO3GPP input and output files.
260 * @note    It opens the input file, but the output file may not be created yet.
261 * @param   pContext            (IN) M4PTO3GPP context
262 * @param   pParams             (IN) Pointer to the parameters for the PTO3GPP.
263 * @note    The pointed structure can be de-allocated after this function returns because
264 *          it is internally copied by the PTO3GPP
265 * @return  M4NO_ERROR:         No error
266 * @return  M4ERR_PARAMETER:    At least one parameter is M4OSA_NULL
267 * @return  M4ERR_STATE:        M4PTO3GPP is not in an appropriate state for this function to be
268                                 called
269 * @return  M4ERR_ALLOC:        There is no more available memory
270 * @return  ERR_PTO3GPP_INVALID_VIDEO_FRAME_SIZE_FOR_H263 The output video frame
271 *                              size parameter is incompatible with H263 encoding
272 * @return  ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_FORMAT       The output video format
273                                                            parameter is undefined
274 * @return  ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_BITRATE      The output video bit-rate parameter
275                                                            is undefined
276 * @return  ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE   The output video frame size parameter
277                                                            is undefined
278 * @return  ERR_PTO3GPP_UNDEFINED_OUTPUT_FILE_SIZE          The output file size parameter
279                                                            is undefined
280 * @return  ERR_PTO3GPP_UNDEFINED_AUDIO_PADDING             The output audio padding parameter
281                                                            is undefined
282 * @return  ERR_PTO3GPP_UNHANDLED_AUDIO_TRACK_INPUT_FILE    The input audio file contains
283                                                            a track format not handled by PTO3GPP
284 ******************************************************************************
285*/
286/*********************************************************/
287M4OSA_ERR M4PTO3GPP_Open(M4PTO3GPP_Context pContext, M4PTO3GPP_Params* pParams)
288/*********************************************************/
289{
290    M4PTO3GPP_InternalContext   *pC = (M4PTO3GPP_InternalContext*)(pContext);
291    M4OSA_ERR                   err = M4NO_ERROR;
292
293    M4READER_MediaFamily    mediaFamily;
294    M4_StreamHandler*       pStreamHandler;
295    M4READER_MediaType      readerMediaType;
296
297    M4OSA_TRACE2_2("M4PTO3GPP_Open called with pContext=0x%x, pParams=0x%x", pContext, pParams);
298
299    /**
300     *  Check input parameters */
301    M4OSA_DEBUG_IF2((M4OSA_NULL == pContext), M4ERR_PARAMETER, \
302                    "M4PTO3GPP_Open: pContext is M4OSA_NULL");
303    M4OSA_DEBUG_IF2((M4OSA_NULL == pParams),  M4ERR_PARAMETER, \
304                    "M4PTO3GPP_Open: pParams is M4OSA_NULL");
305
306    /**
307     *  Check parameters correctness */
308    M4OSA_DEBUG_IF2((M4OSA_NULL == pParams->pPictureCallbackFct),
309               M4ERR_PARAMETER, "M4PTO3GPP_Open: pC->m_Params.pPictureCallbackFct is M4OSA_NULL");
310    M4OSA_DEBUG_IF2((M4OSA_NULL == pParams->pPictureCallbackCtxt),
311                M4ERR_PARAMETER,
312                 "M4PTO3GPP_Open: pC->m_Params.pPictureCallbackCtxt is M4OSA_NULL");
313    M4OSA_DEBUG_IF2((M4OSA_NULL == pParams->pOutput3gppFile),
314                M4ERR_PARAMETER, "M4PTO3GPP_Open: pC->m_Params.pOutput3gppFile is M4OSA_NULL");
315    M4OSA_DEBUG_IF2((M4OSA_NULL == pParams->pTemporaryFile),
316                M4ERR_PARAMETER, "M4PTO3GPP_Open: pC->m_Params.pTemporaryFile is M4OSA_NULL");
317
318    /**
319     * Video Format */
320    if( (M4VIDEOEDITING_kH263 != pParams->OutputVideoFormat) &&
321        (M4VIDEOEDITING_kMPEG4 != pParams->OutputVideoFormat) &&
322        (M4VIDEOEDITING_kMPEG4_EMP != pParams->OutputVideoFormat) &&
323        (M4VIDEOEDITING_kH264 != pParams->OutputVideoFormat))
324    {
325        M4OSA_TRACE1_0("M4PTO3GPP_Open: Undefined output video format");
326        return ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_FORMAT;
327     }
328
329     /**
330     * Video Bitrate */
331    if(!((M4VIDEOEDITING_k16_KBPS       == pParams->OutputVideoBitrate) ||
332         (M4VIDEOEDITING_k24_KBPS       == pParams->OutputVideoBitrate) ||
333         (M4VIDEOEDITING_k32_KBPS       == pParams->OutputVideoBitrate) ||
334         (M4VIDEOEDITING_k48_KBPS       == pParams->OutputVideoBitrate) ||
335         (M4VIDEOEDITING_k64_KBPS       == pParams->OutputVideoBitrate) ||
336         (M4VIDEOEDITING_k96_KBPS       == pParams->OutputVideoBitrate) ||
337         (M4VIDEOEDITING_k128_KBPS      == pParams->OutputVideoBitrate) ||
338         (M4VIDEOEDITING_k192_KBPS      == pParams->OutputVideoBitrate) ||
339         (M4VIDEOEDITING_k256_KBPS      == pParams->OutputVideoBitrate) ||
340         (M4VIDEOEDITING_k288_KBPS      == pParams->OutputVideoBitrate) ||
341         (M4VIDEOEDITING_k384_KBPS      == pParams->OutputVideoBitrate) ||
342         (M4VIDEOEDITING_k512_KBPS      == pParams->OutputVideoBitrate) ||
343         (M4VIDEOEDITING_k800_KBPS      == pParams->OutputVideoBitrate) ||
344         /*+ New Encoder bitrates */
345         (M4VIDEOEDITING_k2_MBPS        == pParams->OutputVideoBitrate) ||
346         (M4VIDEOEDITING_k5_MBPS        == pParams->OutputVideoBitrate) ||
347         (M4VIDEOEDITING_k8_MBPS        == pParams->OutputVideoBitrate) ||
348         (M4VIDEOEDITING_kVARIABLE_KBPS == pParams->OutputVideoBitrate)))
349    {
350        M4OSA_TRACE1_0("M4PTO3GPP_Open: Undefined output video bitrate");
351        return ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_BITRATE;
352    }
353
354    /**
355     * Video frame size */
356    if (!((M4VIDEOEDITING_kSQCIF == pParams->OutputVideoFrameSize) ||
357          (M4VIDEOEDITING_kQQVGA == pParams->OutputVideoFrameSize) ||
358          (M4VIDEOEDITING_kQCIF == pParams->OutputVideoFrameSize) ||
359          (M4VIDEOEDITING_kQVGA == pParams->OutputVideoFrameSize) ||
360          (M4VIDEOEDITING_kCIF  == pParams->OutputVideoFrameSize) ||
361          (M4VIDEOEDITING_kVGA  == pParams->OutputVideoFrameSize) ||
362
363          (M4VIDEOEDITING_kNTSC == pParams->OutputVideoFrameSize) ||
364          (M4VIDEOEDITING_kWVGA == pParams->OutputVideoFrameSize) ||
365
366          (M4VIDEOEDITING_k640_360 == pParams->OutputVideoFrameSize) ||
367          (M4VIDEOEDITING_k854_480 == pParams->OutputVideoFrameSize) ||
368          (M4VIDEOEDITING_kHD1280  == pParams->OutputVideoFrameSize) ||
369          (M4VIDEOEDITING_kHD1080  == pParams->OutputVideoFrameSize) ||
370          (M4VIDEOEDITING_kHD960   == pParams->OutputVideoFrameSize)))
371
372    {
373        M4OSA_TRACE1_0("M4PTO3GPP_Open: Undefined output video frame size");
374        return ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE;
375    }
376
377    /**
378     * Maximum size of the output 3GPP file */
379    if (!((M4PTO3GPP_k50_KB     == pParams->OutputFileMaxSize) ||
380          (M4PTO3GPP_k75_KB     == pParams->OutputFileMaxSize) ||
381          (M4PTO3GPP_k100_KB    == pParams->OutputFileMaxSize) ||
382          (M4PTO3GPP_k150_KB    == pParams->OutputFileMaxSize) ||
383          (M4PTO3GPP_k200_KB    == pParams->OutputFileMaxSize) ||
384          (M4PTO3GPP_k300_KB    == pParams->OutputFileMaxSize) ||
385          (M4PTO3GPP_k400_KB    == pParams->OutputFileMaxSize) ||
386          (M4PTO3GPP_k500_KB    == pParams->OutputFileMaxSize) ||
387          (M4PTO3GPP_kUNLIMITED == pParams->OutputFileMaxSize)))
388
389    {
390        M4OSA_TRACE1_0("M4PTO3GPP_Open: Undefined output 3GPP file size");
391        return ERR_PTO3GPP_UNDEFINED_OUTPUT_FILE_SIZE;
392    }
393
394    /* Audio padding */
395    if (M4OSA_NULL != pParams->pInputAudioTrackFile)
396    {
397        if ((!( (M4PTO3GPP_kAudioPaddingMode_None   == pParams->AudioPaddingMode) ||
398                (M4PTO3GPP_kAudioPaddingMode_Silence== pParams->AudioPaddingMode) ||
399                (M4PTO3GPP_kAudioPaddingMode_Loop   == pParams->AudioPaddingMode))))
400        {
401            M4OSA_TRACE1_0("M4PTO3GPP_Open: Undefined audio padding");
402            return ERR_PTO3GPP_UNDEFINED_AUDIO_PADDING;
403        }
404    }
405
406    /**< Size check for H263 (only valid sizes are CIF, QCIF and SQCIF) */
407    if ((M4VIDEOEDITING_kH263 == pParams->OutputVideoFormat) &&
408        (M4VIDEOEDITING_kSQCIF != pParams->OutputVideoFrameSize) &&
409        (M4VIDEOEDITING_kQCIF != pParams->OutputVideoFrameSize) &&
410        (M4VIDEOEDITING_kCIF != pParams->OutputVideoFrameSize))
411    {
412        M4OSA_TRACE1_0("M4PTO3GPP_Open():\
413             returning ERR_PTO3GPP_INVALID_VIDEO_FRAME_SIZE_FOR_H263");
414        return ERR_PTO3GPP_INVALID_VIDEO_FRAME_SIZE_FOR_H263;
415    }
416
417    /**
418     *  Check state automaton */
419    if (M4PTO3GPP_kState_CREATED != pC->m_State)
420    {
421        M4OSA_TRACE1_1("M4PTO3GPP_Open(): Wrong State (%d), returning M4ERR_STATE", pC->m_State);
422        return M4ERR_STATE;
423    }
424
425    /**
426     * Copy the M4PTO3GPP_Params structure */
427    memcpy((void *)(&pC->m_Params),
428                (void *)pParams, sizeof(M4PTO3GPP_Params));
429    M4OSA_TRACE1_1("M4PTO3GPP_Open: outputVideoBitrate = %d", pC->m_Params.OutputVideoBitrate);
430
431    /***********************************/
432    /* Open input file with the reader */
433    /***********************************/
434    if (M4OSA_NULL != pC->m_Params.pInputAudioTrackFile)
435    {
436        /**
437         * Get the reader interface according to the input audio file type */
438        switch(pC->m_Params.AudioFileFormat)
439        {
440#ifdef M4VSS_SUPPORT_READER_AMR
441        case M4VIDEOEDITING_kFileType_AMR:
442        err = M4READER_AMR_getInterfaces( &readerMediaType, &pC->m_pReaderGlobInt,
443                &pC->m_pReaderDataInt);
444        if (M4NO_ERROR != err)
445        {
446            M4OSA_TRACE1_1("M4PTO3GPP_Open(): M4READER_AMR_getInterfaces returns 0x%x", err);
447            return err;
448        }
449            break;
450#endif
451
452#ifdef AAC_SUPPORTED
453        case M4VIDEOEDITING_kFileType_3GPP:
454            err = M4READER_3GP_getInterfaces( &readerMediaType, &pC->m_pReaderGlobInt,
455                    &pC->m_pReaderDataInt);
456            if (M4NO_ERROR != err)
457            {
458                M4OSA_TRACE1_1("M4PTO3GPP_Open(): M4READER_3GP_getInterfaces returns 0x%x", err);
459                return err;
460            }
461            break;
462#endif
463
464        default:
465            return ERR_PTO3GPP_UNHANDLED_AUDIO_TRACK_INPUT_FILE;
466        }
467
468        /**
469         *  Initializes the reader shell */
470        err = pC->m_pReaderGlobInt->m_pFctCreate(&pC->m_pAudioReaderContext);
471        if (M4NO_ERROR != err)
472        {
473            M4OSA_TRACE1_1("M4PTO3GPP_Open(): pReaderGlobInt->m_pFctCreate returns 0x%x", err);
474            return err;
475        }
476
477        pC->m_pReaderDataInt->m_readerContext = pC->m_pAudioReaderContext;
478        /**< Link the reader interface to the reader context */
479
480        /**
481         *  Set the reader shell file access functions */
482        err = pC->m_pReaderGlobInt->m_pFctSetOption(pC->m_pAudioReaderContext,
483            M4READER_kOptionID_SetOsaFileReaderFctsPtr,  (M4OSA_DataOption)pC->pOsalFileRead);
484        if (M4NO_ERROR != err)
485        {
486            M4OSA_TRACE1_1("M4PTO3GPP_Open(): pReaderGlobInt->m_pFctSetOption returns 0x%x", err);
487            return err;
488        }
489
490        /**
491         *  Open the input audio file */
492        err = pC->m_pReaderGlobInt->m_pFctOpen(pC->m_pAudioReaderContext,
493            pC->m_Params.pInputAudioTrackFile);
494        if (M4NO_ERROR != err)
495        {
496            M4OSA_TRACE1_1("M4PTO3GPP_Open(): pReaderGlobInt->m_pFctOpen returns 0x%x", err);
497            pC->m_pReaderGlobInt->m_pFctDestroy(pC->m_pAudioReaderContext);
498            pC->m_pAudioReaderContext = M4OSA_NULL;
499            return err;
500        }
501
502        /**
503         *  Get the audio streams from the input file */
504        err = M4NO_ERROR;
505        while (M4NO_ERROR == err)
506        {
507            err = pC->m_pReaderGlobInt->m_pFctGetNextStream(pC->m_pAudioReaderContext,
508                &mediaFamily, &pStreamHandler);
509
510            if((err == ((M4OSA_UInt32)M4ERR_READER_UNKNOWN_STREAM_TYPE)) ||
511                   (err == ((M4OSA_UInt32)M4WAR_TOO_MUCH_STREAMS)))
512            {
513                err = M4NO_ERROR;
514                continue;
515            }
516
517            if (M4NO_ERROR == err) /**< One stream found */
518            {
519                /**< Found an audio stream */
520                if ((M4READER_kMediaFamilyAudio == mediaFamily)
521                    && (M4OSA_NULL == pC->m_pReaderAudioStream))
522                {
523                    pC->m_pReaderAudioStream = (M4_AudioStreamHandler*)pStreamHandler;
524                    /**< Keep pointer to the audio stream */
525                    M4OSA_TRACE3_0("M4PTO3GPP_Open(): Found an audio stream in input");
526                    pStreamHandler->m_bStreamIsOK = M4OSA_TRUE;
527
528                    /**
529                     *  Allocate audio AU used for read operations */
530                    pC->m_pReaderAudioAU = (M4_AccessUnit*)M4OSA_malloc(sizeof(M4_AccessUnit),
531                        M4PTO3GPP,(M4OSA_Char *)"pReaderAudioAU");
532                    if (M4OSA_NULL == pC->m_pReaderAudioAU)
533                    {
534                        M4OSA_TRACE1_0("M4PTO3GPP_Open(): unable to allocate pReaderAudioAU, \
535                                       returning M4ERR_ALLOC");
536                        return M4ERR_ALLOC;
537                    }
538
539                    /**
540                     *  Initializes an access Unit */
541                    err = pC->m_pReaderGlobInt->m_pFctFillAuStruct(pC->m_pAudioReaderContext,
542                            pStreamHandler, pC->m_pReaderAudioAU);
543                    if (M4NO_ERROR != err)
544                    {
545                        M4OSA_TRACE1_1("M4PTO3GPP_Open():\
546                         pReaderGlobInt->m_pFctFillAuStruct(audio)returns 0x%x", err);
547                        return err;
548                    }
549                }
550                else
551                {
552                    pStreamHandler->m_bStreamIsOK = M4OSA_FALSE;
553                }
554            }
555            else if (M4WAR_NO_MORE_STREAM != err) /**< Unexpected error code */
556            {
557                M4OSA_TRACE1_1("M4PTO3GPP_Open():\
558                     pReaderGlobInt->m_pFctGetNextStream returns 0x%x",
559                    err);
560                return err;
561            }
562        } /* while*/
563    } /*if (M4OSA_NULL != pC->m_Params.pInputAudioTrackFile)*/
564
565    pC->m_VideoState = M4PTO3GPP_kStreamState_STARTED;
566
567    /**
568     * Init the audio stream */
569    if (M4OSA_NULL != pC->m_pReaderAudioStream)
570    {
571        pC->m_AudioState = M4PTO3GPP_kStreamState_STARTED;
572        err = pC->m_pReaderGlobInt->m_pFctReset(pC->m_pAudioReaderContext,
573            (M4_StreamHandler*)pC->m_pReaderAudioStream);
574        if (M4NO_ERROR != err)
575        {
576            M4OSA_TRACE1_1("M4PTO3GPP_Open(): pReaderDataInt->m_pFctReset(audio returns 0x%x",
577                 err);
578            return err;
579        }
580    }
581
582    /**
583     *  Update state automaton */
584    pC->m_State = M4PTO3GPP_kState_OPENED;
585
586    /**
587     * Get the max File size */
588    switch(pC->m_Params.OutputFileMaxSize)
589    {
590    case M4PTO3GPP_k50_KB:  pC->m_MaxFileSize = 50000;  break;
591    case M4PTO3GPP_k75_KB:  pC->m_MaxFileSize = 75000;  break;
592    case M4PTO3GPP_k100_KB: pC->m_MaxFileSize = 100000; break;
593    case M4PTO3GPP_k150_KB: pC->m_MaxFileSize = 150000; break;
594    case M4PTO3GPP_k200_KB: pC->m_MaxFileSize = 200000; break;
595    case M4PTO3GPP_k300_KB: pC->m_MaxFileSize = 300000; break;
596    case M4PTO3GPP_k400_KB: pC->m_MaxFileSize = 400000; break;
597    case M4PTO3GPP_k500_KB: pC->m_MaxFileSize = 500000; break;
598    case M4PTO3GPP_kUNLIMITED:
599    default:                                            break;
600    }
601
602    M4OSA_TRACE3_0("M4PTO3GPP_Open(): returning M4NO_ERROR");
603    return M4NO_ERROR;
604}
605
606/**
607 ******************************************************************************
608 * M4OSA_ERR M4PTO3GPP_Step(M4PTO3GPP_Context pContext);
609 * @brief   Perform one step of trancoding.
610 * @note
611 * @param   pContext            (IN) M4PTO3GPP context
612 * @return  M4NO_ERROR          No error
613 * @return  M4ERR_PARAMETER     pContext is M4OSA_NULL
614 * @return  M4ERR_STATE:    M4PTO3GPP is not in an appropriate state for this function
615 *                           to be called
616 * @return  M4PTO3GPP_WAR_END_OF_PROCESSING Encoding completed
617 ******************************************************************************
618*/
619/*********************************************************/
620M4OSA_ERR M4PTO3GPP_Step(M4PTO3GPP_Context pContext)
621/*********************************************************/
622{
623    M4PTO3GPP_InternalContext *pC = (M4PTO3GPP_InternalContext*)(pContext);
624    M4OSA_ERR err = M4NO_ERROR;
625    M4OSA_UInt32 l_uiAudioStepCount = 0;
626    M4OSA_Int32  JumpToTime = 0;
627    M4OSA_Time  mtIncCts;
628
629    /**
630     *  Check input parameters */
631    M4OSA_DEBUG_IF2((M4OSA_NULL==pContext), M4ERR_PARAMETER,
632                "M4PTO3GPP_Step: pContext is M4OSA_NULL");
633
634    /**
635     *  Check state automaton */
636    if ( !((M4PTO3GPP_kState_OPENED == pC->m_State) || (M4PTO3GPP_kState_READY == pC->m_State)) )
637    {
638        M4OSA_TRACE1_1("M4PTO3GPP_Step(): Wrong State (%d), returning M4ERR_STATE", pC->m_State);
639        return M4ERR_STATE;
640    }
641
642    /******************************************************************/
643    /**
644     *  In case this is the first step, we prepare the decoder, the encoder and the writer */
645    if (M4PTO3GPP_kState_OPENED == pC->m_State)
646    {
647        M4OSA_TRACE2_0("M4PTO3GPP_Step(): This is the first step, \
648                       calling M4PTO3GPP_Ready4Processing");
649
650        /**
651         *  Prepare the reader, the decoder, the encoder, the writer... */
652        err = M4PTO3GPP_Ready4Processing(pC);
653        if (M4NO_ERROR != err)
654        {
655            M4OSA_TRACE1_1("M4PTO3GPP_Step(): M4PTO3GPP_Ready4Processing() returns 0x%x", err);
656            return err;
657        }
658
659        /**
660         *  Update state automaton */
661        pC->m_State = M4PTO3GPP_kState_READY;
662
663        M4OSA_TRACE3_0("M4PTO3GPP_Step(): returning M4NO_ERROR (a)");
664        return M4NO_ERROR; /**< we only do that in the first step, \
665                           first REAL step will be the next one */
666    }
667
668
669    /*
670     * Check if we reached the targeted file size.
671     * We do that before the encoding, because the core encoder has to know if this is
672     * the last frame to encode */
673    err = pC->m_pWriterGlobInt->pFctGetOption(pC->m_p3gpWriterContext,
674        M4WRITER_kFileSizeAudioEstimated, (M4OSA_DataOption) &pC->m_CurrentFileSize);
675    if ((0 != pC->m_MaxFileSize) &&
676        /**< Add a marge to the file size in order to never exceed the max file size */
677       ((pC->m_CurrentFileSize + M4PTO3GPP_MARGE_OF_FILE_SIZE) >= pC->m_MaxFileSize))
678    {
679        pC->m_IsLastPicture = M4OSA_TRUE;
680    }
681
682    /******************************************************************
683    *  At that point we are in M4PTO3GPP_kState_READY state
684    *  We perform one step of video encoding
685    ******************************************************************/
686
687    /************* VIDEO ENCODING ***************/
688    if (M4PTO3GPP_kStreamState_STARTED == pC->m_VideoState) /**<If the video encoding is going on*/
689    {   /**
690         * Call the encoder  */
691        pC->m_NbCurrentFrame++;
692
693        /* Check if it is the last frame the to encode */
694        if((pC->m_Params.NbVideoFrames > 0) \
695            && (pC->m_NbCurrentFrame >= pC->m_Params.NbVideoFrames))
696        {
697            pC->m_IsLastPicture = M4OSA_TRUE;
698        }
699
700        M4OSA_TRACE2_2("M4PTO3GPP_Step(): Calling pEncoderInt->pFctEncode with videoCts = %.2f\
701                       nb = %lu", pC->m_mtCts, pC->m_NbCurrentFrame);
702
703        err = pC->m_pEncoderInt->pFctEncode(pC->m_pMp4EncoderContext, M4OSA_NULL,
704            /**< The input plane is null because the input Picture will be obtained by the\
705            VPP filter from the context */
706                                        pC->m_mtCts,
707                                        (pC->m_IsLastPicture ?
708                                        M4ENCODER_kLastFrame : M4ENCODER_kNormalFrame) );
709        /**< Last param set to M4OSA_TRUE signals that this is the last frame to be encoded,\
710        M4OSA_FALSE else */
711
712        M4OSA_TRACE3_2("M4PTO3GPP_Step(): pEncoderInt->pFctEncode returns 0x%x, vidFormat =0x%x",
713            err, pC->m_Params.OutputVideoFormat);
714        if((M4NO_ERROR == err) && (M4VIDEOEDITING_kH264 == pC->m_Params.OutputVideoFormat))
715        {
716            /* Check if last frame.*
717            *                  */
718            if(M4OSA_TRUE == pC->m_IsLastPicture)
719            {
720                M4OSA_TRACE3_0("M4PTO3GPP_Step(): Last picture");
721                pC->m_VideoState = M4PTO3GPP_kStreamState_FINISHED;
722            }
723
724        }
725
726        if (M4WAR_NO_MORE_AU == err) /**< The video encoding is finished */
727        {
728            M4OSA_TRACE3_0("M4PTO3GPP_Step(): pEncoderInt->pFctEncode returns M4WAR_NO_MORE_AU");
729            pC->m_VideoState = M4PTO3GPP_kStreamState_FINISHED;
730        }
731        else if (M4NO_ERROR != err)     /**< Unexpected error code */
732        {
733            if( (((M4OSA_UInt32)M4WAR_WRITER_STOP_REQ) == err) ||
734                    (((M4OSA_UInt32)M4ERR_ALLOC) == err) )
735            {
736                M4OSA_TRACE1_0("M4PTO3GPP_Step: returning ERR_PTO3GPP_ENCODER_ACCES_UNIT_ERROR");
737                return ERR_PTO3GPP_ENCODER_ACCES_UNIT_ERROR;
738            }
739            else
740            {
741                M4OSA_TRACE1_1("M4PTO3GPP_Step(): pEncoderInt->pFctEncode(last) (a) returns 0x%x",
742                    err);
743                return err;
744            }
745        }
746    } /**< End of video encoding */
747
748
749    /****** AUDIO TRANSCODING (read + null encoding + write) ******/
750    if (M4PTO3GPP_kStreamState_STARTED == pC->m_AudioState)
751    {
752        while ( (M4PTO3GPP_kStreamState_STARTED == pC->m_AudioState) &&
753                (pC->m_mtAudioCts < pC->m_mtNextCts))
754
755        {
756            l_uiAudioStepCount++;
757            if (M4OSA_FALSE == pC->m_bAudioPaddingSilence)
758            {
759                /**< Read the next audio AU in the input Audio file */
760                err = pC->m_pReaderDataInt->m_pFctGetNextAu(pC->m_pAudioReaderContext,
761                    (M4_StreamHandler*)pC->m_pReaderAudioStream, pC->m_pReaderAudioAU);
762                pC->m_mtAudioCts = pC->m_pReaderAudioAU->m_CTS + pC->m_AudioOffSet;
763
764                if (M4WAR_NO_MORE_AU == err)    /* The audio transcoding is finished */
765                {
766                    M4OSA_TRACE2_0("M4PTO3GPP_Step():\
767                                  pReaderDataInt->m_pFctGetNextAu(audio) returns \
768                                    M4WAR_NO_MORE_AU");
769                    switch(pC->m_Params.AudioPaddingMode)
770                    {
771                        case M4PTO3GPP_kAudioPaddingMode_None:
772
773                            pC->m_AudioState = M4PTO3GPP_kStreamState_FINISHED;
774                            break;
775
776                        case M4PTO3GPP_kAudioPaddingMode_Silence:
777
778                            if (M4DA_StreamTypeAudioAmrNarrowBand
779                                != pC->m_pReaderAudioStream->m_basicProperties.m_streamType)
780                                /**< Do nothing if the input audio file format is not AMR */
781                            {
782                                pC->m_AudioState = M4PTO3GPP_kStreamState_FINISHED;
783                            }
784                            else
785                            {
786                                pC->m_bAudioPaddingSilence = M4OSA_TRUE;
787                            }
788                            break;
789
790                        case M4PTO3GPP_kAudioPaddingMode_Loop:
791
792                            /**< Jump to the beginning of the audio file */
793                            err = pC->m_pReaderGlobInt->m_pFctJump(pC->m_pAudioReaderContext,
794                                (M4_StreamHandler*)pC->m_pReaderAudioStream, &JumpToTime);
795
796                            if (M4NO_ERROR != err)
797                            {
798                                M4OSA_TRACE1_1("M4PTO3GPP_Step(): \
799                                              pReaderDataInt->m_pFctReset(audio returns 0x%x",
800                                               err);
801                                return err;
802                            }
803
804                            if (M4DA_StreamTypeAudioAmrNarrowBand
805                                == pC->m_pReaderAudioStream->m_basicProperties.m_streamType)
806                            {
807                                pC->m_mtAudioCts += 20; /*< SEMC bug fixed at Lund */
808                                pC->m_AudioOffSet = pC->m_mtAudioCts;
809
810                                /**
811                                 * 'BZZZ' bug fix:
812                                 * add a silence frame */
813                                mtIncCts = (M4OSA_Time)((pC->m_mtAudioCts) *
814                                    (pC->m_pWriterAudioStream->timeScale / 1000.0));
815                                err = M4PTO3GPP_writeAmrSilence122Frame(pC->m_pWriterDataInt,
816                                    pC->m_p3gpWriterContext, &pC->m_WriterAudioAU, mtIncCts);
817
818                                if (M4NO_ERROR != err)
819                                {
820                                    M4OSA_TRACE1_1("M4PTO3GPP_Step(): \
821                                                   M4PTO3GPP_AddAmrSilenceSid returns 0x%x", err);
822                                    return err;
823                                }/**< Add => no audio cts increment...*/
824                            }
825                            else
826                            {
827                                pC->m_AudioOffSet = pC->m_mtAudioCts + pC->m_DeltaAudioCts;
828                            }
829                            break;
830                    } /* end of: switch */
831                }
832                else if (M4NO_ERROR != err)
833                {
834                    M4OSA_TRACE1_1("M4PTO3GPP_Step(): pReaderDataInt->m_pFctGetNextAu(Audio)\
835                                   returns 0x%x", err);
836                    return err;
837                }
838                else
839                {
840                    /**
841                     * Save the delta Cts (AAC only) */
842                    pC->m_DeltaAudioCts = pC->m_pReaderAudioAU->m_CTS - pC->m_PrevAudioCts;
843                    pC->m_PrevAudioCts  = pC->m_pReaderAudioAU->m_CTS;
844
845                    /**
846                     *  Prepare the writer AU */
847                    err = pC->m_pWriterDataInt->pStartAU(pC->m_p3gpWriterContext, 1,
848                        &pC->m_WriterAudioAU);
849                    if (M4NO_ERROR != err)
850                    {
851                        M4OSA_TRACE1_1("M4PTO3GPP_Step(): pWriterDataInt->pStartAU(Audio)\
852                                       returns 0x%x", err);
853                        return err;
854                    }
855
856                    /**
857                     *  Copy audio data from reader AU to writer AU */
858                    M4OSA_TRACE2_1("M4PTO3GPP_Step(): Copying audio AU: size=%d",
859                        pC->m_pReaderAudioAU->m_size);
860                    memcpy((void *)pC->m_WriterAudioAU.dataAddress,
861                        (void *)pC->m_pReaderAudioAU->m_dataAddress,
862                        pC->m_pReaderAudioAU->m_size);
863                    pC->m_WriterAudioAU.size = pC->m_pReaderAudioAU->m_size;
864
865                    /**
866                     *  Convert CTS unit from milliseconds to timescale */
867                    if (M4DA_StreamTypeAudioAmrNarrowBand
868                        != pC->m_pReaderAudioStream->m_basicProperties.m_streamType)
869                    {
870                        pC->m_WriterAudioAU.CTS  = (M4OSA_Time)
871                            ((pC->m_AudioOffSet + pC->m_pReaderAudioAU->m_CTS)
872                            * pC->m_pWriterAudioStream->timeScale / 1000.0);
873                    }
874                    else
875                    {
876                        pC->m_WriterAudioAU.CTS = (M4OSA_Time)(pC->m_mtAudioCts *
877                            (pC->m_pWriterAudioStream->timeScale / 1000.0));
878                    }
879                    pC->m_WriterAudioAU.nbFrag = 0;
880                    M4OSA_TRACE2_1("M4PTO3GPP_Step(): audio AU: CTS=%d ms", pC->m_mtAudioCts
881                        /*pC->m_pReaderAudioAU->m_CTS*/);
882
883                    /**
884                     *  Write it to the output file */
885                    err = pC->m_pWriterDataInt->pProcessAU(pC->m_p3gpWriterContext, 1,
886                        &pC->m_WriterAudioAU);
887
888                    if (M4NO_ERROR != err)
889                    {
890                        M4OSA_TRACE1_1("M4PTO3GPP_Step(): pWriterDataInt->pProcessAU(Audio)\
891                                       returns 0x%x", err);
892                        return err;
893                    }
894                }
895            }
896            else /**< M4OSA_TRUE == pC->m_bAudioPaddingSilence */
897            {
898                if (M4DA_StreamTypeAudioAmrNarrowBand ==
899                    pC->m_pReaderAudioStream->m_basicProperties.m_streamType)
900                {
901                    /**
902                     * Fill in audio au with silence */
903                    pC->m_mtAudioCts += 20;
904
905                    /**
906                     * Padd with silence */
907                    mtIncCts = (M4OSA_Time)(pC->m_mtAudioCts
908                        * (pC->m_pWriterAudioStream->timeScale / 1000.0));
909                    err = M4PTO3GPP_writeAmrSilence048Frame(pC->m_pWriterDataInt,
910                        pC->m_p3gpWriterContext, &pC->m_WriterAudioAU, mtIncCts);
911
912                    if (M4NO_ERROR != err)
913                    {
914                        M4OSA_TRACE1_1("M4PTO3GPP_Step(): M4PTO3GPP_AddAmrSilenceSid returns 0x%x",
915                            err);
916                        return err;
917                    }
918                }
919                else /**< Do nothing if the input audio file format is not AMR */
920                {
921                    pC->m_AudioState = M4PTO3GPP_kStreamState_FINISHED;
922                }
923
924            }
925        } /**< while */
926    } /**< End of audio encoding */
927
928    pC->m_mtCts = pC->m_mtNextCts;
929
930    /**
931     *  The transcoding is finished when no stream is being encoded anymore */
932    if (M4PTO3GPP_kStreamState_FINISHED == pC->m_VideoState)
933    {
934        pC->m_State = M4PTO3GPP_kState_FINISHED;
935        M4OSA_TRACE2_0("M4PTO3GPP_Step(): transcoding finished, returning M4WAR_NO_MORE_AU");
936        return M4PTO3GPP_WAR_END_OF_PROCESSING;
937    }
938
939    M4OSA_TRACE3_0("M4PTO3GPP_Step(): returning M4NO_ERROR (b)");
940    return M4NO_ERROR;
941}
942
943/**
944 ******************************************************************************
945 * M4OSA_ERR M4PTO3GPP_Close(M4PTO3GPP_Context pContext);
946 * @brief   Finish the M4PTO3GPP transcoding.
947 * @note    The output 3GPP file is ready to be played after this call
948 * @param   pContext            (IN) M4PTO3GPP context
949 * @return  M4NO_ERROR:         No error
950 * @return  M4ERR_PARAMETER:    pContext is M4OSA_NULL (If Debug Level >= 2)
951 * @return  M4ERR_STATE:    M4PTO3GPP is not in an appropriate state for this function to be called
952 ******************************************************************************
953*/
954/*********************************************************/
955M4OSA_ERR M4PTO3GPP_Close(M4PTO3GPP_Context pContext)
956/*********************************************************/
957{
958    M4PTO3GPP_InternalContext *pC = (M4PTO3GPP_InternalContext*)(pContext);
959    M4OSA_ERR    osaErr = M4NO_ERROR;
960    M4OSA_UInt32 lastCTS;
961    M4ENCODER_Header* encHeader;
962    M4SYS_StreamIDmemAddr streamHeader;
963
964    M4OSA_TRACE3_1("M4PTO3GPP_Close called with pContext=0x%x", pContext);
965
966    /**
967     *  Check input parameters */
968    M4OSA_DEBUG_IF2((M4OSA_NULL==pContext), M4ERR_PARAMETER, "M4PTO3GPP_Close:\
969                                                             pContext is M4OSA_NULL");
970
971    /* Check state automaton */
972    if ((pC->m_State != M4PTO3GPP_kState_OPENED) &&
973        (pC->m_State != M4PTO3GPP_kState_READY) &&
974        (pC->m_State != M4PTO3GPP_kState_FINISHED))
975    {
976        M4OSA_TRACE1_1("M4PTO3GPP_Close(): Wrong State (%d), returning M4ERR_STATE", pC->m_State);
977        return M4ERR_STATE;
978    }
979
980    /*************************************/
981    /******** Finish the encoding ********/
982    /*************************************/
983    if (M4PTO3GPP_kState_READY == pC->m_State)
984    {
985        pC->m_State = M4PTO3GPP_kState_FINISHED;
986    }
987
988    if (M4PTO3GPP_kEncoderRunning == pC->m_eEncoderState)
989    {
990        if (pC->m_pEncoderInt->pFctStop != M4OSA_NULL)
991        {
992            osaErr = pC->m_pEncoderInt->pFctStop(pC->m_pMp4EncoderContext);
993            if (M4NO_ERROR != osaErr)
994            {
995                M4OSA_TRACE1_1("M4PTO3GPP_close: m_pEncoderInt->pFctStop returns 0x%x", osaErr);
996                /* Well... how the heck do you handle a failed cleanup? */
997            }
998        }
999
1000        pC->m_eEncoderState = M4PTO3GPP_kEncoderStopped;
1001    }
1002
1003    /* Has the encoder actually been opened? Don't close it if that's not the case. */
1004    if (M4PTO3GPP_kEncoderStopped == pC->m_eEncoderState)
1005    {
1006        osaErr = pC->m_pEncoderInt->pFctClose(pC->m_pMp4EncoderContext);
1007        if (M4NO_ERROR != osaErr)
1008        {
1009            M4OSA_TRACE1_1("M4PTO3GPP_close: m_pEncoderInt->pFctClose returns 0x%x", osaErr);
1010            /* Well... how the heck do you handle a failed cleanup? */
1011        }
1012
1013        pC->m_eEncoderState = M4PTO3GPP_kEncoderClosed;
1014    }
1015
1016    /*******************************/
1017    /******** Close 3GP out ********/
1018    /*******************************/
1019
1020    if (M4OSA_NULL != pC->m_p3gpWriterContext)  /* happens in state _SET */
1021    {
1022        /* HW encoder: fetch the DSI from the shell video encoder, and feed it to the writer before
1023        closing it. */
1024        if ( (M4VIDEOEDITING_kMPEG4_EMP == pC->m_Params.OutputVideoFormat)
1025            || (M4VIDEOEDITING_kMPEG4 == pC->m_Params.OutputVideoFormat)
1026            || (M4VIDEOEDITING_kH264 == pC->m_Params.OutputVideoFormat))
1027        {
1028            osaErr = pC->m_pEncoderInt->pFctGetOption(pC->m_pMp4EncoderContext,
1029                M4ENCODER_kOptionID_EncoderHeader,
1030                                                            (M4OSA_DataOption)&encHeader);
1031            if ( (M4NO_ERROR != osaErr) || (M4OSA_NULL == encHeader->pBuf) )
1032            {
1033                M4OSA_TRACE1_1("M4PTO3GPP_close: failed to get the encoder header (err 0x%x)",
1034                    osaErr);
1035                /**< no return here, we still have stuff to deallocate after close, even if \
1036                it fails. */
1037            }
1038            else
1039            {
1040                /* set this header in the writer */
1041                streamHeader.streamID = M4PTO3GPP_WRITER_VIDEO_STREAM_ID;
1042                streamHeader.size = encHeader->Size;
1043                streamHeader.addr = (M4OSA_MemAddr32)encHeader->pBuf;
1044                osaErr = pC->m_pWriterGlobInt->pFctSetOption(pC->m_p3gpWriterContext,
1045                    M4WRITER_kDSI, &streamHeader);
1046                if (M4NO_ERROR != osaErr)
1047                {
1048                    M4OSA_TRACE1_1("M4PTO3GPP_close: failed to set the DSI in the writer \
1049                                (err 0x%x)   ", osaErr);
1050                }
1051            }
1052        }
1053
1054        /* Update last Video CTS */
1055        lastCTS = (M4OSA_UInt32)pC->m_mtCts;
1056
1057        osaErr = pC->m_pWriterGlobInt->pFctSetOption(pC->m_p3gpWriterContext,
1058            (M4OSA_UInt32)M4WRITER_kMaxFileDuration, &lastCTS);
1059        if (M4NO_ERROR != osaErr)
1060        {
1061            M4OSA_TRACE1_1("M4PTO3GPP_Close: SetOption(M4WRITER_kMaxFileDuration) returns 0x%x",
1062                osaErr);
1063        }
1064
1065        /* Write and close the 3GP output file */
1066        osaErr = pC->m_pWriterGlobInt->pFctCloseWrite(pC->m_p3gpWriterContext);
1067        if (M4NO_ERROR != osaErr)
1068        {
1069            M4OSA_TRACE1_1("M4PTO3GPP_Close: pWriterGlobInt->pFctCloseWrite returns 0x%x", osaErr);
1070            /**< don't return yet, we have to close other things */
1071        }
1072        pC->m_p3gpWriterContext = M4OSA_NULL;
1073    }
1074
1075    /**
1076     * State transition */
1077    pC->m_State = M4PTO3GPP_kState_CLOSED;
1078
1079    M4OSA_TRACE3_1("M4PTO3GPP_Close(): returning 0x%x", osaErr);
1080    return osaErr;
1081}
1082
1083
1084/**
1085 ******************************************************************************
1086 * M4OSA_ERR M4PTO3GPP_CleanUp(M4PTO3GPP_Context pContext);
1087 * @brief   Free all resources used by the M4PTO3GPP.
1088 * @note    The context is no more valid after this call
1089 * @param   pContext            (IN) M4PTO3GPP context
1090 * @return  M4NO_ERROR:         No error
1091 * @return  M4ERR_PARAMETER:    pContext is M4OSA_NULL (If Debug Level >= 2)
1092 ******************************************************************************
1093*/
1094/*********************************************************/
1095M4OSA_ERR M4PTO3GPP_CleanUp(M4PTO3GPP_Context pContext)
1096/*********************************************************/
1097{
1098    M4OSA_ERR err = M4NO_ERROR;
1099    M4PTO3GPP_InternalContext *pC = (M4PTO3GPP_InternalContext*)(pContext);
1100
1101    M4OSA_TRACE3_1("M4PTO3GPP_CleanUp called with pContext=0x%x", pContext);
1102
1103    /**
1104     *  Check input parameters */
1105    M4OSA_DEBUG_IF2((M4OSA_NULL==pContext),M4ERR_PARAMETER, "M4PTO3GPP_CleanUp: pContext \
1106                                                            is M4OSA_NULL");
1107
1108    /**
1109     *  First call Close, if needed, to clean the video encoder */
1110
1111    if ((M4PTO3GPP_kState_OPENED == pC->m_State) || (M4PTO3GPP_kState_READY == pC->m_State)
1112        || (M4PTO3GPP_kState_FINISHED == pC->m_State))
1113    {
1114        err = M4PTO3GPP_Close(pContext);
1115        if (M4NO_ERROR != err)
1116        {
1117            M4OSA_TRACE1_1("M4PTO3GPP_CleanUp: M4PTO3GPP_Close returns 0x%x", err);
1118            /**< don't return, we have to free other components */
1119        }
1120    }
1121
1122    /**
1123     *  Free Audio reader stuff, if needed */
1124
1125    if (M4OSA_NULL != pC->m_pAudioReaderContext) /**< may be M4OSA_NULL if M4PTO3GPP_Open was not\
1126                                                 called */
1127    {
1128
1129        err = pC->m_pReaderGlobInt->m_pFctClose(pC->m_pAudioReaderContext);
1130        if (M4NO_ERROR != err)
1131        {
1132            M4OSA_TRACE1_1("M4PTO3GPP_CleanUp: pReaderGlobInt->m_pFctClose returns 0x%x", err);
1133            /**< don't return, we have to free other components */
1134        }
1135        err = pC->m_pReaderGlobInt->m_pFctDestroy(pC->m_pAudioReaderContext);
1136        pC->m_pAudioReaderContext = M4OSA_NULL;
1137        if (M4NO_ERROR != err)
1138        {
1139            M4OSA_TRACE1_1("M4PTO3GPP_CleanUp: pReaderGlobInt->m_pFctDestroy returns 0x%x", err);
1140            /**< don't return, we have to free other components */
1141        }
1142    }
1143
1144    if (M4OSA_NULL != pC->m_pReaderAudioAU)
1145    {
1146        M4OSA_free((M4OSA_MemAddr32)pC->m_pReaderAudioAU);
1147        pC->m_pReaderAudioAU = M4OSA_NULL;
1148    }
1149
1150    /**
1151     *  Free video encoder stuff, if needed */
1152    if (M4OSA_NULL != pC->m_pMp4EncoderContext)
1153    {
1154        err = pC->m_pEncoderInt->pFctCleanup(pC->m_pMp4EncoderContext);
1155        pC->m_pMp4EncoderContext = M4OSA_NULL;
1156        if (M4NO_ERROR != err)
1157        {
1158            M4OSA_TRACE1_1("M4PTO3GPP_CleanUp: pEncoderInt->pFctDestroy returns 0x%x", err);
1159            /**< don't return, we have to free other components */
1160        }
1161    }
1162
1163    if (M4OSA_NULL != pC->m_pWriterVideoStream)
1164    {
1165        M4OSA_free((M4OSA_MemAddr32)pC->m_pWriterVideoStream);
1166        pC->m_pWriterVideoStream = M4OSA_NULL;
1167    }
1168    if (M4OSA_NULL != pC->m_pWriterAudioStream)
1169    {
1170        M4OSA_free((M4OSA_MemAddr32)pC->m_pWriterAudioStream);
1171        pC->m_pWriterAudioStream = M4OSA_NULL;
1172    }
1173    if (M4OSA_NULL != pC->m_pWriterVideoStreamInfo)
1174    {
1175        M4OSA_free((M4OSA_MemAddr32)pC->m_pWriterVideoStreamInfo);
1176        pC->m_pWriterVideoStreamInfo = M4OSA_NULL;
1177    }
1178    if (M4OSA_NULL != pC->m_pWriterAudioStreamInfo)
1179    {
1180        M4OSA_free((M4OSA_MemAddr32)pC->m_pWriterAudioStreamInfo);
1181        pC->m_pWriterAudioStreamInfo = M4OSA_NULL;
1182    }
1183
1184
1185    /**
1186     *  Free the shells interfaces */
1187    if (M4OSA_NULL != pC->m_pReaderGlobInt)
1188    {
1189        M4OSA_free((M4OSA_MemAddr32)pC->m_pReaderGlobInt);
1190        pC->m_pReaderGlobInt = M4OSA_NULL;
1191    }
1192    if (M4OSA_NULL != pC->m_pReaderDataInt)
1193    {
1194        M4OSA_free((M4OSA_MemAddr32)pC->m_pReaderDataInt);
1195        pC->m_pReaderDataInt = M4OSA_NULL;
1196    }
1197
1198    if(M4OSA_NULL != pC->m_pEncoderInt)
1199    {
1200        M4OSA_free((M4OSA_MemAddr32)pC->m_pEncoderInt);
1201        pC->m_pEncoderInt = M4OSA_NULL;
1202    }
1203    if(M4OSA_NULL != pC->m_pWriterGlobInt)
1204    {
1205        M4OSA_free((M4OSA_MemAddr32)pC->m_pWriterGlobInt);
1206        pC->m_pWriterGlobInt = M4OSA_NULL;
1207    }
1208    if(M4OSA_NULL != pC->m_pWriterDataInt)
1209    {
1210        M4OSA_free((M4OSA_MemAddr32)pC->m_pWriterDataInt);
1211        pC->m_pWriterDataInt = M4OSA_NULL;
1212    }
1213    /**< Do not free pC->pOsaMemoryPtrFct and pC->pOsaMemoryPtrFct, because it's owned by the \
1214    application */
1215
1216    /**
1217     *  Free the context itself */
1218    M4OSA_free((M4OSA_MemAddr32)pC);
1219    pC = M4OSA_NULL;
1220
1221    M4OSA_TRACE3_0("M4PTO3GPP_CleanUp(): returning M4NO_ERROR");
1222    return M4NO_ERROR;
1223}
1224
1225/********************* INTERNAL FUNCTIONS *********************/
1226
1227/**
1228 ******************************************************************************
1229 * M4OSA_ERR M4PTO3GPP_Ready4Processing(M4PTO3GPP_InternalContext* pC);
1230 * @brief   Prepare all resources and interfaces for the transcoding.
1231 * @note    It is called by the first M4OSA_Step() call
1232 * @param   pC          (IN) M4PTO3GPP private context
1233 * @return  M4NO_ERROR: No error
1234 * @return  Any error returned by an underlaying module
1235 ******************************************************************************
1236*/
1237/******************************************************/
1238M4OSA_ERR M4PTO3GPP_Ready4Processing(M4PTO3GPP_InternalContext* pC)
1239/******************************************************/
1240{
1241    M4OSA_ERR               err = M4NO_ERROR;
1242    M4WRITER_OutputFileType outputFileType;
1243    M4OSA_UInt32            uiVersion;
1244    M4ENCODER_Format        encFormat;
1245    M4ENCODER_AdvancedParams   EncParams;    /**< Encoder advanced parameters */
1246    M4SYS_StreamIDValue     optionValue;
1247    M4OSA_Bool              bActivateEmp = M4OSA_FALSE;
1248
1249    M4OSA_TRACE3_1("M4PTO3GPP_Ready4Processing called with pC=0x%x", pC);
1250
1251    /******************************/
1252    /******************************/
1253
1254    /********************************************/
1255    /********                            ********/
1256    /******** Video Encoder Parames init ********/
1257    /********                            ********/
1258    /********************************************/
1259
1260    /**
1261     *  Get the correct encoder interface */
1262    switch(pC->m_Params.OutputVideoFormat)
1263    {
1264        case M4VIDEOEDITING_kMPEG4_EMP: bActivateEmp = M4OSA_TRUE; /* no break */
1265        case M4VIDEOEDITING_kMPEG4:
1266            if (pC->registeredExternalEncs[M4VE_kMpeg4VideoEnc].registered)
1267            {
1268#ifdef M4VSS_ENABLE_EXTERNAL_ENCODERS
1269                pC->m_pEncoderExternalAPI = pC->registeredExternalEncs[M4VE_kMpeg4VideoEnc]
1270                .pEncoderInterface;
1271                pC->m_pEncoderUserData = pC->registeredExternalEncs[M4VE_kMpeg4VideoEnc].pUserData;
1272
1273                err = M4EGE_MPEG4_getInterfaces(&encFormat, &pC->m_pEncoderInt,
1274                    M4ENCODER_OPEN_ADVANCED);
1275#else
1276                M4OSA_TRACE1_0("No external MPEG4 encoder available!\
1277                               Did you forget to register one?");
1278                err = M4ERR_STATE;
1279#endif
1280            }
1281            else
1282            {
1283#ifdef M4VSS_SUPPORT_ENCODER_MPEG4
1284                err = VideoEditorVideoEncoder_getInterface_MPEG4(&encFormat, &pC->m_pEncoderInt,
1285                    M4ENCODER_OPEN_ADVANCED);
1286#else /* software MPEG4 encoder not available! */
1287                M4OSA_TRACE1_0("No MPEG4 encoder available! Did you forget to register one?");
1288                err = M4ERR_STATE;
1289#endif /* software MPEG4 encoder available? */
1290            }
1291            break;
1292        case M4VIDEOEDITING_kH263:
1293            if (pC->registeredExternalEncs[M4VE_kH263VideoEnc].registered)
1294            {
1295#ifdef M4VSS_ENABLE_EXTERNAL_ENCODERS
1296                pC->m_pEncoderExternalAPI = pC->registeredExternalEncs[M4VE_kH263VideoEnc]
1297                .pEncoderInterface;
1298                pC->m_pEncoderUserData = pC->registeredExternalEncs[M4VE_kH263VideoEnc].pUserData;
1299
1300                err = M4EGE_H263_getInterfaces(&encFormat, &pC->m_pEncoderInt,
1301                    M4ENCODER_OPEN_ADVANCED);
1302#else
1303                M4OSA_TRACE1_0("No external H263 encoder available! Did you forget to register\
1304                               one?");
1305                err = M4ERR_STATE;
1306#endif
1307            }
1308            else
1309            {
1310#ifdef M4VSS_SUPPORT_ENCODER_MPEG4
1311                err = VideoEditorVideoEncoder_getInterface_H263(&encFormat, &pC->m_pEncoderInt,
1312                    M4ENCODER_OPEN_ADVANCED);
1313#else /* software H263 encoder not available! */
1314                M4OSA_TRACE1_0("No H263 encoder available! Did you forget to register one?");
1315                err = M4ERR_STATE;
1316#endif /* software H263 encoder available? */
1317            }
1318            break;
1319        case M4VIDEOEDITING_kH264:
1320            if (pC->registeredExternalEncs[M4VE_kH264VideoEnc].registered)
1321            {
1322                M4OSA_TRACE1_0("M4PTO3GPP_Ready4Processing: No external H264 encoder available! \
1323                               Did you forget to register one?");
1324                err = M4ERR_STATE;
1325            }
1326            else
1327            {
1328#ifdef M4VSS_SUPPORT_ENCODER_AVC
1329                err = VideoEditorVideoEncoder_getInterface_H264(&encFormat, &pC->m_pEncoderInt,
1330                    M4ENCODER_OPEN_ADVANCED);
1331#else /* software H264 encoder not available! */
1332                M4OSA_TRACE1_0("M4PTO3GPP_Ready4Processing: No H264 encoder available!\
1333                               Did you forget to register one?");
1334                err = M4ERR_STATE;
1335#endif /* software H264 encoder available? */
1336            }
1337            break;
1338        default:
1339            M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: unknown format 0x%x returning \
1340                           ERR_M4PTO3GPP_UNDEFINED_OUTPUT_VIDEO_FORMAT",
1341                           pC->m_Params.OutputVideoFormat);
1342            return ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_FORMAT;
1343    }
1344    if (M4NO_ERROR != err)
1345    {
1346        M4OSA_TRACE1_1("switch(pC->m_Params.OutputVideoFormat): getInterfaces returns 0x%x", err);
1347        return err;
1348    }
1349
1350    /**
1351     *  Fill encoder parameters according to M4PTO3GPP settings */
1352
1353    /**
1354     * Video frame size */
1355    switch(pC->m_Params.OutputVideoFrameSize)
1356    {
1357        case M4VIDEOEDITING_kSQCIF :
1358            EncParams.FrameHeight = M4ENCODER_SQCIF_Height;
1359            EncParams.FrameWidth  = M4ENCODER_SQCIF_Width;
1360            break;
1361        case M4VIDEOEDITING_kQQVGA :
1362            EncParams.FrameHeight = M4ENCODER_QQVGA_Height;
1363            EncParams.FrameWidth  = M4ENCODER_QQVGA_Width;
1364            break;
1365        case M4VIDEOEDITING_kQCIF :
1366            EncParams.FrameHeight = M4ENCODER_QCIF_Height;
1367            EncParams.FrameWidth  = M4ENCODER_QCIF_Width;
1368            break;
1369        case M4VIDEOEDITING_kQVGA :
1370            EncParams.FrameHeight = M4ENCODER_QVGA_Height;
1371            EncParams.FrameWidth  = M4ENCODER_QVGA_Width;
1372            break;
1373        case M4VIDEOEDITING_kCIF :
1374            EncParams.FrameHeight = M4ENCODER_CIF_Height;
1375            EncParams.FrameWidth  = M4ENCODER_CIF_Width;
1376            break;
1377        case M4VIDEOEDITING_kVGA :
1378            EncParams.FrameHeight = M4ENCODER_VGA_Height;
1379            EncParams.FrameWidth  = M4ENCODER_VGA_Width;
1380            break;
1381/* +PR LV5807 */
1382        case M4VIDEOEDITING_kWVGA :
1383            EncParams.FrameHeight = M4ENCODER_WVGA_Height;
1384            EncParams.FrameWidth  = M4ENCODER_WVGA_Width;
1385            break;
1386        case M4VIDEOEDITING_kNTSC:
1387            EncParams.FrameHeight = M4ENCODER_NTSC_Height;
1388            EncParams.FrameWidth  = M4ENCODER_NTSC_Width;
1389            break;
1390/* -PR LV5807 */
1391/* +CR Google */
1392        case M4VIDEOEDITING_k640_360:
1393            EncParams.FrameHeight = M4ENCODER_640_360_Height;
1394            EncParams.FrameWidth  = M4ENCODER_640_360_Width;
1395            break;
1396
1397        case M4VIDEOEDITING_k854_480:
1398            EncParams.FrameHeight = M4ENCODER_854_480_Height;
1399            EncParams.FrameWidth  = M4ENCODER_854_480_Width;
1400            break;
1401
1402        case M4VIDEOEDITING_kHD1280:
1403            EncParams.FrameHeight = M4ENCODER_HD1280_Height;
1404            EncParams.FrameWidth  = M4ENCODER_HD1280_Width;
1405            break;
1406
1407        case M4VIDEOEDITING_kHD1080:
1408            EncParams.FrameHeight = M4ENCODER_HD1080_Height;
1409            EncParams.FrameWidth  = M4ENCODER_HD1080_Width;
1410            break;
1411
1412        case M4VIDEOEDITING_kHD960:
1413            EncParams.FrameHeight = M4ENCODER_HD960_Height;
1414            EncParams.FrameWidth  = M4ENCODER_HD960_Width;
1415            break;
1416/* -CR Google */
1417        default :
1418            M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: unknown format 0x%x returning \
1419                           ERR_M4PTO3GPP_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE",
1420                           pC->m_Params.OutputVideoFrameSize);
1421            return ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE;
1422    }
1423
1424    EncParams.InputFormat = M4ENCODER_kIYUV420;
1425
1426    /**
1427     * Video bitrate */
1428    switch(pC->m_Params.OutputVideoBitrate)
1429    {
1430        case M4VIDEOEDITING_k16_KBPS:
1431        case M4VIDEOEDITING_k24_KBPS:
1432        case M4VIDEOEDITING_k32_KBPS:
1433        case M4VIDEOEDITING_k48_KBPS:
1434        case M4VIDEOEDITING_k64_KBPS:
1435        case M4VIDEOEDITING_k96_KBPS:
1436        case M4VIDEOEDITING_k128_KBPS:
1437        case M4VIDEOEDITING_k192_KBPS:
1438        case M4VIDEOEDITING_k256_KBPS:
1439        case M4VIDEOEDITING_k288_KBPS:
1440        case M4VIDEOEDITING_k384_KBPS:
1441        case M4VIDEOEDITING_k512_KBPS:
1442        case M4VIDEOEDITING_k800_KBPS:
1443/*+ New Encoder bitrates */
1444        case M4VIDEOEDITING_k2_MBPS:
1445        case M4VIDEOEDITING_k5_MBPS:
1446        case M4VIDEOEDITING_k8_MBPS:
1447/*- New Encoder bitrates */
1448            EncParams.Bitrate = pC->m_Params.OutputVideoBitrate;
1449            break;
1450
1451        case M4VIDEOEDITING_kVARIABLE_KBPS:
1452/*+ New Encoder bitrates */
1453            EncParams.Bitrate = M4VIDEOEDITING_k8_MBPS;
1454/*- New Encoder bitrates */
1455            break;
1456
1457        default :
1458            M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: unknown format 0x%x returning\
1459                           ERR_M4PTO3GPP_UNDEFINED_OUTPUT_VIDEO_BITRATE",
1460                           pC->m_Params.OutputVideoBitrate);
1461            return ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_BITRATE;
1462    }
1463
1464    /**
1465     * Video format */
1466    switch(pC->m_Params.OutputVideoFormat)
1467    {
1468        case M4VIDEOEDITING_kMPEG4_EMP :
1469        case M4VIDEOEDITING_kMPEG4 :
1470            EncParams.Format    = M4ENCODER_kMPEG4;
1471            break;
1472        case M4VIDEOEDITING_kH263 :
1473            EncParams.Format    = M4ENCODER_kH263;
1474            break;
1475        case M4VIDEOEDITING_kH264:
1476            EncParams.Format    = M4ENCODER_kH264;
1477            break;
1478        default :
1479            M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: unknown format 0x%x returning\
1480                           ERR_M4PTO3GPP_UNDEFINED_OUTPUT_VIDEO_FORMAT",
1481                           pC->m_Params.OutputVideoFormat);
1482            return ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_FORMAT;
1483    }
1484
1485    /**
1486     * Video frame rate (set it to max = 30 fps) */
1487    EncParams.uiTimeScale = 30;
1488    EncParams.uiRateFactor = 1;
1489
1490    EncParams.FrameRate = M4ENCODER_k30_FPS;
1491
1492
1493    /******************************/
1494    /******** 3GP out init ********/
1495    /******************************/
1496
1497    /* Get the 3GPP writer interface */
1498    err = M4WRITER_3GP_getInterfaces(&outputFileType, &pC->m_pWriterGlobInt, &pC->m_pWriterDataInt);
1499    if (M4NO_ERROR != err)
1500    {
1501        M4OSA_TRACE1_1("M4WRITER_3GP_getInterfaces: M4WRITER_3GP_getInterfaces returns 0x%x", err);
1502        return err;
1503    }
1504
1505    /* Init the 3GPP writer */
1506    err = pC->m_pWriterGlobInt->pFctOpen(&pC->m_p3gpWriterContext, pC->m_Params.pOutput3gppFile,
1507        pC->pOsalFileWrite, pC->m_Params.pTemporaryFile, pC->pOsalFileRead);
1508    if (M4NO_ERROR != err)
1509    {
1510        M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: pWriterGlobInt->pFctOpen returns 0x%x", err);
1511        return err;
1512    }
1513
1514    /**
1515     *  Link to the writer context in the writer interface */
1516    pC->m_pWriterDataInt->pWriterContext = pC->m_p3gpWriterContext;
1517
1518    /**
1519     *  Set the product description string in the written file */
1520    err = pC->m_pWriterGlobInt->pFctSetOption(pC->m_p3gpWriterContext, M4WRITER_kEmbeddedString,
1521        (M4OSA_DataOption)M4PTO3GPP_SIGNATURE);
1522    if (M4NO_ERROR != err)
1523    {
1524        M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: \
1525                       pWriterGlobInt->pFctSetOption(M4WRITER_kEmbeddedString) returns 0x%x", err);
1526        return err;
1527    }
1528
1529    /**
1530     *  Set the product version in the written file */
1531    uiVersion = M4VIDEOEDITING_VERSION_MAJOR*100 + M4VIDEOEDITING_VERSION_MINOR*10
1532        + M4VIDEOEDITING_VERSION_REVISION;
1533    err = pC->m_pWriterGlobInt->pFctSetOption(pC->m_p3gpWriterContext, M4WRITER_kEmbeddedVersion,
1534        (M4OSA_DataOption)&uiVersion);
1535    if (M4NO_ERROR != err)
1536    {
1537        M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: \
1538                       pWriterGlobInt->pFctSetOption(M4WRITER_kEmbeddedVersion) returns 0x%x", err);
1539        return err;
1540    }
1541
1542    /**
1543     * In case of EMP, we have to explicitely give an emp ftyp to the writer */
1544    if(M4OSA_TRUE == bActivateEmp)
1545    {
1546        M4VIDEOEDITING_FtypBox ftyp;
1547
1548        ftyp.major_brand          = M4VIDEOEDITING_BRAND_3GP4;
1549        ftyp.minor_version        = M4VIDEOEDITING_BRAND_0000;
1550        ftyp.nbCompatibleBrands   = 2;
1551        ftyp.compatible_brands[0] = M4VIDEOEDITING_BRAND_3GP4;
1552        ftyp.compatible_brands[1] = M4VIDEOEDITING_BRAND_EMP;
1553
1554        err = pC->m_pWriterGlobInt->pFctSetOption(pC->m_p3gpWriterContext,
1555            (M4OSA_UInt32)M4WRITER_kSetFtypBox, (M4OSA_DataOption) &ftyp);
1556        if (M4NO_ERROR != err)
1557        {
1558            M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing:\
1559                         m_pWriterGlobInt->pFctSetOption(M4WRITER_kSetFtypBox) returns 0x%x!", err);
1560            return err;
1561        }
1562    }
1563
1564    /**
1565     *  Allocate and fill the video stream structures for the writer */
1566    pC->m_pWriterVideoStream =
1567        (M4SYS_StreamDescription*)M4OSA_malloc(sizeof(M4SYS_StreamDescription), M4PTO3GPP,
1568        (M4OSA_Char *)"pWriterVideoStream");
1569    if (M4OSA_NULL == pC->m_pWriterVideoStream)
1570    {
1571        M4OSA_TRACE1_0("M4PTO3GPP_Ready4Processing(): unable to allocate pWriterVideoStream, \
1572                       returning M4ERR_ALLOC");
1573        return M4ERR_ALLOC;
1574    }
1575    pC->m_pWriterVideoStreamInfo =
1576        (M4WRITER_StreamVideoInfos*)M4OSA_malloc(sizeof(M4WRITER_StreamVideoInfos), M4PTO3GPP,
1577        (M4OSA_Char *)"pWriterVideoStreamInfo");
1578    if (M4OSA_NULL == pC->m_pWriterVideoStreamInfo)
1579    {
1580        M4OSA_TRACE1_0("M4PTO3GPP_Ready4Processing(): unable to allocate pWriterVideoStreamInfo,\
1581                       returning M4ERR_ALLOC");
1582        return M4ERR_ALLOC;
1583    }
1584
1585    /**
1586     * Fill Video properties structure for the AddStream method */
1587    pC->m_pWriterVideoStreamInfo->height        = EncParams.FrameHeight;
1588    pC->m_pWriterVideoStreamInfo->width         = EncParams.FrameWidth;
1589    pC->m_pWriterVideoStreamInfo->fps           = 0;        /**< Not used by the core writer */
1590    pC->m_pWriterVideoStreamInfo->Header.pBuf   = M4OSA_NULL;
1591    /** No header, will be set by setOption */
1592    pC->m_pWriterVideoStreamInfo->Header.Size   = 0;
1593
1594    /**
1595     *  Fill Video stream description structure for the AddStream method */
1596    pC->m_pWriterVideoStream->streamID = M4PTO3GPP_WRITER_VIDEO_STREAM_ID;
1597
1598    /**
1599     * Video format */
1600    switch(pC->m_Params.OutputVideoFormat)
1601    {
1602        case M4VIDEOEDITING_kMPEG4_EMP:
1603        case M4VIDEOEDITING_kMPEG4:
1604            pC->m_pWriterVideoStream->streamType = M4SYS_kMPEG_4;   break;
1605        case M4VIDEOEDITING_kH263:
1606            pC->m_pWriterVideoStream->streamType = M4SYS_kH263;     break;
1607        case M4VIDEOEDITING_kH264:
1608            pC->m_pWriterVideoStream->streamType = M4SYS_kH264;     break;
1609        default :
1610            M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: unknown format 0x%x returning \
1611                           ERR_M4PTO3GPP_UNDEFINED_OUTPUT_VIDEO_FORMAT",
1612                           pC->m_Params.OutputVideoFormat);
1613            return ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_FORMAT;
1614    }
1615
1616    /**
1617     * Video bitrate */
1618    switch(pC->m_Params.OutputVideoBitrate)
1619    {
1620        case M4VIDEOEDITING_k16_KBPS:
1621        case M4VIDEOEDITING_k24_KBPS:
1622        case M4VIDEOEDITING_k32_KBPS:
1623        case M4VIDEOEDITING_k48_KBPS:
1624        case M4VIDEOEDITING_k64_KBPS:
1625        case M4VIDEOEDITING_k96_KBPS:
1626        case M4VIDEOEDITING_k128_KBPS:
1627        case M4VIDEOEDITING_k192_KBPS:
1628        case M4VIDEOEDITING_k256_KBPS:
1629        case M4VIDEOEDITING_k288_KBPS:
1630        case M4VIDEOEDITING_k384_KBPS:
1631        case M4VIDEOEDITING_k512_KBPS:
1632        case M4VIDEOEDITING_k800_KBPS:
1633/*+ New Encoder bitrates */
1634        case M4VIDEOEDITING_k2_MBPS:
1635        case M4VIDEOEDITING_k5_MBPS:
1636        case M4VIDEOEDITING_k8_MBPS:
1637/*- New Encoder bitrates */
1638            pC->m_pWriterVideoStream->averageBitrate = pC->m_Params.OutputVideoBitrate;
1639            break;
1640
1641        case M4VIDEOEDITING_kVARIABLE_KBPS :
1642            pC->m_pWriterVideoStream->averageBitrate = 0;
1643            break;
1644
1645        default :
1646            M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: unknown format 0x%x returning\
1647                           ERR_M4PTO3GPP_UNDEFINED_OUTPUT_VIDEO_BITRATE",
1648                           pC->m_Params.OutputVideoBitrate);
1649            return ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_BITRATE;
1650    }
1651
1652    pC->m_pWriterVideoStream->duration                  = 0;        /**< Duration is not known */
1653    pC->m_pWriterVideoStream->timeScale                 = 0;    /**< Not used by the core writer */
1654    pC->m_pWriterVideoStream->maxBitrate                = pC->m_pWriterVideoStream->averageBitrate;
1655    pC->m_pWriterVideoStream->profileLevel              = 0;    /**< Not used by the core writer */
1656    pC->m_pWriterVideoStream->decoderSpecificInfo       = (M4OSA_MemAddr32)
1657                                                            (pC->m_pWriterVideoStreamInfo);
1658    pC->m_pWriterVideoStream->decoderSpecificInfoSize   = sizeof(M4WRITER_StreamVideoInfos);
1659
1660    /**
1661     * Update AU properties for video stream */
1662    pC->m_WriterVideoAU.CTS         = pC->m_WriterVideoAU.DTS = 0;  /** Reset time */
1663    pC->m_WriterVideoAU.size        = 0;
1664    pC->m_WriterVideoAU.frag        = M4OSA_NULL;
1665    pC->m_WriterVideoAU.nbFrag      = 0;                            /** No fragment */
1666    pC->m_WriterVideoAU.stream      = pC->m_pWriterVideoStream;
1667    pC->m_WriterVideoAU.attribute   = AU_RAP;
1668    pC->m_WriterVideoAU.dataAddress = M4OSA_NULL;
1669
1670    /**
1671     *  If there is an audio input, allocate and fill the audio stream structures for the writer */
1672    if(M4OSA_NULL != pC->m_pReaderAudioStream)
1673    {
1674        pC->m_pWriterAudioStream =
1675            (M4SYS_StreamDescription*)M4OSA_malloc(sizeof(M4SYS_StreamDescription), M4PTO3GPP,
1676            (M4OSA_Char *)"pWriterAudioStream");
1677        if (M4OSA_NULL == pC->m_pWriterAudioStream)
1678        {
1679            M4OSA_TRACE1_0("M4PTO3GPP_Ready4Processing(): unable to allocate pWriterAudioStream, \
1680                           returning M4ERR_ALLOC");
1681            return M4ERR_ALLOC;
1682        }
1683        pC->m_pWriterAudioStreamInfo =
1684            (M4WRITER_StreamAudioInfos*)M4OSA_malloc(sizeof(M4WRITER_StreamAudioInfos), M4PTO3GPP,
1685            (M4OSA_Char *)"pWriterAudioStreamInfo");
1686        if (M4OSA_NULL == pC->m_pWriterAudioStreamInfo)
1687        {
1688            M4OSA_TRACE1_0("M4PTO3GPP_Ready4Processing(): unable to allocate \
1689                           pWriterAudioStreamInfo, returning M4ERR_ALLOC");
1690            return M4ERR_ALLOC;
1691        }
1692
1693        pC->m_pWriterAudioStreamInfo->nbSamplesPerSec = 0; /**< unused by our shell writer */
1694        pC->m_pWriterAudioStreamInfo->nbBitsPerSample = 0; /**< unused by our shell writer */
1695        pC->m_pWriterAudioStreamInfo->nbChannels = 1;      /**< unused by our shell writer */
1696
1697        if( (M4OSA_NULL != pC->m_pReaderAudioStream) && /* audio could have been discarded */
1698            (M4OSA_NULL != pC->m_pReaderAudioStream->m_basicProperties.m_pDecoderSpecificInfo) )
1699        {
1700            /* If we copy the stream from the input, we copy its DSI */
1701            pC->m_pWriterAudioStreamInfo->Header.Size =
1702                pC->m_pReaderAudioStream->m_basicProperties.m_decoderSpecificInfoSize;
1703            pC->m_pWriterAudioStreamInfo->Header.pBuf =
1704                (M4OSA_MemAddr8)pC->m_pReaderAudioStream->m_basicProperties.m_pDecoderSpecificInfo;
1705        }
1706        else
1707        {
1708            /* Writer will put a default DSI */
1709            pC->m_pWriterAudioStreamInfo->Header.Size = 0;
1710            pC->m_pWriterAudioStreamInfo->Header.pBuf = M4OSA_NULL;
1711        }
1712
1713        /**
1714         * Add the audio stream */
1715        switch (pC->m_pReaderAudioStream->m_basicProperties.m_streamType)
1716        {
1717            case M4DA_StreamTypeAudioAmrNarrowBand:
1718                pC->m_pWriterAudioStream->streamType = M4SYS_kAMR;
1719                break;
1720            case M4DA_StreamTypeAudioAac:
1721                pC->m_pWriterAudioStream->streamType = M4SYS_kAAC;
1722                break;
1723            case M4DA_StreamTypeAudioEvrc:
1724                pC->m_pWriterAudioStream->streamType = M4SYS_kEVRC;
1725                break;
1726            default:
1727                M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: unhandled audio format (0x%x),\
1728                               returning ERR_PTO3GPP_UNDEFINED_OUTPUT_VIDEO_BITRATE",
1729                               pC->m_pReaderAudioStream->m_basicProperties.m_streamType);
1730                return ERR_PTO3GPP_UNDEFINED_OUTPUT_AUDIO_FORMAT;
1731        }
1732
1733        /*
1734         * Fill Audio stream description structure for the AddStream method */
1735        pC->m_pWriterAudioStream->streamID                  = M4PTO3GPP_WRITER_AUDIO_STREAM_ID;
1736        pC->m_pWriterAudioStream->duration                  = 0;/**< Duration is not known yet */
1737        pC->m_pWriterAudioStream->timeScale                 = M4PTO3GPP_WRITER_AUDIO_AMR_TIME_SCALE;
1738        pC->m_pWriterAudioStream->profileLevel              = M4PTO3GPP_WRITER_AUDIO_PROFILE_LEVEL;
1739        pC->m_pWriterAudioStream->averageBitrate            =
1740                                pC->m_pReaderAudioStream->m_basicProperties.m_averageBitRate;
1741        pC->m_pWriterAudioStream->maxBitrate                =
1742                                pC->m_pWriterAudioStream->averageBitrate;
1743
1744        /**
1745         * Our writer shell interface is a little tricky: we put M4WRITER_StreamAudioInfos \
1746            in the DSI pointer... */
1747        pC->m_pWriterAudioStream->decoderSpecificInfo =
1748                    (M4OSA_MemAddr32)pC->m_pWriterAudioStreamInfo;
1749
1750        /**
1751         * Update AU properties for audio stream */
1752        pC->m_WriterAudioAU.CTS         = pC->m_WriterAudioAU.DTS = 0;  /** Reset time */
1753        pC->m_WriterAudioAU.size        = 0;
1754        pC->m_WriterAudioAU.frag        = M4OSA_NULL;
1755        pC->m_WriterAudioAU.nbFrag      = 0;                            /** No fragment */
1756        pC->m_WriterAudioAU.stream      = pC->m_pWriterAudioStream;
1757        pC->m_WriterAudioAU.attribute   = AU_RAP;
1758        pC->m_WriterAudioAU.dataAddress = M4OSA_NULL;
1759    }
1760
1761    /************************************/
1762    /******** Video Encoder Init ********/
1763    /************************************/
1764
1765    /**
1766     * PTO uses its own bitrate regulation, not the "true" core regulation */
1767    EncParams.bInternalRegulation = M4OSA_TRUE; //M4OSA_FALSE;
1768    EncParams.uiStartingQuantizerValue = M4PTO3GPP_QUANTIZER_STEP;
1769
1770    /**
1771     * Other encoder settings */
1772    if(M4OSA_TRUE == bActivateEmp)
1773    {
1774        EncParams.uiHorizontalSearchRange  = 15;            /* set value */
1775        EncParams.uiVerticalSearchRange    = 15;            /* set value */
1776        EncParams.bErrorResilience         = M4OSA_FALSE;   /* no error resilience */
1777        EncParams.uiIVopPeriod             = 15;            /* one I frame every 15 frames */
1778        EncParams.uiMotionEstimationTools  = 1;             /* M4V_MOTION_EST_TOOLS_NO_4MV */
1779        EncParams.bAcPrediction            = M4OSA_FALSE;   /* no AC prediction */
1780        EncParams.bDataPartitioning        = M4OSA_FALSE;   /* no data partitioning */
1781    }
1782    else
1783    {
1784        EncParams.uiHorizontalSearchRange  = 0;             /* use default */
1785        EncParams.uiVerticalSearchRange    = 0;             /* use default */
1786        EncParams.bErrorResilience         = M4OSA_FALSE;   /* no error resilience */
1787        EncParams.uiIVopPeriod             = 15;             /* use default */
1788        EncParams.uiMotionEstimationTools  = 0;             /* M4V_MOTION_EST_TOOLS_ALL */
1789        EncParams.bAcPrediction            = M4OSA_TRUE;    /* use AC prediction */
1790        EncParams.bDataPartitioning        = M4OSA_FALSE;   /* no data partitioning */
1791    }
1792
1793    /**
1794     * Create video encoder */
1795    err = pC->m_pEncoderInt->pFctInit(&pC->m_pMp4EncoderContext, pC->m_pWriterDataInt,
1796                                    M4PTO3GPP_applyVPP, pC, pC->m_pEncoderExternalAPI,
1797                                    pC->m_pEncoderUserData);
1798    if (M4NO_ERROR != err)
1799    {
1800        M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: EncoderInt->pFctInit returns 0x%x", err);
1801        return err;
1802    }
1803
1804    pC->m_eEncoderState = M4PTO3GPP_kEncoderClosed;
1805
1806    err = pC->m_pEncoderInt->pFctOpen(pC->m_pMp4EncoderContext, &pC->m_WriterVideoAU, &EncParams);
1807    if (M4NO_ERROR != err)
1808    {
1809        M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: EncoderInt->pFctOpen returns 0x%x", err);
1810        return err;
1811    }
1812
1813    pC->m_eEncoderState = M4PTO3GPP_kEncoderStopped;
1814
1815    if (M4OSA_NULL != pC->m_pEncoderInt->pFctStart)
1816    {
1817        err = pC->m_pEncoderInt->pFctStart(pC->m_pMp4EncoderContext);
1818
1819        if (M4NO_ERROR != err)
1820        {
1821            M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: EncoderInt->pFctStart returns 0x%x", err);
1822            return err;
1823        }
1824    }
1825
1826    pC->m_eEncoderState = M4PTO3GPP_kEncoderRunning;
1827
1828    /**
1829     * No more  setoption on "M4ENCODER_kVideoFragmentSize" here.
1830     * It is now automaticly and "smartly" set in the encoder shell. */
1831
1832    /**************************************/
1833    /******** 3GP out add streams  ********/
1834    /**************************************/
1835
1836    err = pC->m_pWriterGlobInt->pFctAddStream(pC->m_p3gpWriterContext, pC->m_pWriterVideoStream);
1837    if (M4NO_ERROR != err)
1838    {
1839        M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: pWriterGlobInt->pFctAddStream(video) returns\
1840                       0x%x", err);
1841        return err;
1842    }
1843
1844    /**
1845     * Set video max au size */
1846    optionValue.streamID    = M4PTO3GPP_WRITER_VIDEO_STREAM_ID;
1847    optionValue.value = (M4OSA_UInt32)(1.5F * (M4OSA_Float)(pC->m_pWriterVideoStreamInfo->width
1848                                                * pC->m_pWriterVideoStreamInfo->height)
1849                                                * M4PTO3GPP_VIDEO_MIN_COMPRESSION_RATIO);
1850    M4OSA_TRACE3_1("M4PTO3GPP_Ready4Processing,M4WRITER_kMaxAUSize: %u",optionValue.value);
1851    err = pC->m_pWriterGlobInt->pFctSetOption(pC->m_p3gpWriterContext,
1852                                (M4OSA_UInt32)M4WRITER_kMaxAUSize,(M4OSA_DataOption) &optionValue);
1853    if (M4NO_ERROR != err)
1854    {
1855        M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: pWriterGlobInt->pFctSetOption(video,\
1856                       M4WRITER_kMaxAUSize) returns 0x%x", err);
1857        return err;
1858    }
1859
1860    /**
1861     * Set video max chunck size */
1862    optionValue.value = (M4OSA_UInt32)((M4OSA_Float)optionValue.value
1863                        * M4PTO3GPP_VIDEO_AU_SIZE_TO_CHUNCK_SIZE_RATIO);
1864    M4OSA_TRACE3_1("M4PTO3GPP_Ready4Processing,M4WRITER_kMaxChunckSize: %u",optionValue.value);
1865    err = pC->m_pWriterGlobInt->pFctSetOption(pC->m_p3gpWriterContext,
1866                        (M4OSA_UInt32)M4WRITER_kMaxChunckSize,(M4OSA_DataOption) &optionValue);
1867    if (M4NO_ERROR != err)
1868    {
1869        M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: pWriterGlobInt->pFctSetOption(video,\
1870                       M4WRITER_kMaxChunckSize) returns 0x%x", err);
1871        return err;
1872    }
1873
1874    if (M4OSA_NULL != pC->m_pReaderAudioStream)
1875    {
1876        err = pC->m_pWriterGlobInt->pFctAddStream(pC->m_p3gpWriterContext, pC->m_pWriterAudioStream);
1877        if (M4NO_ERROR != err)
1878        {
1879            M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: pWriterGlobInt->pFctAddStream(audio) \
1880                           returns 0x%x", err);
1881            return err;
1882        }
1883
1884        /**
1885         * Set audio max au size */
1886        optionValue.value       = M4PTO3GPP_AUDIO_MAX_AU_SIZE;
1887        optionValue.streamID    = M4PTO3GPP_WRITER_AUDIO_STREAM_ID;
1888        err = pC->m_pWriterGlobInt->pFctSetOption(pC->m_p3gpWriterContext,
1889            (M4OSA_UInt32)M4WRITER_kMaxAUSize,(M4OSA_DataOption) &optionValue);
1890        if (M4NO_ERROR != err)
1891        {
1892            M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: pWriterGlobInt->pFctSetOption(audio,\
1893                           M4WRITER_kMaxAUSize) returns 0x%x", err);
1894            return err;
1895        }
1896
1897        /**
1898         * Set audio max chunck size */
1899        optionValue.value = M4PTO3GPP_AUDIO_MAX_CHUNK_SIZE; /**< Magical */
1900        err = pC->m_pWriterGlobInt->pFctSetOption(pC->m_p3gpWriterContext,
1901                        (M4OSA_UInt32)M4WRITER_kMaxChunckSize,(M4OSA_DataOption) &optionValue);
1902        if (M4NO_ERROR != err)
1903        {
1904            M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: pWriterGlobInt->pFctSetOption(audio,\
1905                           M4WRITER_kMaxChunckSize) returns 0x%x", err);
1906            return err;
1907        }
1908    }
1909
1910    /*
1911     * Close the stream registering in order to be ready to write data */
1912    err = pC->m_pWriterGlobInt->pFctStartWriting(pC->m_p3gpWriterContext);
1913    if (M4NO_ERROR != err)
1914    {
1915        M4OSA_TRACE1_1("M4PTO3GPP_Ready4Processing: pWriterGlobInt->pFctStartWriting returns 0x%x",
1916                        err);
1917        return err;
1918    }
1919
1920
1921    M4OSA_TRACE3_0("M4PTO3GPP_Ready4Processing: returning M4NO_ERROR");
1922    return M4NO_ERROR;
1923}
1924
1925/**
1926 ******************************************************************************
1927 M4OSA_ERR M4PTO3GPP_writeAmrSilence122Frame(M4WRITER_DataInterface* pWriterDataIntInterface,
1928                            M4WRITER_Context* pWriterContext,
1929                                      M4SYS_AccessUnit* pWriterAudioAU, M4OSA_Time mtIncCts)
1930 * @brief   Write an AMR 12.2kbps silence FRAME into the writer
1931 * @note    Mainly used to fix the 'bzz' bug...
1932 * @param   pWriterDataIntInterface (IN)    writer data interfaces
1933 *          pWriterContext          (IN/OUT)writer context
1934 *          pWriterAudioAU          (OUT)   writer audio access unit
1935 *          mtIncCts                (IN)    writer CTS
1936 * @return  M4NO_ERROR: No error
1937 ******************************************************************************
1938*/
1939static M4OSA_ERR M4PTO3GPP_writeAmrSilence122Frame(M4WRITER_DataInterface* pWriterDataIntInterface,
1940                                                   M4WRITER_Context* pWriterContext,
1941                                                    M4SYS_AccessUnit* pWriterAudioAU,
1942                                                    M4OSA_Time mtIncCts)
1943{
1944    M4OSA_ERR err;
1945
1946    err = pWriterDataIntInterface->pStartAU(pWriterContext, M4PTO3GPP_WRITER_AUDIO_STREAM_ID,
1947                                        pWriterAudioAU);
1948    if (M4NO_ERROR != err)
1949    {
1950        M4OSA_TRACE1_1("M4PTO3GPP_writeAmrSilence122Frame: pWriterDataInt->pStartAU(audio) returns \
1951                                                    0x%x!", err);
1952        return err;
1953    }
1954
1955    memcpy((void *)pWriterAudioAU->dataAddress,
1956     (void *)M4PTO3GPP_AMR_AU_SILENCE_122_FRAME, M4PTO3GPP_AMR_AU_SILENCE_FRAME_122_SIZE);
1957    pWriterAudioAU->size    = M4PTO3GPP_AMR_AU_SILENCE_FRAME_122_SIZE;
1958    pWriterAudioAU->CTS     = mtIncCts;
1959    pWriterAudioAU->nbFrag  = 0;
1960
1961    err = pWriterDataIntInterface->pProcessAU(pWriterContext, M4PTO3GPP_WRITER_AUDIO_STREAM_ID,
1962                                                pWriterAudioAU);
1963    if (M4NO_ERROR != err)
1964    {
1965        M4OSA_TRACE1_1("M4PTO3GPP_writeAmrSilence122Frame: pWriterDataInt->pProcessAU(silence) \
1966                       returns 0x%x!", err);
1967        return err;
1968    }
1969
1970    return M4NO_ERROR;
1971}
1972
1973/**
1974 ******************************************************************************
1975 M4OSA_ERR M4PTO3GPP_writeAmrSilence048Frame(M4WRITER_DataInterface* pWriterDataIntInterface,
1976                                        M4WRITER_Context* pWriterContext,
1977                                      M4SYS_AccessUnit* pWriterAudioAU, M4OSA_Time mtIncCts)
1978 * @brief   Write an AMR 12.2kbps silence FRAME into the writer
1979 * @note    Mainly used to fix the 'bzz' bug...
1980 * @param   pWriterDataIntInterface (IN)    writer data interfaces
1981 *          pWriterContext          (IN/OUT)writer context
1982 *          pWriterAudioAU          (OUT)   writer audio access unit
1983 *          mtIncCts                (IN)    writer CTS
1984 * @return  M4NO_ERROR: No error
1985 ******************************************************************************
1986*/
1987static M4OSA_ERR M4PTO3GPP_writeAmrSilence048Frame(M4WRITER_DataInterface* pWriterDataIntInterface,
1988                                                   M4WRITER_Context* pWriterContext,
1989                                                M4SYS_AccessUnit* pWriterAudioAU,
1990                                                M4OSA_Time mtIncCts)
1991{
1992    M4OSA_ERR err;
1993
1994    err = pWriterDataIntInterface->pStartAU(pWriterContext, M4PTO3GPP_WRITER_AUDIO_STREAM_ID,
1995                                                        pWriterAudioAU);
1996    if (M4NO_ERROR != err)
1997    {
1998        M4OSA_TRACE1_1("M4PTO3GPP_writeAmrSilence048Frame: pWriterDataInt->pStartAU(audio)\
1999                       returns 0x%x!", err);
2000        return err;
2001    }
2002
2003    memcpy((void *)pWriterAudioAU->dataAddress,
2004                (void *)M4PTO3GPP_AMR_AU_SILENCE_048_FRAME,
2005                M4PTO3GPP_AMR_AU_SILENCE_FRAME_048_SIZE);
2006    pWriterAudioAU->size    = M4PTO3GPP_AMR_AU_SILENCE_FRAME_048_SIZE;
2007    pWriterAudioAU->CTS     = mtIncCts;
2008    pWriterAudioAU->nbFrag  = 0;
2009
2010    err = pWriterDataIntInterface->pProcessAU(pWriterContext,
2011                    M4PTO3GPP_WRITER_AUDIO_STREAM_ID, pWriterAudioAU);
2012    if (M4NO_ERROR != err)
2013    {
2014        M4OSA_TRACE1_1("M4PTO3GPP_writeAmrSilence048Frame: \
2015                       pWriterDataInt->pProcessAU(silence) returns 0x%x!", err);
2016        return err;
2017    }
2018
2019    return M4NO_ERROR;
2020}
2021
2022
2023M4OSA_ERR M4PTO3GPP_RegisterExternalVideoEncoder(M4PTO3GPP_Context pContext,
2024                                     M4VE_EncoderType encoderType,
2025                                     M4VE_Interface*    pEncoderInterface,
2026                                     M4OSA_Void* pUserData)
2027{
2028    M4OSA_ERR err = M4NO_ERROR;
2029    M4PTO3GPP_InternalContext *pC = (M4PTO3GPP_InternalContext*)(pContext);
2030
2031    switch (encoderType)
2032    {
2033        case M4VE_kMpeg4VideoEnc:
2034        case M4VE_kH263VideoEnc:
2035            /* OK */
2036        break;
2037
2038        case M4VE_kH264VideoEnc:
2039            M4OSA_TRACE1_0("M4PTO3GPP_RegisterExternalVideoEncoder: \
2040                           H264 encoder type not implemented yet");
2041            return M4ERR_NOT_IMPLEMENTED;
2042        break;
2043
2044        default:
2045            M4OSA_TRACE1_1("M4PTO3GPP_RegisterExternalVideoEncoder:\
2046                           unknown encoderType %d", encoderType);
2047            return M4ERR_PARAMETER;
2048        break;
2049    }
2050
2051    pC->registeredExternalEncs[encoderType].pEncoderInterface = pEncoderInterface;
2052    pC->registeredExternalEncs[encoderType].pUserData = pUserData;
2053    pC->registeredExternalEncs[encoderType].registered = M4OSA_TRUE;
2054
2055    /* Notice it overwrites any HW encoder that may already have been registered for this type;
2056    this is normal. */
2057
2058    return M4NO_ERROR;
2059}
2060
2061