First public contribution.
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
17 #include <c3gplibrary.h>
19 #if defined (COMPOSE_DEBUG)
20 #define DEBUG_PRINT RDebug::Print
25 const TInt KMinWriteBufferMaxCount = 6;
26 _LIT(K3GPComposePanicName, "C3GPCompose");
28 // This is video base class containing common video properties.
29 T3GPVideoPropertiesBase::T3GPVideoPropertiesBase(T3GPVideoType aType,
30 TUint aTimescale, const TSize& aSize) :
31 iType(aType), iTimescale(aTimescale), iSize(aSize)
36 This structure stores the common and MPEG-4 video specific properties of video data.
38 @param aTimescale Timescale of the video data. This is the number of time units that
40 @param aSize Video width and height in pixels.
41 @param aMaxBitRate Maximum video bit rate.
42 @param aAvgBitRate Average video bit rate.
43 @param aDecoderSpecificInfo MPEG-4 video DecoderSpecificInfo data stored in an ESDS atom.
45 EXPORT_C T3GPVideoPropertiesMpeg4Video::T3GPVideoPropertiesMpeg4Video(TUint aTimescale,
46 const TSize& aSize, TUint aMaxBitRate, TUint aAvgBitRate, const TDesC8& aDecoderSpecificInfo) :
47 T3GPVideoPropertiesBase(E3GPMpeg4Video, aTimescale, aSize),
48 iMaxBitRate(aMaxBitRate),
49 iAvgBitRate(aAvgBitRate),
50 iDecoderSpecificInfo(aDecoderSpecificInfo)
55 This structure stores the common and H.263 specific properties of video data.
57 @param aTimescale Timescale of the video data. This is the number of time units that
59 @param aSize Video width and height in pixels.
60 @param aVideoLevel Indicates the H263 video level.
61 @param aProfile Indicates the H263 profile.
63 EXPORT_C T3GPVideoPropertiesH263::T3GPVideoPropertiesH263(TUint aTimescale, const TSize& aSize,
64 TInt aVideoLevel, TProfile aProfile) :
65 T3GPVideoPropertiesBase((aProfile == EProfile0) ? E3GPH263Profile0 : E3GPH263Profile3,
66 aTimescale, aSize), iVideoLevel(aVideoLevel)
71 This structure stores the common and AVC specific properties of video data.
73 @param aTimescale Timescale of the video data. This is the number of time units that
75 @param aSize Video width and height in pixels.
76 @param aDecoderSpecificInfo AVCDecoderConfigurationRecord data that will be stored in the avcC atom.
78 EXPORT_C T3GPVideoPropertiesAvc::T3GPVideoPropertiesAvc(TUint aTimescale, const TSize& aSize,
79 const TDesC8& aDecoderSpecificInfo) :
80 T3GPVideoPropertiesBase(E3GPAvcProfileBaseline, aTimescale, aSize),
81 iDecoderSpecificInfo(aDecoderSpecificInfo)
84 NOTE: Although Baseline profile is being set here, it's just used to indicate
85 the fact that we have AVC data. The underlying 3GP lib does not differentiate
86 between profiles when composing a file. It simply writes the contents of
87 iDecoderSpecificInfo (which contains the profile amongst other things)
88 verbatim into the "avcC" box.
92 // This is audio base class containing common audio properties.
93 T3GPAudioPropertiesBase::T3GPAudioPropertiesBase(T3GPAudioType aType,
94 TUint aTimescale, TInt aFramesPerSample) :
95 iType(aType), iTimescale(aTimescale), iFramesPerSample(aFramesPerSample)
97 __ASSERT_ALWAYS((aTimescale > 0) && (aTimescale <= KMaxTUint16), User::Panic(K3GPComposePanicName, KErrOverflow));
101 This structure stores the common and MPEG-4 audio-specific properties of audio data.
103 @param aTimescale Timescale of the audio data. This is the number of time units that pass in one
104 second. It must be smaller than 65536.
105 @param aDecoderSpecificInfo MPEG-4 audio DecoderSpecificInfo data stored in an ESDS atom.
107 EXPORT_C T3GPAudioPropertiesMpeg4Audio::T3GPAudioPropertiesMpeg4Audio(TUint aTimescale,
108 const TDesC8& aDecoderSpecificInfo) :
109 T3GPAudioPropertiesBase(E3GPMpeg4Audio, aTimescale, 0),
110 iDecoderSpecificInfo(aDecoderSpecificInfo)
115 This structure stores the common and AMR-specific properties of audio data.
117 @param aTimescale Timescale of the audio data. This is the number of time units that pass in one
118 second. It must be smaller than 65536.
119 @param aFramesPerSample Frames per sample. It must be smaller than 256.
120 MPEG-4 audio has a fixed value of 1.
121 @param aModeSet AMR mode set.
122 @param aCodec AMR Speech Codec.
124 EXPORT_C T3GPAudioPropertiesAmr::T3GPAudioPropertiesAmr(TUint aTimescale, TInt aFramesPerSample,
125 TInt aModeSet, TSpeechCodec aCodec) :
126 T3GPAudioPropertiesBase((aCodec == EAmrNB) ? E3GPAmrNB : E3GPAmrWB,
127 aTimescale, aFramesPerSample), iModeSet(aModeSet)
129 __ASSERT_ALWAYS((aFramesPerSample > 0) && (aFramesPerSample <= KMaxTUint8),
130 User::Panic(K3GPComposePanicName, KErrOverflow));
134 This structure stores the common and QCELP-specific properties of MPEG4 audio data. The storage mode is
135 automatically set to MPEG4 Audio Sample Description Box mode.
137 @param aTimescale Timescale of the audio data. This is the number of time units that pass in one
138 second. It must be smaller than 65536.
139 @param aFramesPerSample Frames per sample. It must be smaller than 512.
140 MPEG-4 audio has a fixed value of 1.
141 @param aDecoderSpecificInfo MPEG-4 audio decoder specific information data stored in an ESDS atom.
143 EXPORT_C T3GPAudioPropertiesQcelp::T3GPAudioPropertiesQcelp(TUint aTimescale, TInt aFramesPerSample,
144 const TDesC8& aDecoderSpecificInfo) :
145 T3GPAudioPropertiesBase(E3GPQcelp13K, aTimescale, aFramesPerSample),
146 iMode(E3GPMP4AudioDescriptionBox),
147 iDecoderSpecificInfo(aDecoderSpecificInfo)
149 __ASSERT_ALWAYS((aFramesPerSample > 0) && (aFramesPerSample <= KMaxTUint8),
150 User::Panic(K3GPComposePanicName, KErrOverflow));
154 This structure stores the common and QCELP-specific properties of audio data.
156 @param aTimescale Timescale of the audio data. This is the number of time units that pass in one
157 second. It must be smaller than 65536.
158 @param aFramesPerSample Frames per sample. It must be smaller than 512.
159 MPEG-4 audio has a fixed value of 1.
162 EXPORT_C T3GPAudioPropertiesQcelp::T3GPAudioPropertiesQcelp(TUint aTimescale, TInt aFramesPerSample) :
163 T3GPAudioPropertiesBase(E3GPQcelp13K, aTimescale, aFramesPerSample),
164 iMode(E3GPQcelpSampleEntryBox),
165 iDecoderSpecificInfo(KNullDesC8)
167 __ASSERT_ALWAYS((aFramesPerSample > 0) && (aFramesPerSample <= KMaxTUint8),
168 User::Panic(K3GPComposePanicName, KErrOverflow));
172 Create an instance of 3GP composer using default buffer count and size.
174 The default values for buffer count and size are as follow:
175 Write Buffer Size is 2048
176 Write Buffer Max Count is 15
178 @return A pointer to the newly created 3gp compose object.
180 @leave KErrGeneral General error.
181 @leave KErrNoMemory Out of memory.
183 @panic C3GPCompose KErrAbort if clients do not a CActiveScheduler installed already.
185 EXPORT_C C3GPCompose* C3GPCompose::NewL()
187 // Leave if no scheduler exists
188 __ASSERT_ALWAYS ((CActiveScheduler::Current() != NULL), Panic(KErrAbort));
189 C3GPCompose* self = new (ELeave) C3GPCompose();
194 Create an instance of 3GP composer, and let the user set a count limit and size of
195 internal buffer for composition.
197 The default values for buffer count and size are as follow:
198 Write Buffer Size is 2048
199 Write Buffer Max Count is 15
201 An increase of the buffer count and size will lead to a decrease of file I/O activities, thereby,
202 improves the performance of the 3GP Composer at the expense of higher memory usage.
204 @param aMediaWriteBufferSize Size of media data file output buffer (in bytes).
205 @param aWriteBufferMaxCount Maximum number of buffers (both media and meta) allowed before file
206 output changes to synchronous (by default file writing is asynchronous
207 operation). A minimum value of 6 is enforced.
209 @return A pointer to the newly created 3gp compose object.
211 @leave KErrGeneral General error.
212 @leave KErrNoMemory Out of memory.
214 @panic C3GPCompose KErrAbort if clients do not a CActiveScheduler installed already.
215 @panic C3GPCompose KErrArgument if Write Buffer Size is less or equal to 0 or Write Buffer Max Count is
218 EXPORT_C C3GPCompose* C3GPCompose::NewL(TInt aMediaWriteBufferSize, TInt aWriteBufferMaxCount)
220 __ASSERT_ALWAYS ((aMediaWriteBufferSize > 0 && aWriteBufferMaxCount >= KMinWriteBufferMaxCount),
221 Panic(KErrArgument));
222 // Leave if no scheduler exists
223 __ASSERT_ALWAYS ((CActiveScheduler::Current() != NULL), Panic(KErrAbort));
225 C3GPCompose* self = new (ELeave) C3GPCompose(aMediaWriteBufferSize, aWriteBufferMaxCount);
229 // First phase constructor
230 C3GPCompose::C3GPCompose(TInt aMediaWriteBufferSize, TInt aWriteBufferMaxCount) :
231 iMediaWriteBufferSize(aMediaWriteBufferSize),
232 iWriteBufferMaxCount(aWriteBufferMaxCount),
233 iDuplicateFileHandleCreated(EFalse)
238 This function initialises the 3GP composer for writing 3GP/3G2/MP4 data into a file.
239 Any combination of one video and one audio type is acceptable.
241 Note: Ownership of aVideo and aAudio remains with the caller. Both aVideo and aAudio are ready for
242 deletion after C3GPCompose::Open returns.
244 @param aFileFormat Specifies the file format in which the data will be created. Refer to
245 T3GPFileFormatType for supported file format types.
246 @param aVideo Specifies the video stream to be used for video data. The input data given will
247 be inserted into 3GP file headers and is ready to be disposed when
248 C3GPCompose::Open returns. See Video Properties Classes.
249 If aVideo is NULL, audio-only file will be composed.
250 @param aAudio Specifies the audio stream to be used for audio data. The input data given will
251 be inserted into 3GP file headers and is ready to be disposed when
252 C3GPCompose::Open returns. See Audio Properties Classes.
253 If aAudio is NULL, video-only file will be composed.
254 @param aFilename A full path name of the file to save the data to. An empty path is not allowed.
255 @param aFlags Optional flags for composing preferences. Refer to T3GPComposeFlag for supported flags.
256 The combined use of flags is acceptable. For example:
257 E3GPLongClip | E3GPMetaDataLast
259 @return KErrNone if successful. Otherwise, returns one of the system wide error codes.
260 KErrGeneral if an error has no specific categorisation;
261 KErrNoMemory if an attempt to allocate memory has failed;
262 KErrArgument if neither video nor audio stream is specified;
263 KErrAccessDenied if opening file has failed;
264 KErrUnderflow if the file name length is not greater than 0;
265 KErrInUse if the composer is currently engaged; C3GPCompose::Complete must be called to
266 finish the current composition before the composer can be re-initialised again.
268 EXPORT_C TInt C3GPCompose::Open(T3GPFileFormatType aFileFormat,
269 const T3GPVideoPropertiesBase* aVideo,
270 const T3GPAudioPropertiesBase* aAudio,
271 const TDesC& aFilename,
278 if (aFilename.Length() <= 0)
280 return KErrUnderflow;
282 if (!aVideo && !aAudio)
284 // if neither video nor audio is supplied
288 // Create a zero terminated version of the file name
290 TInt err = fileName.Create(aFilename.Length() + 1);
293 fileName.Copy(aFilename);
294 mp4_u16* mp4FileName = const_cast<mp4_u16*>(fileName.PtrZ());
295 MP4Err mp4Err = MP4ComposeOpen(&iHandler, reinterpret_cast<MP4FileName>(mp4FileName), Mp4Type(aVideo, aAudio));
297 if (mp4Err == MP4_OK)
299 // Write audio and video properties to the 3GP file
300 err = SetComposeProperties(aVideo, aAudio, aFileFormat, aFlags);
303 Complete(); // Ingore the error
308 err = SymbianOSError(mp4Err);
316 This function initialises the 3GP composer for writing 3GP/3G2/MP4 data into a file.
317 Any combination of one video and one audio type is acceptable.
319 Note: E3GPMetaDataLast will be defaulted in aFlags if file handle is used for the initialisation
322 Note: Ownership of aVideo and aAudio remains with the caller. Both aVideo and aAudio are ready for
323 deletion after C3GPCompose::Open returns.
325 @param aFileFormat Specifies the file format in which the data will be created. Refer to
326 T3GPFileFormatType for supported file format types.
327 @param aVideo Specifies the video stream to be used for video data. The input data given will
328 be inserted into 3GP file headers and is ready to be disposed when
329 C3GPCompose::Open returns. See Video Properties Classes.
330 If aVideo is NULL, audio-only file will be composed.
331 @param aAudio Specifies the audio stream to be used for audio data. The input data given will
332 be inserted into 3GP file headers and is ready to be disposed when
333 C3GPCompose::Open returns. See Audio Properties Classes.
334 If aAudio is NULL, video-only file will be composed.
335 @param aFile File handle of the file to save the data to. E3GPMetaDataLast needs to be set for
336 aFlags when this is used.
337 @param aFlags Optional flags for composing preferences. Refer to T3GPComposeFlag for supported flags.
338 The combined use of flags is acceptable. For example:
339 E3GPLongClip | E3GPMetaDataLast
341 @return KErrNone if successful. Otherwise, returns one of the system wide error codes.
342 KErrGeneral if an error has no specific categorisation;
343 KErrNoMemory if an attempt to allocate memory has failed;
344 KErrArgument if neither video nor audio stream is specified;
345 KErrAccessDenied if opening file has failed;
346 KErrInUse if the composer is currently engaged; C3GPCompose::Complete must be called to
347 finish the current composition before the composer can be re-initialised again.
350 EXPORT_C TInt C3GPCompose::Open(T3GPFileFormatType aFileFormat,
351 const T3GPVideoPropertiesBase* aVideo,
352 const T3GPAudioPropertiesBase* aAudio,
357 if (!iDuplicateFileHandleCreated)
359 iDuplicateFileHandleCreated = ETrue;
361 err = iFile.Duplicate(aFile);
368 return Open(aFileFormat, aVideo, aAudio, iFile, aFlags);
372 This function initialises the 3GP composer for writing 3GP/3G2/MP4 data into a file.
373 Any combination of one video and one audio type is acceptable.
375 Note: E3GPMetaDataLast will be defaulted in aFlags if file handle is used for the initialisation
378 Note: Ownership of aVideo and aAudio remains with the caller. Both aVideo and aAudio are ready for
379 deletion after C3GPCompose::Open returns.
381 @param aFileFormat Specifies the file format in which the data will be created. Refer to
382 T3GPFileFormatType for supported file format types.
383 @param aVideo Specifies the video stream to be used for video data. The input data given will
384 be inserted into 3GP file headers and is ready to be disposed when
385 C3GPCompose::Open returns. See Video Properties Classes.
386 If aVideo is NULL, audio-only file will be composed.
387 @param aAudio Specifies the audio stream to be used for audio data. The input data given will
388 be inserted into 3GP file headers and is ready to be disposed when
389 C3GPCompose::Open returns. See Audio Properties Classes.
390 If aAudio is NULL, video-only file will be composed.
391 @param aFile File handle of the file to save the data to. E3GPMetaDataLast needs to be set for
392 aFlags when this is used.
393 @param aFlags Optional flags for composing preferences. Refer to T3GPComposeFlag for supported flags.
394 The combined use of flags is acceptable. For example:
395 E3GPLongClip | E3GPMetaDataLast
397 @return KErrNone if successful. Otherwise, returns one of the system wide error codes.
398 KErrGeneral if an error has no specific categorisation;
399 KErrNoMemory if an attempt to allocate memory has failed;
400 KErrArgument if neither video nor audio stream is specified;
401 KErrAccessDenied if opening file has failed;
402 KErrInUse if the composer is currently engaged; C3GPCompose::Complete must be called to
403 finish the current composition before the composer can be re-initialised again.
405 EXPORT_C TInt C3GPCompose::Open(T3GPFileFormatType aFileFormat,
406 const T3GPVideoPropertiesBase* aVideo,
407 const T3GPAudioPropertiesBase* aAudio,
415 if (!aVideo && !aAudio)
417 // if neither video nor audio is supplied
421 TInt driveNumber = EDriveA;
422 TDriveInfo driveInfo;
423 TInt err = aFile.Drive(driveNumber, driveInfo);
426 MP4Err mp4Err = MP4ComposeOpenFileHandle64(&iHandler, &aFile, static_cast<TDriveNumber>(driveNumber), Mp4Type(aVideo, aAudio));
427 if (mp4Err == MP4_OK)
429 // Write audio and video properties to the 3GP file
430 err = SetComposeProperties(aVideo, aAudio, aFileFormat, aFlags);
433 Complete(); // Ingore the error
438 err = SymbianOSError(mp4Err);
447 Deletes all objects and releases all resource owned by this instance.
449 EXPORT_C C3GPCompose::~C3GPCompose()
451 Complete(); // Ignore the error
455 This function completes the composing operation. It frees the memory allocated by the library instance
456 and closes the output file.
458 It is necessary to call this function before the output file is guaranteed to be a valid output file
459 even though the file may exist prior to the call.
461 The composer can be reused again after this call, following another call to C3GPCompose::Open to
462 re-initialise the composer.
464 If C3GPCompose::Complete is called before the composer is initialised, it will be ignored and KErrNone
467 Although during destruction of C3GPCompose, this function will be automatically called, and no error
468 code will be returned. Therefore, when destroying the Composer object that you have used to compose a
469 file, you should ensure that data is committed to the file by invoking C3GPCompose::Complete before
470 destroying the Composer object.
472 @return KErrNone if successful. Otherwise, returns one of the system wide error codes.
473 KErrGeneral if an error has no specific categorisation;
474 KErrWrite if metadata could not be written.
476 EXPORT_C TInt C3GPCompose::Complete()
478 MP4Err mp4Err = MP4_OK;
481 mp4Err = MP4ComposeClose(iHandler);
483 // Always reset the class member data even this function returns error
485 return SymbianOSError(mp4Err);
488 // Helper function to reset class member data.
489 void C3GPCompose::Reset()
498 This function writes one video frame to the output file or buffer.
500 The frames must be inserted according to their causal sequence. Because the library doesn't analyze
501 the video bit stream, frames are inserted into the 3GP file in the same order as they are entered
502 with this function. Therefore, the frames will not be retrieved from the resulting 3GP file or
503 buffer correctly if they are not in proper order.
505 A frame inserted with this function call will result in one 3GP sample and one 3GP chunk.
507 The current frame's dependency information which is using default values (E3GPDependencyUnknown &
508 E3GPRedundancyUnknown) is inserted.
510 The data is available in the output file only after calling C3GPCompose::Complete. C3GPCompose::Complete
511 should be called exactly once when all audio and video data has been inserted into the library.
513 @param aBuffer The descriptor containing the video frame data to be written.
514 @param aDuration Duration of video frame in timescale, see T3GPVideoPropertiesBase.
515 @param aKeyFrame ETrue to indicate whether this frame is a key frame. EFalse otherwise.
517 @return KErrNone if successful. Otherwise, returns one of the system wide error codes.
518 KErrGeneral if an error has no specific categorisation;
519 KErrNotSupported if the composer is setup for an audio-only file;
520 KErrUnderflow if the supplied video frame buffer data is empty;
521 KErrNotReady if the composer has not yet been initialised; See C3GPCompose::Open.
523 EXPORT_C TInt C3GPCompose::WriteVideoFrame(const TDesC8& aBuffer, TUint aDuration, TBool aKeyFrame)
529 if (aBuffer.Length() <= 0)
531 return KErrUnderflow;
535 return KErrNotSupported;
538 // Insert video frame data
539 mp4_bool keyFrame = aKeyFrame;
540 mp4_u32 duration = aDuration;
541 MP4Err mp4Err = MP4ComposeWriteVideoFrame(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()), aBuffer.Length(), duration, keyFrame);
543 return SymbianOSError(mp4Err);
547 This function sets the current frame's dependency information to SDTP box and writes one video frame
550 The frames must be inserted according to their causal sequence. Because the library doesn't analyze
551 the video bit stream, frames are inserted into the 3GP file in the same order as they are entered
552 with this function. Therefore, the frames will not be retrieved from the resulting 3GP file or
553 buffer correctly if they are not in proper order.
555 A frame inserted with this function call will result in one 3GP sample and one 3GP chunk.
557 The data is available in the output file only after calling C3GPCompose::Complete. C3GPCompose::Complete
558 should be called exactly once when all audio and video data has been inserted into the library.
560 @param aBuffer The descriptor containing the video frame data to be written.
561 @param aDuration Duration of video frame in timescale, see T3GPVideoPropertiesBase.
562 @param aKeyFrame ETrue to indicate whether this frame is a key frame. EFalse otherwise.
563 @param aDependencies This specifies the current frame's dependency information.
564 The information will be supplied into the SDTP box.
565 See T3GPFrameDependencies.
567 @return KErrNone if successful. Otherwise, returns one of the system wide error codes.
568 KErrGeneral if an error has no specific categorisation;
569 KErrNotSupported if the composer is setup for an audio-only file;
570 KErrUnderflow if the supplied video frame buffer data is empty;
571 KErrNotReady if the composer has not yet been initialised; See C3GPCompose::Open.
573 EXPORT_C TInt C3GPCompose::WriteVideoFrame(const TDesC8& aBuffer, TUint aDuration, TBool aKeyFrame,
574 const T3GPFrameDependencies& aDependencies)
580 if (aBuffer.Length() <= 0)
582 return KErrUnderflow;
586 return KErrNotSupported;
589 // Insert the current frame's dependency information
590 MP4Err mp4Err = MP4ComposeWriteNextVideoFrameDependencies(iHandler, aDependencies.iDependsOn,
591 aDependencies.iIsDependedOn, aDependencies.iHasRedundancy);
593 if (mp4Err == MP4_OK)
595 // Insert video frame data
596 mp4_bool keyFrame = aKeyFrame;
597 mp4_u32 duration = aDuration;
598 mp4Err = MP4ComposeWriteVideoFrame(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()),
599 aBuffer.Length(), duration, keyFrame);
602 return SymbianOSError(mp4Err);
606 This function writes audio frames into the output file or buffer. The data is available in the
607 3GP output file only after calling C3GPCompose::Complete. C3GPCompose::Complete should be called exactly
608 once when all audio and video data has been inserted into the library.
611 This function writes one MPEG audio frame to the 3GP file.
613 For other audio types:
614 This function writes a number of audio frames to the 3GP file specified during composer setup
615 in the input parameter aAudio when calling C3GPCompose::Open. All audio frames inserted with
616 one function call will be placed inside one sample in the resulting file.
618 Note: Only the last call can have a different number of frames if the number is less than
619 the number of frames per sample specified during composer setup.
621 @see T3GPAudioPropertiesAmr
622 @see T3GPAudioPropertiesQcelp
624 @param aBuffer The descriptor containing the audio data to be written.
625 @param aDuration Duration of audio frames in timescale, see T3GPAudioPropertiesBase
627 @return KErrNone if successful. Otherwise, returns one of the system wide error codes.
628 KErrGeneral if an error has no specific categorisation;
629 KErrNotSupported if the composer is setup for a video-only file;
630 KErrUnderflow if the supplied audio frames buffer data is empty;
631 KErrNotReady if the composer has not yet been initialised; See C3GPCompose::Open.
633 EXPORT_C TInt C3GPCompose::WriteAudioFrames(const TDesC8& aBuffer, TUint aDuration)
639 if (aBuffer.Length() <= 0)
641 return KErrUnderflow;
645 return KErrNotSupported;
648 mp4_u32 duration = aDuration;
649 // use 0 for the number of frames since it is being ignored within the mp4 library implementation
650 MP4Err mp4Err = MP4ComposeWriteAudioFrames(iHandler, const_cast<mp4_u8*>(aBuffer.Ptr()),
651 aBuffer.Length(), 0, duration);
653 return SymbianOSError(mp4Err);
657 Writes a buffer containing whole atom to inside of user data atom (UDTA) defined in aLocation.
659 The buffer should contain an atom of structure that conforms to the definition of a "full box"
660 as specified in ISO/IEC 14496-12:2003: "Information technology – Coding of audio-visual objects
661 – Part 12: ISO base media file format."
663 For more information on user data atoms, see Section 8 – Asset Information of "3GPP TS 26.244
664 version 6.1.0 – 3GP file format (Rel 6)."
666 @param aLocation Specifies the location of user information to be written. Refer to
667 T3GPUdtaLocation for possible values.
668 @param aBuffer The descriptor containing the user information to write into file.
670 @return KErrNone if successful. Otherwise, returns one of the system wide error codes.
671 KErrGeneral if an error has no specific categorisation;
672 KErrArgument if asked aLocation is invalid;
673 KErrUnderflow if the supplied buffer data is empty;
674 KErrNotSupported if specify video track user data but no video type is specified,
675 or specify audio track user data but no audio type is specified
676 KErrNoMemory if an attempt to allocate memory has failed;
677 KErrNotReady if the composer has not yet been initialised; See C3GPCompose::Open.
679 @panic C3GPCompose KErrArgument if the location of user information is not of T3GPUdtaLocation.
681 EXPORT_C TInt C3GPCompose::SetUserData(T3GPUdtaLocation aLocation, const TDesC8& aBuffer)
687 if (aBuffer.Length() <= 0)
689 return KErrUnderflow;
691 if ((!iHasAudio && aLocation == E3GPUdtaAudioTrak) || (!iHasVideo && aLocation == E3GPUdtaVideoTrak))
693 return KErrNotSupported;
700 location = MP4_UDTA_MOOV;
702 case (E3GPUdtaVideoTrak):
703 location = MP4_UDTA_VIDEOTRAK;
705 case (E3GPUdtaAudioTrak):
706 location = MP4_UDTA_AUDIOTRAK;
713 mp4_u32 bufferSize = aBuffer.Length();
714 MP4Err mp4Err = MP4ComposeSetUserDataAtom(iHandler, location, const_cast<mp4_u8*>(aBuffer.Ptr()), bufferSize);
715 return SymbianOSError(mp4Err);
718 // Helper function to convert 3GP/MP4 library specific error codes to system wide error codes
719 TInt C3GPCompose::SymbianOSError(MP4Err aError)
721 TInt error = KErrNone;
730 case (MP4_OUT_OF_MEMORY):
731 error = KErrNoMemory;
733 case (MP4_FILE_ERROR):
734 error = KErrAccessDenied;
736 case (MP4_INVALID_TYPE):
737 error = KErrArgument;
739 case (MP4_METADATA_ERROR):
748 // Helper function to map 3GP enum type to MP4 audio and video type
749 mp4_u32 C3GPCompose::Mp4Type(const T3GPVideoPropertiesBase* aVideo, const T3GPAudioPropertiesBase* aAudio)
751 mp4_u32 videoType = MP4_TYPE_NONE;
752 mp4_u32 audioType = MP4_TYPE_NONE;
757 switch (aVideo->iType)
759 case (E3GPMpeg4Video):
760 videoType = MP4_TYPE_MPEG4_VIDEO;
762 case (E3GPH263Profile0):
763 videoType = MP4_TYPE_H263_PROFILE_0;
765 case (E3GPH263Profile3):
766 videoType = MP4_TYPE_H263_PROFILE_3;
770 * NOTE: The underlying 3GP library does
771 * not differentiate between the various AVC
772 * profiles when composing.
774 * In all cases it will simply copy the data
775 * from the iDecoderSpecificInfo member of
776 * T3GPVideoPropertiesAvc into the 'avcC' atom.
777 * It does not do any checking of that data, so
778 * it is the API user's responsibility to ensure
779 * that it contains a valid AVCDecoderConfigurationRecord
780 * with the correct AVC profile and level.
782 * An interesting side-effect of this is that you can
783 * compose AVC data with arbitrary profiles even if they
784 * are not "supported" by this API. For example, as long
785 * as the AVCDecoderConfigurationRecord says there is
786 * High 10 profile data and the AVC data is of that profile
787 * then you will still end up with a valid file.
789 case (E3GPAvcProfileBaseline):
790 videoType = MP4_TYPE_AVC_PROFILE_BASELINE;
792 case (E3GPAvcProfileMain):
793 videoType = MP4_TYPE_AVC_PROFILE_MAIN;
795 case (E3GPAvcProfileExtended):
796 videoType = MP4_TYPE_AVC_PROFILE_EXTENDED;
798 case (E3GPAvcProfileHigh):
799 videoType = MP4_TYPE_AVC_PROFILE_HIGH;
809 switch (aAudio->iType)
811 case (E3GPMpeg4Audio):
812 audioType = MP4_TYPE_MPEG4_AUDIO;
815 audioType = MP4_TYPE_AMR_NB;
818 audioType = MP4_TYPE_AMR_WB;
821 audioType = MP4_TYPE_QCELP_13K;
827 return (videoType | audioType);
830 // Helper function to set compose properties
831 TInt C3GPCompose::SetComposeProperties(const T3GPVideoPropertiesBase* aVideo,
832 const T3GPAudioPropertiesBase* aAudio, T3GPFileFormatType aFileFormat, TUint aFlag)
834 mp4_u32 writeBufferSize = iMediaWriteBufferSize;
835 mp4_u32 writeBufferMaxCount = iWriteBufferMaxCount;
836 MP4Err mp4Err = MP4SetCustomFileBufferSizes(iHandler, writeBufferSize, writeBufferMaxCount, 0);
837 if ( mp4Err != MP4_OK)
839 return SymbianOSError(mp4Err);
842 // Set compose flag before other MP4Compose functions
843 TInt err = SetComposeFlag(aFileFormat, aFlag);
851 switch (aVideo->iType)
853 case (E3GPMpeg4Video):
854 err = SetMPeg4VideoProperties(aVideo);
856 case (E3GPAvcProfileBaseline):
857 case (E3GPAvcProfileMain):
858 case (E3GPAvcProfileExtended):
859 case (E3GPAvcProfileHigh):
860 err = SetAvcVideoProperties(aVideo);
862 case (E3GPH263Profile0):
863 case (E3GPH263Profile3):
864 err = SetH263VideoProperties(aVideo);
877 switch (aAudio->iType)
879 case (E3GPMpeg4Audio):
880 err = SetMpeg4AudioProperties(aAudio);
883 err = SetQcelpAudioProperties(aAudio);
887 err = SetAmrAudioProperties(aAudio);
896 // Inform the 3GP library about the MPeg4 video data
897 TInt C3GPCompose::SetMPeg4VideoProperties(const T3GPVideoPropertiesBase* aVideo)
899 const T3GPVideoPropertiesMpeg4Video* mpeg4Video = static_cast<const T3GPVideoPropertiesMpeg4Video*>(aVideo);
901 MP4Err err = MP4ComposeWriteVideoDecoderSpecificInfo(iHandler, const_cast<mp4_u8*>(mpeg4Video->iDecoderSpecificInfo.Ptr()),
902 mpeg4Video->iDecoderSpecificInfo.Length());
906 err = MP4ComposeAddVideoDescription(iHandler, mpeg4Video->iTimescale,
907 mpeg4Video->iSize.iWidth, mpeg4Video->iSize.iHeight,
908 mpeg4Video->iMaxBitRate, mpeg4Video->iAvgBitRate);
911 return SymbianOSError(err);
914 // Inform the 3GP library about the AVC video data
915 TInt C3GPCompose::SetAvcVideoProperties(const T3GPVideoPropertiesBase* aVideo)
917 const T3GPVideoPropertiesAvc* avcVideo = static_cast<const T3GPVideoPropertiesAvc*>(aVideo);
919 MP4Err err = MP4ComposeWriteVideoDecoderSpecificInfo(iHandler, const_cast<mp4_u8*>(avcVideo->iDecoderSpecificInfo.Ptr()),
920 avcVideo->iDecoderSpecificInfo.Length ());
924 // aMaxBitRate and aAvgBitRate are MPEG-4 video specific values. Set 0 for them
925 err = MP4ComposeAddVideoDescription(iHandler, avcVideo->iTimescale,
926 avcVideo->iSize.iWidth, avcVideo->iSize.iHeight, 0, 0);
929 return SymbianOSError(err);
932 // Inform the 3GP library about the H263 video data
933 TInt C3GPCompose::SetH263VideoProperties(const T3GPVideoPropertiesBase* aVideo)
935 // aMaxBitRate and aAvgBitRate are MPEG-4 video specific values. Set 0 for H263 video
936 MP4Err err = MP4ComposeAddVideoDescription(iHandler, aVideo->iTimescale,
937 aVideo->iSize.iWidth, aVideo->iSize.iHeight, 0, 0);
941 const T3GPVideoPropertiesH263* h263Video = static_cast<const T3GPVideoPropertiesH263*>(aVideo);
942 TVideoClipProperties properties;
943 properties.iH263Level = h263Video->iVideoLevel;
944 err = MP4ComposeSetVideoClipProperties(iHandler, properties);
947 return SymbianOSError(err);
950 // Inform the 3GP library about the MPeg4 audio data
951 TInt C3GPCompose::SetMpeg4AudioProperties(const T3GPAudioPropertiesBase* aAudio)
953 const T3GPAudioPropertiesMpeg4Audio* mpeg4Audio = static_cast<const T3GPAudioPropertiesMpeg4Audio*>(aAudio);
955 MP4Err err = MP4ComposeWriteAudioDecoderSpecificInfo(iHandler, const_cast<mp4_u8*>(mpeg4Audio->iDecoderSpecificInfo.Ptr()),
956 mpeg4Audio->iDecoderSpecificInfo.Length ());
960 //modeSet is needed only for AMR audio. Set it to 0 for Mpeg4 audio.
961 err = MP4ComposeAddAudioDescription(iHandler, mpeg4Audio->iTimescale, mpeg4Audio->iFramesPerSample, 0);
964 return SymbianOSError(err);
967 // Inform the 3GP library about the Amr audio data
968 TInt C3GPCompose::SetAmrAudioProperties(const T3GPAudioPropertiesBase* aAudio)
970 const T3GPAudioPropertiesAmr* amrAudio = static_cast<const T3GPAudioPropertiesAmr*>(aAudio);
971 //modeSet is needed only for AMR audio.
972 MP4Err err = MP4ComposeAddAudioDescription(iHandler, amrAudio->iTimescale,
973 amrAudio->iFramesPerSample, amrAudio->iModeSet);
974 return SymbianOSError(err);
977 // Sets the storage mode of storing 13K QCELP data in a 3G2 file
978 TInt C3GPCompose::SetQcelpAudioProperties(const T3GPAudioPropertiesBase* aAudio)
980 const T3GPAudioPropertiesQcelp* qcelpAudio = static_cast<const T3GPAudioPropertiesQcelp*>(aAudio);
981 MP4Err err = MP4ComposeSetQCELPStorageMode(iHandler, qcelpAudio->iMode);
984 if ( qcelpAudio->iMode == E3GPMP4AudioDescriptionBox)
986 err = MP4ComposeWriteAudioDecoderSpecificInfo(iHandler, const_cast<mp4_u8*>(qcelpAudio->iDecoderSpecificInfo.Ptr()), qcelpAudio->iDecoderSpecificInfo.Length ());
990 //modeSet is needed only for AMR audio. Set it to 0 for Qcelp audio.
991 err = MP4ComposeAddAudioDescription(iHandler, qcelpAudio->iTimescale, qcelpAudio->iFramesPerSample, 0);
995 return SymbianOSError(err);
999 TInt C3GPCompose::SetComposeFlag(T3GPFileFormatType aFileFormat, TUint aFlag)
1001 mp4_u32 fileFormat = 0;
1002 switch (aFileFormat)
1005 fileFormat = MP4_FLAG_GENERATE_MP4;
1008 fileFormat = MP4_FLAG_GENERATE_3G2;
1011 fileFormat = MP4_FLAG_NONE;
1014 Panic(KErrArgument);
1017 MP4Err err = MP4ComposeSetFlags(iHandler, aFlag | fileFormat);
1018 return SymbianOSError(err);
1022 void C3GPCompose::Panic(TInt aPanic)
1025 User::Panic(K3GPComposePanicName, aPanic);