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