M4MP4W_Interface.c revision 947721ba962c19913b76658cdbb19ae8c77c9c50
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 ******************************************************************************
20 * @file    M4MP4W_Interface.c
21 * @brief    3GPP file writer interface
22 * @note    This implementation follows the common interface defined
23 *          in "M4WRITER_common.h".
24 ******************************************************************************
25*/
26
27#include "NXPSW_CompilerSwitches.h"
28
29/**
30 * OSAL includes */
31#include "M4OSA_Types.h"            /**< OSAL basic types definiton */
32#include "M4OSA_FileWriter.h"        /**< Include for OSAL file accesses implementation */
33#include "M4OSA_Memory.h"            /**< Include for OSAL memory accesses implementation */
34#include "M4OSA_Debug.h"            /**< OSAL debug tools */
35
36/**
37 * Writer includes */
38#include "M4WRITER_common.h"        /**< Definition of the writer common interface that
39                                          this module follows */
40
41#ifdef _M4MP4W_USE_CST_MEMORY_WRITER
42#include "M4MP4W_Types_CstMem.h"    /**< MP4/3GP core writer types */
43#include "M4MP4W_Writer_CstMem.h"    /**< MP4/3GP core writer functions */
44#else
45#include "M4MP4W_Types.h"            /**< MP4/3GP core writer types */
46#include "M4MP4W_Writer.h"            /**< MP4/3GP core writer functions */
47#endif /* _M4MP4W_USE_CST_MEMORY_WRITER */
48
49/**
50 * Specific errors for this module */
51#define M4WRITER_3GP_ERR_UNSUPPORTED_STREAM_TYPE \
52                M4OSA_ERR_CREATE(M4_ERR, M4WRITER_3GP, 0x000001)
53
54
55/**
56 ******************************************************************************
57 * structure    M4WRITER_3GP_InternalContext
58 * @brief        This structure defines the writer context (private)
59 * @note        This structure is used for all writer calls to store the context
60 ******************************************************************************
61*/
62typedef struct
63{
64    M4OSA_Context    pMP4Context;    /**< MP4 writer context */
65    M4OSA_UInt32    maxAUsizes;        /**< the maximum AU size possible */
66} M4WRITER_3GP_InternalContext;
67
68
69/******************************************************************************
70 * M4OSA_ERR M4WRITER_3GP_openWrite(M4WRITER_Context* pContext, void* pWhat,
71 *                                   M4OSA_FileWriterPointer* pFileWriterPointer)
72 * @brief    Open a writer session.
73 * @note
74 * @param    pContext:     (OUT) Execution context of the 3GP writer, allocated by this function.
75 * @param    outputFileDescriptor (IN)  Descriptor of the output file to create.
76 * @param    fileWriterFunction     (IN)  Pointer to structure containing the set of OSAL
77 *                                       file write functions.
78 * @param    tempFileDescriptor     (IN)  Descriptor of the temporary file to open
79 *                                        (NULL if not used)
80 * @param    fileReaderFunction     (IN)  Pointer to structure containing the set of OSAL file read
81 *                                      functions (NULL if not used)
82 * @return    M4NO_ERROR:  there is no error
83 * @return    M4ERR_ALLOC: there is no more available memory
84 * @return    M4ERR_PARAMETER: pContext or pFilePtrFct is M4OSA_NULL (debug only)
85 * @return    any error returned by the MP4 core writer openWrite (Its coreID is M4MP4_WRITER)
86 ******************************************************************************
87*/
88M4OSA_ERR M4WRITER_3GP_openWrite( M4WRITER_Context* pContext,
89                                  void* outputFileDescriptor,
90                                  M4OSA_FileWriterPointer* pFileWriterPointer,
91                                  void* tempFileDescriptor,
92                                  M4OSA_FileReadPointer* pFileReaderPointer )
93{
94    M4WRITER_3GP_InternalContext* apContext;
95    M4OSA_ERR err;
96
97    M4OSA_TRACE1_0("M4WRITER_3GP_openWrite");
98
99    /**
100     *    Check input parameters */
101    M4OSA_DEBUG_IF2((M4OSA_NULL == pContext),M4ERR_PARAMETER,
102         "M4WRITER_3GP_openWrite: pContext is M4OSA_NULL");
103    M4OSA_DEBUG_IF2((M4OSA_NULL == pFileWriterPointer),M4ERR_PARAMETER,
104         "M4WRITER_3GP_openWrite: pFileWriterPointer is M4OSA_NULL");
105
106    /**
107     *    Allocate memory for the context */
108    *pContext=M4OSA_NULL;
109    apContext = (M4WRITER_3GP_InternalContext*)M4OSA_malloc(
110                    sizeof(M4WRITER_3GP_InternalContext),
111                    M4WRITER_3GP,
112                    (M4OSA_Char *)"M4WRITER_3GP_InternalContext");
113
114    if (M4OSA_NULL == apContext)
115    {
116        M4OSA_TRACE1_0("M4WRITER_3GP_openWrite:\
117             unable to allocate context, returning M4ERR_ALLOC");
118        return (M4OSA_ERR)M4ERR_ALLOC;
119    }
120
121    /**
122     *    Reset context variables */
123    apContext->pMP4Context = M4OSA_NULL;
124    apContext->maxAUsizes = 0;
125
126    /**
127     *    Return the writer context */
128    *pContext = (M4WRITER_Context *)apContext;
129
130    /**
131     *    Launch the openWrite of the MP4 writer */
132    M4OSA_TRACE3_0("M4WRITER_3GP_openWrite: calling M4MP4W_openWrite()");
133
134    err = M4MP4W_openWrite(&apContext->pMP4Context, outputFileDescriptor,
135            pFileWriterPointer, tempFileDescriptor, pFileReaderPointer );
136
137    if (M4OSA_ERR_IS_ERROR(err))
138    {
139        M4OSA_TRACE1_1("M4WRITER_3GP_openWrite: "
140                       "M4MP4W_openWrite returns error 0x%x", err);
141    }
142
143    M4OSA_TRACE2_1("M4WRITER_3GP_openWrite: returning 0x%x", err);
144
145    return err;
146}
147
148
149/******************************************************************************
150 * M4OSA_ERR M4WRITER_3GP_startWriting(M4WRITER_Context pContext)
151 * @brief    Indicates to the writer that the setup session is ended and that
152 *          we will start to write.
153 * @note
154 * @param     pContext:   (IN) Execution context of the 3GP writer,
155 * @return    M4NO_ERROR: there is no error
156 * @return    M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only)
157 * @return    any error returned by the MP4 core writer startWriting (Its
158 *            coreID is M4MP4_WRITER)
159 ******************************************************************************
160*/
161M4OSA_ERR M4WRITER_3GP_startWriting(M4WRITER_Context pContext)
162{
163    M4WRITER_3GP_InternalContext* apContext =
164                (M4WRITER_3GP_InternalContext*)pContext;
165
166    M4OSA_ERR err;
167
168    M4OSA_TRACE1_1("M4WRITER_3GP_startWriting: pContext=0x%x", pContext);
169
170    /**
171     *    Check input parameter */
172    M4OSA_DEBUG_IF2((M4OSA_NULL == apContext),M4ERR_PARAMETER,
173         "M4WRITER_3GP_startWriting: pContext is M4OSA_NULL");
174
175    /**
176     *    Call the MP4 core writer */
177    M4OSA_TRACE3_0("M4WRITER_3GP_startWriting: calling M4MP4W_startWriting()");
178    err = M4MP4W_startWriting(apContext->pMP4Context);
179    if (M4OSA_ERR_IS_ERROR(err))
180    {
181        M4OSA_TRACE1_1("M4MP4W_startWriting returns error 0x%x", err);
182    }
183
184    M4OSA_TRACE2_1("M4WRITER_3GP_startWriting: returning 0x%x", err);
185    return err;
186}
187
188
189/******************************************************************************
190 * M4OSA_ERR M4WRITER_3GP_addStream(
191 *     M4WRITER_Context pContext,
192 *     M4SYS_StreamDescription *pStreamDescription)
193 * @brief     Add a stream (audio or video).
194 * @note      Decoder specific info properties are correctly set before calling
195 *            the core writer add function
196 * @param     pContext:   (IN) Execution context of the 3GP writer,
197 * @param     streamDescription:    (IN) stream description.
198 * @return    M4NO_ERROR: there is no error
199 * @return    M4ERR_PARAMETER: pContext or pStreamDescription is M4OSA_NULL
200 *            (debug only)
201 * @return    any error returned by the MP4 core writer addStream
202 *            (Its coreID is M4MP4_WRITER)
203 ******************************************************************************
204*/
205M4OSA_ERR M4WRITER_3GP_addStream(M4WRITER_Context pContext,
206                                 M4SYS_StreamDescription* pStreamDescription)
207{
208    M4WRITER_3GP_InternalContext *apContext =
209        (M4WRITER_3GP_InternalContext *)pContext;
210
211    M4OSA_ERR err;
212    M4WRITER_StreamVideoInfos *pVideoInfo = M4OSA_NULL;
213    M4WRITER_StreamAudioInfos *pAudioInfo = M4OSA_NULL;
214    M4MP4W_StreamIDsize sizeValue;
215
216    M4OSA_TRACE1_2("M4WRITER_3GP_addStream: pContext=0x%x, "
217                   "pStreamDescription=0x%x",
218                   pContext, pStreamDescription);
219
220    /**
221     *    Check input parameters */
222    M4OSA_DEBUG_IF2((M4OSA_NULL == apContext),M4ERR_PARAMETER,
223         "M4WRITER_3GP_addStream: pContext is M4OSA_NULL");
224    M4OSA_DEBUG_IF2((M4OSA_NULL == pStreamDescription),M4ERR_PARAMETER,
225         "M4WRITER_3GP_addStream: pStreamDescription is M4OSA_NULL");
226
227    /**
228     *    Adapt audio/video stream infos */
229    switch (pStreamDescription->streamType)
230    {
231        case M4SYS_kMPEG_4:
232        case M4SYS_kH264:
233        case M4SYS_kH263:
234            M4OSA_TRACE3_1("M4WRITER_3GP_addStream: "
235                    "adding a Video stream (streamType=0x%x)",
236                    pStreamDescription->streamType);
237            /**
238             *    Common descriptions */
239            pStreamDescription->streamID = VideoStreamID;    /**< The only values checked by our
240                                                                  core writer are streamID */
241            pStreamDescription->timeScale = 1000;            /**< and timeScale */
242
243/* Not recommended for video editing -> write explicitely the 'bitr' box into 'd263' */
244/* Rem : it is REL 5 of 3gpp documentation */
245//            /**
246//             * Average bit-rate must not be set in H263 to be compatible with Platform4 */
247//            if (M4SYS_kH263 == pStreamDescription->streamType)
248//            {
249//                pStreamDescription->averageBitrate = -1;
250//            }
251
252            /**
253             *    Decoder specific info */
254            pVideoInfo = (M4WRITER_StreamVideoInfos *)pStreamDescription->decoderSpecificInfo;
255            pStreamDescription->decoderSpecificInfoSize = pVideoInfo->Header.Size;
256            pStreamDescription->decoderSpecificInfo = (M4OSA_MemAddr32)pVideoInfo->Header.pBuf;
257            M4OSA_TRACE3_2("M4WRITER_3GP_addStream: Video: DSI=0x%x, DSIsize=%d",
258                 pVideoInfo->Header.pBuf, pVideoInfo->Header.Size);
259            break;
260
261        case M4SYS_kAMR:
262        case M4SYS_kAMR_WB:
263        case M4SYS_kAAC:
264        case M4SYS_kEVRC:
265            M4OSA_TRACE3_1("M4WRITER_3GP_addStream: adding an Audio stream (streamType=0x%x)",
266                 pStreamDescription->streamType);
267            /**
268             *    Common descriptions */
269            pStreamDescription->streamID = AudioStreamID;    /**< The only value checked by our
270                                                                 core writer is streamID */
271
272            /**
273             *    Decoder specific info */
274            pAudioInfo = (M4WRITER_StreamAudioInfos *)pStreamDescription->decoderSpecificInfo;
275            pStreamDescription->decoderSpecificInfoSize = pAudioInfo->Header.Size;
276            pStreamDescription->decoderSpecificInfo = (M4OSA_MemAddr32)pAudioInfo->Header.pBuf;
277            M4OSA_TRACE3_2("M4WRITER_3GP_addStream: Audio: DSI=0x%x, DSIsize=%d",
278                 pAudioInfo->Header.pBuf, pAudioInfo->Header.Size);
279            break;
280
281        default:
282            M4OSA_TRACE1_1("M4WRITER_3GP_addStream:\
283                 returning M4WRITER_3GP_ERR_UNSUPPORTED_STREAM_TYPE (streamType=0x%x)",
284                     pStreamDescription->streamType);
285            return (M4OSA_ERR)M4WRITER_3GP_ERR_UNSUPPORTED_STREAM_TYPE;
286            break;
287    }
288
289    /**
290     *    Call the MP4 core writer */
291    M4OSA_TRACE3_0("M4WRITER_3GP_addStream: calling M4MP4W_addStream()");
292    err = M4MP4W_addStream(apContext->pMP4Context,pStreamDescription);
293    if (M4OSA_ERR_IS_ERROR(err))
294    {
295        M4OSA_TRACE1_1("M4WRITER_3GP_addStream: M4MP4W_addStream returns error 0x%x", err);
296        M4OSA_TRACE1_1("M4WRITER_3GP_addStream: returning 0x%x", err);
297        return (err);
298    }
299
300    /**
301     *    For Video, set the M4MP4W_trackSize Option */
302    switch (pStreamDescription->streamType)
303    {
304        case M4SYS_kMPEG_4:
305        case M4SYS_kH264:
306        case M4SYS_kH263:
307            sizeValue.streamID = VideoStreamID;
308            sizeValue.height = (M4OSA_UInt16)(pVideoInfo->height);
309            sizeValue.width  = (M4OSA_UInt16)(pVideoInfo->width);
310            M4OSA_TRACE3_2("M4WRITER_3GP_addStream: Video: height=%d, width=%d",
311                 sizeValue.height, sizeValue.width);
312
313            M4OSA_TRACE3_0("M4WRITER_3GP_addStream: calling M4MP4W_setOption(M4MP4W_trackSize)");
314            err = M4MP4W_setOption( apContext->pMP4Context, M4MP4W_trackSize,
315                 (M4OSA_DataOption)&sizeValue);
316            if (M4OSA_ERR_IS_ERROR(err))
317            {
318                M4OSA_TRACE1_1("M4WRITER_3GP_addStream: M4MP4W_setOption returns error 0x%x",
319                     err);
320            }
321            break;
322        default:
323            break;
324    }
325
326    M4OSA_TRACE2_1("M4WRITER_3GP_addStream: returning 0x%x", err);
327    return err;
328}
329
330
331/******************************************************************************
332 * M4OSA_ERR M4WRITER_3GP_closeWrite(M4WRITER_Context pContext)
333 * @brief    Close the writer. The context is freed here.
334 * @note
335 * @param     pContext:   (IN) Execution context of the 3GP writer,
336 * @return    M4NO_ERROR: there is no error
337 * @return    M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only)
338 * @return    any error returned by the MP4 core writer closeWrite (Its coreID
339 *            is M4MP4_WRITER)
340 ******************************************************************************
341*/
342M4OSA_ERR M4WRITER_3GP_closeWrite(M4WRITER_Context pContext)
343{
344    M4WRITER_3GP_InternalContext* apContext=(M4WRITER_3GP_InternalContext*)pContext;
345    M4OSA_ERR err = M4NO_ERROR;
346
347    M4OSA_TRACE1_1("M4WRITER_3GP_closeWrite called with pContext=0x%x", pContext);
348
349    /**
350    *    Check input parameter */
351    M4OSA_DEBUG_IF2((M4OSA_NULL == apContext),M4ERR_PARAMETER,
352         "M4WRITER_3GP_closeWrite: pContext is M4OSA_NULL");
353
354    /**
355     *    Call the MP4 core writer */
356    if (M4OSA_NULL != apContext->pMP4Context)
357    {
358        M4OSA_TRACE3_0("M4WRITER_3GP_closeWrite: calling M4MP4W_closeWrite()");
359        err = M4MP4W_closeWrite(apContext->pMP4Context);
360        if (M4OSA_ERR_IS_ERROR(err))
361        {
362            M4OSA_TRACE1_1("M4WRITER_3GP_closeWrite: M4MP4W_closeWrite returns error 0x%x", err);
363        }
364    }
365
366    /**
367     *    Deallocate our own context */
368    M4OSA_free((M4OSA_MemAddr32)apContext);
369
370    M4OSA_TRACE2_1("M4WRITER_3GP_closeWrite: returning 0x%x", err);
371    return err;
372}
373
374
375/******************************************************************************
376 * M4OSA_ERR M4WRITER_3GP_setOption(
377 *        M4WRITER_Context pContext, M4OSA_UInt32 optionID,
378 *        M4OSA_DataOption optionValue)
379 * @brief     This function asks the writer to set the value associated with
380 *            the optionID. The caller is responsible for allocating/
381 *            de-allocating the memory of the value field.
382 * @note      The options handled by the component depend on the implementation
383 *            of the component.
384 * @param     pContext:     (IN) Execution context of the 3GP writer,
385 * @param     pptionId:     (IN) ID of the option to set.
386 * @param     OptionValue : (IN) Value of the option to set.
387 * @return    M4NO_ERROR: there is no error
388 * @return    M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only)
389 * @return    M4ERR_BAD_OPTION_ID: the ID of the option is not valid.
390 * @return    any error returned by the MP4 core writer setOption (Its coreID
391 *            is M4MP4_WRITER)
392 ******************************************************************************
393*/
394M4OSA_ERR M4WRITER_3GP_setOption(
395        M4WRITER_Context pContext, M4OSA_UInt32 optionID,
396        M4OSA_DataOption optionValue)
397{
398    M4WRITER_3GP_InternalContext* apContext =
399            (M4WRITER_3GP_InternalContext*)pContext;
400
401    M4OSA_ERR err = M4NO_ERROR;
402    M4MP4W_memAddr memval;
403    M4SYS_StreamIDValue optval;
404
405    M4OSA_TRACE2_3("M4WRITER_3GP_setOption: pContext=0x%x, optionID=0x%x,\
406         optionValue=0x%x", pContext, optionID, optionValue);
407
408    /**
409     *    Check input parameter */
410    M4OSA_DEBUG_IF2((M4OSA_NULL==apContext),M4ERR_PARAMETER,
411         "M4WRITER_3GP_setOption: pContext is M4OSA_NULL");
412
413    switch (optionID)
414    {
415        /**
416         *    Maximum Access Unit size */
417        case M4WRITER_kMaxAUSize:
418            M4OSA_TRACE2_0("setting M4WRITER_kMaxAUSize option");
419            err = M4MP4W_setOption(
420                    apContext->pMP4Context,M4MP4W_maxAUsize, optionValue);
421            if (M4OSA_ERR_IS_ERROR(err))
422            {
423                M4OSA_TRACE1_1("M4MP4W_setOption(M4MP4W_maxAUsize) "
424                               "returns error 0x%x", err);
425            }
426            break;
427        /**
428         *    Maximum chunck size */
429        case M4WRITER_kMaxChunckSize:
430            M4OSA_TRACE2_0("setting M4WRITER_kMaxChunckSize option");
431            err = M4MP4W_setOption(
432                apContext->pMP4Context,M4MP4W_maxChunkSize, optionValue);
433            if (M4OSA_ERR_IS_ERROR(err))
434            {
435                M4OSA_TRACE1_1("M4MP4W_setOption(M4MP4W_maxChunkSize)\
436                     returns error 0x%x", err);
437            }
438            break;
439        /**
440         *    File string signature */
441        case M4WRITER_kEmbeddedString:
442            M4OSA_TRACE2_0("setting M4WRITER_kEmbeddedString option");
443            /* The given M4OSA_DataOption must actually
444               be a text string */
445            memval.addr = (M4OSA_MemAddr32)optionValue;
446            /**< this is max string size copied by the core */
447            memval.size = 16;
448            err = M4MP4W_setOption(
449                apContext->pMP4Context,M4MP4W_embeddedString, &memval);
450            if (M4OSA_ERR_IS_ERROR(err))
451            {
452                M4OSA_TRACE1_1("M4MP4W_setOption(M4MP4W_embeddedString)\
453                     returns error 0x%x", err);
454            }
455            break;
456        /**
457         *    File integration tag */
458        case M4WRITER_kIntegrationTag:
459            M4OSA_TRACE2_0("setting M4WRITER_kIntegrationTag option");
460            /* The given M4OSA_DataOption must actually
461               be a text string */
462            memval.addr = (M4OSA_MemAddr32)optionValue;
463            /**< this is max string size copied by the core */
464            memval.size = strlen((const char *)optionValue);
465            err = M4MP4W_setOption(
466                apContext->pMP4Context,M4MP4W_integrationTag, &memval);
467            if (M4OSA_ERR_IS_ERROR(err))
468            {
469                M4OSA_TRACE1_1("M4MP4W_setOption(M4MP4W_integrationTag)"
470                               " returns error 0x%x", err);
471            }
472            break;
473        /**
474         *    File version signature */
475        case M4WRITER_kEmbeddedVersion:
476            M4OSA_TRACE2_0("setting M4WRITER_kEmbeddedVersion option");
477            /* The given M4OSA_DataOption must actually
478               be a version number */
479
480            /**< Here 0 means both streams */
481            optval.streamID = 0;
482            /**< version number */
483            optval.value = *(M4OSA_UInt32*)optionValue;
484            err = M4MP4W_setOption(
485                apContext->pMP4Context,M4MP4W_CamcoderVersion, &optval);
486            if (M4OSA_ERR_IS_ERROR(err))
487            {
488                M4OSA_TRACE1_1("M4MP4W_setOption(M4MP4W_CamcoderVersion)"
489                               " returns error 0x%x", err);
490            }
491            break;
492        /**
493         *    Some options are read-only */
494        case M4WRITER_kFileSize:
495        case M4WRITER_kFileSizeAudioEstimated:
496            M4OSA_TRACE2_1("trying to set a read-only option! (ID=0x%x)",
497                    optionID);
498            return (M4OSA_ERR)M4ERR_READ_ONLY;
499            break;
500        /**
501         *    Maximum filesize limitation */
502        case M4WRITER_kMaxFileSize:
503            M4OSA_TRACE2_0("setting M4WRITER_kMaxFileSize option");
504            err = M4MP4W_setOption(
505                apContext->pMP4Context,M4MP4W_maxFileSize, optionValue);
506            if (M4OSA_ERR_IS_ERROR(err))
507            {
508                M4OSA_TRACE1_1("M4MP4W_setOption(M4MP4W_maxFileSize)\
509                     returns error 0x%x", err);
510            }
511            break;
512
513        /**
514         *    Maximum file duration limitation */
515        case M4WRITER_kMaxFileDuration:
516            M4OSA_TRACE2_0("setting M4WRITER_kMaxFileDuration option");
517            err = M4MP4W_setOption(
518                apContext->pMP4Context,M4MP4W_maxFileDuration, optionValue);
519            if (M4OSA_ERR_IS_ERROR(err))
520            {
521                M4OSA_TRACE1_1("M4MP4W_setOption(M4WRITER_kMaxFileDuration)"
522                               " returns error 0x%x", err);
523            }
524            break;
525
526        /**
527         *    Set 'ftyp' atom */
528        case M4WRITER_kSetFtypBox:
529            M4OSA_TRACE2_0("setting M4WRITER_kSetFtypBox option");
530            err = M4MP4W_setOption(
531                apContext->pMP4Context, M4MP4W_setFtypBox, optionValue);
532            if (M4OSA_ERR_IS_ERROR(err))
533            {
534                M4OSA_TRACE1_1("M4MP4W_setOption(M4MP4W_setFtypBox)\
535                     returns error 0x%x", err);
536            }
537            break;
538
539        /**
540         *    Decoder Specific Info */
541        case M4WRITER_kDSI:
542            M4OSA_TRACE2_0("setting M4WRITER_kDSI option");
543            err = M4MP4W_setOption(
544                apContext->pMP4Context, M4MP4W_DSI, optionValue);
545            if (M4OSA_ERR_IS_ERROR(err))
546            {
547                M4OSA_TRACE1_1("M4MP4W_setOption(M4MP4W_DSI)\
548                     returns error 0x%x", err);
549            }
550            break;
551        /*+ H.264 Trimming  */
552        case M4WRITER_kMUL_PPS_SPS:
553            M4OSA_TRACE2_0("setting M4WRITER_kMUL_PPS_SPS option");
554            err = M4MP4W_setOption(
555                apContext->pMP4Context, M4MP4W_MUL_PPS_SPS, optionValue);
556            if (M4OSA_ERR_IS_ERROR(err))
557            {
558                M4OSA_TRACE1_1("M4MP4W_setOption(M4MP4W_DSI)\
559                     returns error 0x%x", err);
560            }
561            break;
562        /*- H.264 Trimming  */
563
564        /**
565         *    Unknown option */
566        default:
567            M4OSA_TRACE2_1("trying to set an unknown option!\
568                 (optionID=0x%x)", optionID);
569            return (M4OSA_ERR)M4ERR_BAD_OPTION_ID;
570            break;
571    }
572
573    M4OSA_TRACE3_1("M4WRITER_3GP_setOption: returning 0x%x", err);
574    return err;
575}
576
577
578/******************************************************************************
579 * M4OSA_ERR M4WRITER_3GP_getOption(
580 *     M4WRITER_Context pContext, M4OSA_UInt32 optionID,
581 *     M4OSA_DataOption optionValue)
582 * @brief     This function asks the writer to return the value associated with
583 *            the optionID. The caller is responsible for allocating/
584 *            de-allocating the memory of the value field.
585 * @note      The options handled by the component depend on the implementation
586 *            of the component.
587 * @param     pContext:     (IN) Execution context of the 3GP writer,
588 * @param     OptionId:      (IN) Id of the option to get.
589 * @param     pOptionValue: (OUT) Value of the option to get.
590 * @return    M4NO_ERROR: there is no error
591 * @return    M4ERR_PARAMETER: pContext is M4OSA_NULL (debug only)
592 * @return    M4ERR_BAD_OPTION_ID: the ID of the option is not valid.
593 * @return    M4ERR_NOT_IMPLEMENTED: This option is not implemented yet.
594 * @return    any error returned by the MP4 core writer getOption (Its coreID
595 *            is M4MP4_WRITER)
596 ******************************************************************************
597*/
598M4OSA_ERR M4WRITER_3GP_getOption(
599        M4WRITER_Context pContext, M4OSA_UInt32 optionID,
600        M4OSA_DataOption optionValue)
601{
602    M4WRITER_3GP_InternalContext* apContext =
603            (M4WRITER_3GP_InternalContext*)pContext;
604
605    M4OSA_ERR err;
606
607    M4OSA_TRACE2_3("M4WRITER_3GP_getOption: pContext=0x%x, optionID=0x%x,\
608         optionValue=0x%x", pContext, optionID, optionValue);
609
610    /**
611    *    Check input parameter */
612    M4OSA_DEBUG_IF2((M4OSA_NULL == apContext),M4ERR_PARAMETER,
613         "M4WRITER_3GP_getOption: pContext is M4OSA_NULL");
614
615    switch (optionID)
616    {
617        /**
618         *    Maximum Access Unit size */
619        case M4WRITER_kMaxAUSize:
620            M4OSA_TRACE2_0("getting M4WRITER_kMaxAUSize option");
621            err = M4MP4W_getOption(apContext->pMP4Context,M4MP4W_maxAUsize,
622                (M4OSA_DataOption*)&optionValue);
623            if (M4OSA_ERR_IS_ERROR(err))
624            {
625                M4OSA_TRACE1_1("M4MP4W_getOption(M4MP4W_maxAUsize)"
626                               " returns error 0x%x", err);
627            }
628            break;
629        /**
630         *    Maximum chunck size */
631        case M4WRITER_kMaxChunckSize:
632            M4OSA_TRACE2_0("getting M4WRITER_kMaxChunckSize option");
633            err = M4MP4W_getOption(apContext->pMP4Context,M4MP4W_maxChunkSize,
634                (M4OSA_DataOption*)&optionValue);
635            if (M4OSA_ERR_IS_ERROR(err))
636            {
637                M4OSA_TRACE1_1("M4MP4W_getOption(M4MP4W_maxChunkSize)\
638                     returns error 0x%x", err);
639            }
640            break;
641        /**
642         *    The file size option */
643        case M4WRITER_kFileSize:
644            M4OSA_TRACE2_0("getting M4WRITER_kFileSize option");
645            /* get the current file size */
646            err = M4MP4W_getCurrentFileSize(
647                apContext->pMP4Context, (M4OSA_UInt32*)optionValue);
648            if (M4OSA_ERR_IS_ERROR(err))
649            {
650                M4OSA_TRACE1_1("M4MP4W_getCurrentFileSize"
651                               " returns error 0x%x", err);
652            }
653            break;
654        /**
655         *    The file size with audio option has its own function call
656              in the MP4 core writer */
657        case M4WRITER_kFileSizeAudioEstimated:
658            M4OSA_TRACE2_0("getting M4WRITER_kFileSizeAudioEstimated option");
659            /* get the current file size ... */
660            err = M4MP4W_getCurrentFileSize(
661                apContext->pMP4Context, (M4OSA_UInt32*)optionValue);
662            if (M4OSA_ERR_IS_ERROR(err))
663            {
664                M4OSA_TRACE1_1("M4MP4W_getCurrentFileSize"
665                               " returns error 0x%x", err);
666            }
667            //no more needed 3gp writer has its own mecanism
668            ///* ... add the estimated next max AU size */
669            //*((M4OSA_UInt32*)optionValue) += apContext->maxAUsizes;
670            break;
671        /**
672         *    Unknown option */
673        default:
674            M4OSA_TRACE2_1("trying to get an unknown option!\
675                 (optionID=0x%x)", optionID);
676            return    (M4OSA_ERR)M4ERR_BAD_OPTION_ID;
677            break;
678    }
679
680    M4OSA_TRACE3_1("M4WRITER_3GP_getOption: returning 0x%x", err);
681    return err;
682}
683
684
685/******************************************************************************
686 * M4OSA_ERR M4WRITER_3GP_startAU(
687 *          M4WRITER_Context pContext, M4SYS_StreamID streamID,
688 *          M4SYS_AccessUnit* pAU)
689 * @brief     Prepare an Access Unit to be ready to store data
690 * @note
691 * @param     pContext: (IN) Execution context of the 3GP writer,
692 * @param     streamID: (IN) Id of the stream to which the Access Unit
693 *            is related.
694 * @param     pAU:      (IN/OUT) Access Unit to be prepared.
695 * @return    M4NO_ERROR: there is no error
696 * @return    M4ERR_PARAMETER: pContext or pAU is M4OSA_NULL (debug only)
697 * @return    M4ERR_BAD_STREAM_ID: streamID is not VideoStreamID nor
698 *            AudioStreamID (debug only)
699 * @return    any error returned by the MP4 core writer startAU (Its coreID
700 *            is M4MP4_WRITER)
701 ******************************************************************************
702*/
703M4OSA_ERR M4WRITER_3GP_startAU(
704        M4WRITER_Context pContext, M4SYS_StreamID streamID,
705        M4SYS_AccessUnit* pAU)
706{
707    M4WRITER_3GP_InternalContext* apContext =
708            (M4WRITER_3GP_InternalContext*)pContext;
709
710    M4OSA_ERR err;
711
712    M4OSA_TRACE2_3("M4WRITER_3GP_startAU: pContext=0x%x, streamID=%d, pAU=0x%x",
713         pContext, streamID, pAU);
714
715    /**
716     *    Check input parameter */
717    M4OSA_DEBUG_IF2((M4OSA_NULL == apContext), M4ERR_PARAMETER,
718         "M4WRITER_3GP_startAU: pContext is M4OSA_NULL");
719    M4OSA_DEBUG_IF2((M4OSA_NULL == pAU), M4ERR_PARAMETER,
720         "M4WRITER_3GP_startAU: pAU is M4OSA_NULL");
721    M4OSA_DEBUG_IF2(
722         ((VideoStreamID != streamID) && (AudioStreamID != streamID)),
723         M4ERR_BAD_STREAM_ID,
724         "M4WRITER_3GP_processAU: Wrong streamID");
725
726    /**
727     * Call the MP4 writer */
728    M4OSA_TRACE3_0("M4WRITER_3GP_startAU: calling M4MP4W_startAU()");
729    err = M4MP4W_startAU(apContext->pMP4Context, streamID, pAU);
730    if (M4OSA_ERR_IS_ERROR(err))
731    {
732        M4OSA_TRACE1_1("M4MP4W_startAU returns error 0x%x", err);
733    }
734
735    M4OSA_TRACE3_2("AU: dataAddress=0x%x, size=%d",
736         pAU->dataAddress, pAU->size);
737
738    /* Convert oversize to a request toward VES automaton */
739    if (M4WAR_MP4W_OVERSIZE == err)
740    {
741        err = M4WAR_WRITER_STOP_REQ;
742    }
743
744    M4OSA_TRACE3_1("M4WRITER_3GP_startAU: returning 0x%x", err);
745    return err;
746}
747
748
749/******************************************************************************
750 * M4OSA_ERR M4WRITER_3GP_processAU(
751 *          M4WRITER_Context pContext, M4SYS_StreamID streamID,
752 *          M4SYS_AccessUnit* pAU)
753 * @brief     Write an Access Unit
754 * @note
755 * @param     pContext: (IN) Execution context of the 3GP writer,
756 * @param     streamID: (IN) Id of the stream to which the Access Unit
757 *            is related.
758 * @param     pAU:      (IN/OUT) Access Unit to be written
759 * @return    M4NO_ERROR: there is no error
760 * @return    M4ERR_PARAMETER: pContext or pAU is M4OSA_NULL (debug only)
761 * @return    M4ERR_BAD_STREAM_ID: streamID is not VideoStreamID nor
762 *            AudioStreamID (debug only)
763 * @return    any error returned by the MP4 core writer processAU
764 *            (Its coreID is M4MP4_WRITER)
765 ******************************************************************************
766*/
767M4OSA_ERR M4WRITER_3GP_processAU(
768        M4WRITER_Context pContext, M4SYS_StreamID streamID,
769        M4SYS_AccessUnit* pAU)
770{
771    M4WRITER_3GP_InternalContext* apContext =
772        (M4WRITER_3GP_InternalContext*)pContext;
773
774    M4OSA_ERR err;
775
776    M4OSA_TRACE2_3("M4WRITER_3GP_processAU: "
777                   "pContext=0x%x, streamID=%d, pAU=0x%x",
778                    pContext, streamID, pAU);
779
780    /**
781     *    Check input parameter */
782    M4OSA_DEBUG_IF2((M4OSA_NULL == apContext), M4ERR_PARAMETER,
783         "M4WRITER_3GP_processAU: pContext is M4OSA_NULL");
784    M4OSA_DEBUG_IF2((M4OSA_NULL == pAU), M4ERR_PARAMETER,
785         "M4WRITER_3GP_processAU: pAU is M4OSA_NULL");
786    M4OSA_DEBUG_IF2(
787         ((VideoStreamID != streamID) && (AudioStreamID != streamID)),
788         M4ERR_BAD_STREAM_ID,
789         "M4WRITER_3GP_processAU: Wrong streamID");
790
791    M4OSA_TRACE3_4("M4WRITER_3GP_processAU: AU: "
792         "dataAddress=0x%x, size=%d, CTS=%d, nbFrag=%d",
793         pAU->dataAddress, pAU->size, (M4OSA_UInt32)pAU->CTS, pAU->nbFrag);
794
795    if(pAU->size > apContext->maxAUsizes)
796    {
797        apContext->maxAUsizes = pAU->size;
798    }
799    /**
800     * Call the MP4 writer */
801    M4OSA_TRACE3_0("M4WRITER_3GP_processAU: calling M4MP4W_processAU()");
802    err = M4MP4W_processAU(apContext->pMP4Context, streamID, pAU);
803    if (M4OSA_ERR_IS_ERROR(err))
804    {
805        M4OSA_TRACE1_1("M4MP4W_processAU returns error 0x%x", err);
806    }
807
808    /* Convert oversize to a request toward VES automaton */
809    if(M4WAR_MP4W_OVERSIZE == err)
810    {
811        err = M4WAR_WRITER_STOP_REQ;
812    }
813
814    M4OSA_TRACE3_1("M4WRITER_3GP_processAU: returning 0x%x", err);
815    return err;
816}
817
818
819/******************************************************************************
820 * M4OSA_ERR M4WRITER_3GP_getInterfaces(
821 *      M4WRITER_OutputFileType* Type,
822 *      M4WRITER_GlobalInterface** SrcGlobalInterface,
823 *      M4WRITER_DataInterface** SrcDataInterface)
824 * @brief     Get the 3GPP writer common interface
825 * @note      Retrieves the set of functions needed to use the 3GPP writer.
826 *            It follows the common writer interface.
827 * @param     Type: (OUT) return the type of this writer. Will always be
828 *            M4WRITER_k3GPP.
829 * @param     SrcGlobalInterface: (OUT) Main set of function to use this
830 *            3GPP writer
831 * @param     SrcDataInterface:   (OUT) Set of function related to datas
832 *            to use this 3GPP writer
833 * @return    M4NO_ERROR: there is no error
834 * @return    M4ERR_ALLOC: there is no more available memory
835 * @return    M4ERR_PARAMETER: At least one of the parameters is M4OSA_NULL
836 *            (debug only)
837 ******************************************************************************
838*/
839M4OSA_ERR M4WRITER_3GP_getInterfaces(
840        M4WRITER_OutputFileType* Type,
841        M4WRITER_GlobalInterface** SrcGlobalInterface,
842        M4WRITER_DataInterface** SrcDataInterface)
843{
844    M4WRITER_GlobalInterface *pGlobal;
845    M4WRITER_DataInterface *pData;
846
847    M4OSA_TRACE2_3("M4WRITER_3GP_getInterfaces: "
848         "Type=0x%x, SrcGlobalInterface=0x%x,\
849         SrcDataInterface=0x%x", Type, SrcGlobalInterface, SrcDataInterface);
850
851    /**
852     *    Check input parameter */
853    M4OSA_DEBUG_IF2((M4OSA_NULL == Type), M4ERR_PARAMETER,
854         "M4WRITER_3GP_getInterfaces: Type is M4OSA_NULL");
855    M4OSA_DEBUG_IF2((M4OSA_NULL == SrcGlobalInterface), M4ERR_PARAMETER,
856         "M4WRITER_3GP_getInterfaces: SrcGlobalInterface is M4OSA_NULL");
857    M4OSA_DEBUG_IF2((M4OSA_NULL == SrcDataInterface), M4ERR_PARAMETER,
858         "M4WRITER_3GP_getInterfaces: SrcDataInterface is M4OSA_NULL");
859
860    /**
861     *    Set the output type */
862    *Type = M4WRITER_k3GPP;
863
864    /**
865     *    Allocate the global interface structure */
866    pGlobal = (M4WRITER_GlobalInterface*)M4OSA_malloc(
867                sizeof(M4WRITER_GlobalInterface),
868                M4WRITER_3GP, (M4OSA_Char *)"M4WRITER_GlobalInterface");
869    if (M4OSA_NULL == pGlobal)
870    {
871        M4OSA_TRACE1_0("unable to allocate M4WRITER_GlobalInterface,\
872             returning M4ERR_ALLOC");
873        *SrcGlobalInterface = M4OSA_NULL;
874        *SrcDataInterface = M4OSA_NULL;
875        return (M4OSA_ERR)M4ERR_ALLOC;
876    }
877
878    /**
879     *    Allocate the data interface structure */
880    pData =
881        (M4WRITER_DataInterface *)M4OSA_malloc(sizeof(M4WRITER_DataInterface),
882        M4WRITER_3GP, (M4OSA_Char *)"M4WRITER_DataInterface");
883    if (M4OSA_NULL == pData)
884    {
885        M4OSA_TRACE1_0("unable to allocate M4WRITER_DataInterface,\
886             returning M4ERR_ALLOC");
887        M4OSA_free((M4OSA_MemAddr32)pGlobal);
888        *SrcGlobalInterface = M4OSA_NULL;
889        *SrcDataInterface = M4OSA_NULL;
890        return (M4OSA_ERR)M4ERR_ALLOC;
891    }
892
893    /**
894     *    Fill the global interface structure */
895    pGlobal->pFctOpen = M4WRITER_3GP_openWrite;
896    pGlobal->pFctAddStream = M4WRITER_3GP_addStream;
897    pGlobal->pFctStartWriting = M4WRITER_3GP_startWriting;
898    pGlobal->pFctCloseWrite = M4WRITER_3GP_closeWrite;
899    pGlobal->pFctSetOption = M4WRITER_3GP_setOption;
900    pGlobal->pFctGetOption = M4WRITER_3GP_getOption;
901
902    /**
903     *    Fill the data interface structure */
904    pData->pStartAU = M4WRITER_3GP_startAU;
905    pData->pProcessAU = M4WRITER_3GP_processAU;
906
907    /**
908     *    Set the return values */
909    *SrcGlobalInterface = pGlobal;
910    *SrcDataInterface = pData;
911
912    M4OSA_TRACE2_0("M4WRITER_3GP_getInterfaces: returning M4NO_ERROR");
913    return M4NO_ERROR;
914}
915
916