diff -r 951a5db380a0 -r d87d32eab1a9 videoeditorengine/vedengine/videoprocessor/src/mp4composer.cpp --- a/videoeditorengine/vedengine/videoprocessor/src/mp4composer.cpp Fri Jan 29 14:08:33 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,796 +0,0 @@ -/* -* Copyright (c) 2010 Ixonos Plc. -* All rights reserved. -* This component and the accompanying materials are made available -* under the terms of the "Eclipse Public License v1.0" -* which accompanies this distribution, and is available -* at the URL "http://www.eclipse.org/legal/epl-v10.html". -* -* Initial Contributors: -* Nokia Corporation - Initial contribution -* -* Contributors: -* Ixonos Plc -* -* Description: -* -*/ - - -//FC Based on Cmp4parser - - -// INCLUDE FILES -#include -#include "mp4composer.h" -#include "vedvideosettings.h" -#include "vedavcedit.h" - - -// ASSERTIONS -//#define MPASSERT(x) __ASSERT_DEBUG(x, User::Panic(_L("CVideoProcessorImpl"), EInternalAssertionFailure)) - - -// MACROS -//#define ?macro ?macro_def - -#ifdef _DEBUG -#include -#define PRINT(x) RDebug::Print x; -#else -#define PRINT(x) -#endif - -// LOCAL CONSTANTS AND MACROS - -const TUint KFreeDiskSpaceCounter = 10; // Interval when to find out real free disk space -const TUint KMaxComposeBufferSize = 512000; // : Adjust buffer size dynamically - -#ifdef _DEBUG -const TInt KLeaveCode = CComposer::EComposerFailure; -#else -const TInt KLeaveCode = KErrGeneral; -#endif - -// ============================= LOCAL FUNCTIONS =============================== - -// ----------------------------------------------------------------------------- -// RateIndex: converts sample rate to rate index used in decoder config info -// ----------------------------------------------------------------------------- -// -static TUint8 RateIndex(TInt aRate) - { - switch ( aRate ) - { - case 96000: - return 0x0; - case 88200: - return 0x1; - case 64000: - return 0x2; - case 48000: - return 0x3; - case 44100: - return 0x4; - case 32000: - return 0x5; - case 24000: - return 0x6; - case 22050: - return 0x7; - case 16000: - return 0x8; - case 12000: - return 0x9; - case 11025: - return 0xa; - case 8000: - return 0xb; - case 7350: - return 0xc; - default: - return 0xf; - } - } - - -// ================= MEMBER FUNCTIONS ======================= - -// C++ default constructor can NOT contain any code, that -// might leave. -// - -CMP4Composer::CMP4Composer() -{ - iMP4Handle = 0; - iFreeDiskSpace = 0; - iFreeDiskSpaceCounter = 0; - iFirstWrite = ETrue; - iFsOpened = EFalse; -} - -// Two-phased constructor. -CMP4Composer* CMP4Composer::NewL(const TDesC &aFileName, - CParser::TVideoFormat aVideoFormat, - CParser::TAudioFormat aAudioFormat, - CVedAVCEdit *aAvcEdit) -{ - CMP4Composer *self = new (ELeave) CMP4Composer; - CleanupStack::PushL(self); - self->ConstructL(aFileName, aVideoFormat, aAudioFormat, aAvcEdit); - CleanupStack::Pop(); // self - return self; -} - -CMP4Composer* CMP4Composer::NewL(RFile* aFileHandle, - CParser::TVideoFormat aVideoFormat, - CParser::TAudioFormat aAudioFormat, - CVedAVCEdit *aAvcEdit) -{ - CMP4Composer *self = new (ELeave) CMP4Composer; - CleanupStack::PushL(self); - self->ConstructL(aFileHandle, aVideoFormat, aAudioFormat, aAvcEdit); - CleanupStack::Pop(); // self - return self; -} - -// Symbian OS default constructor can leave. -void CMP4Composer::ConstructL(const TDesC &aFileName, - CParser::TVideoFormat aVideoFormat, - CParser::TAudioFormat aAudioFormat, - CVedAVCEdit *aAvcEdit) -{ - TUint mediaType = 0; - - iOutputMovieFileName = TFileName(aFileName); - iFileHandle = NULL; - - iAvcEdit = aAvcEdit; - - // open MP4 library - - TBuf<258> temp(aFileName); - temp.ZeroTerminate(); - - MP4FileName name = reinterpret_cast( const_cast(temp.Ptr()) ); - - SetMediaOptions(aVideoFormat, aAudioFormat, mediaType); - - MP4Err error; - - // if the filename length is greater 0, then compose to file else buffer - if(aFileName.Length() > 0) - { - error = MP4ComposeOpen(&iMP4Handle, name, mediaType); - } - else - { - // initialize to compose to buffer - iComposeBuffer = (TUint8*)HBufC::NewL( KMaxComposeBufferSize ); - iComposedSize = KMaxComposeBufferSize; - error = MP4ComposeOpenToBuffer(&iMP4Handle, mediaType,(mp4_u8*)iComposeBuffer,&iComposedSize); - } - - if ( error != MP4_OK ) - User::Leave(KLeaveCode); - - SetComposerOptionsL(aVideoFormat, aAudioFormat); - -} - -void CMP4Composer::ConstructL(RFile* aFileHandle, - CParser::TVideoFormat aVideoFormat, - CParser::TAudioFormat aAudioFormat, - CVedAVCEdit *aAvcEdit) -{ - TUint mediaType = 0; - - iOutputMovieFileName.Zero(); - iFileHandle = aFileHandle; - - iAvcEdit = aAvcEdit; - - SetMediaOptions(aVideoFormat, aAudioFormat, mediaType); - - // open MP4 library - MP4Err error; - - error = MP4ComposeOpenFileHandle(&iMP4Handle, aFileHandle, EDriveC, mediaType); - - if ( error != MP4_OK ) - User::Leave(KLeaveCode); - - SetComposerOptionsL(aVideoFormat, aAudioFormat); - -} - - -void CMP4Composer::SetMediaOptions(CParser::TVideoFormat aVideoFormat, - CParser::TAudioFormat aAudioFormat, - TUint& aMediaFlags) - -{ - - if ( (aVideoFormat == CParser::EVideoFormatH263Profile0Level10) || - (aVideoFormat == CParser::EVideoFormatH263Profile0Level45) ) - { - aMediaFlags = MP4_TYPE_H263_PROFILE_0; - iVideoType = MP4_TYPE_H263_PROFILE_0; - } - -#ifdef VIDEOEDITORENGINE_AVC_EDITING - else if (aVideoFormat == CParser::EVideoFormatAVCProfileBaseline) - { - aMediaFlags = MP4_TYPE_AVC_PROFILE_BASELINE; - iVideoType = MP4_TYPE_AVC_PROFILE_BASELINE; - } -#endif - else - { - aMediaFlags = MP4_TYPE_MPEG4_VIDEO; - iVideoType = MP4_TYPE_MPEG4_VIDEO; - } - - if ( aAudioFormat == CParser::EAudioFormatAMR ) - { - aMediaFlags |= MP4_TYPE_AMR_NB; - iAudioType = MP4_TYPE_AMR_NB; - } - - else if ( aAudioFormat == CParser::EAudioFormatAAC ) - { - aMediaFlags |= MP4_TYPE_MPEG4_AUDIO; // added for AAC support. - iAudioType = MP4_TYPE_MPEG4_AUDIO; - } - -} - -void CMP4Composer::SetComposerOptionsL(CParser::TVideoFormat aVideoFormat, - CParser::TAudioFormat aAudioFormat) -{ - - MP4Err error; - - TBool videoMpeg4OrAvc = ( aVideoFormat == CParser::EVideoFormatMPEG4 || - aVideoFormat == CParser::EVideoFormatAVCProfileBaseline ); - - mp4_u32 flags = 0; - flags |= MP4_FLAG_LARGEFILEBUFFER; // Note: What does this do when using RFile ? - flags |= MP4_FLAG_METADATALAST; - - // generate MP4 file format if MPEG-4/AVC video & AAC audio - if ( (videoMpeg4OrAvc && aAudioFormat == CParser::EAudioFormatAAC) || - (videoMpeg4OrAvc && aAudioFormat == CParser::EAudioFormatNone) || - (aVideoFormat == CParser::EVideoFormatNone && aAudioFormat == CParser::EAudioFormatAAC) ) - { - flags |= MP4_FLAG_GENERATE_MP4; - } - - error = MP4ComposeSetFlags(iMP4Handle, flags); - - if (error != MP4_OK) - if (error == MP4_OUT_OF_MEMORY) - { - User::LeaveNoMemory(); - } - else - { - User::Leave(KLeaveCode); - } - - // set buffer sizes; only composer buffer settings are effective for this instance - error = MP4SetCustomFileBufferSizes(iMP4Handle, K3gpMp4ComposerWriteBufferSize, K3gpMp4ComposerNrOfWriteBuffers, K3gpMp4ParserReadBufferSize ); - - if (error == MP4_OUT_OF_MEMORY) - { - User::Leave(KErrNoMemory); - } - else if ( error != MP4_OK ) - { - User::Leave(KLeaveCode); - } -} - - -// Destructor -CMP4Composer::~CMP4Composer() -{ - if (iMP4Handle) - { - MP4ComposeClose(iMP4Handle); - } - - if(iComposeBuffer) // added for Buffer support - { - User::Free(iComposeBuffer); - iComposeBuffer=0; - } - - iMP4Handle = 0; - - if (iFsOpened) - { - iFS.Close(); - iFsOpened = EFalse; - } - - -} - -// --------------------------------------------------------- -// CMP4Composer::WriteFrames -// Write the next frame(s) to file -// --------------------------------------------------------- -// -TInt CMP4Composer::WriteFrames(TDesC8& aSrcBuffer, TInt aFrameSize, - TInt aDuration, TInt aKeyFrame, - TInt aNumberOfFrames, TInt aFrameType) -{ - MP4Err error = KErrNone; - - // get the parameters - TUint32 frameSize = aFrameSize; - TUint32 duration = aDuration; - mp4_bool keyframe = (mp4_bool)aKeyFrame; - TInt numberOfFrames = aNumberOfFrames; - TFrameType frameType = (aFrameType>0 ? (aFrameType==1 ? EFrameTypeAudio : EFrameTypeVideo) - : EFrameTypeNone); - - if (frameType == EFrameTypeVideo) - { - error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(aSrcBuffer.Ptr()), - frameSize, duration, keyframe); - if ( error != MP4_OK ) - return KLeaveCode; - } - - else if (frameType == EFrameTypeAudio) - { - error = MP4ComposeWriteAudioFrames(iMP4Handle,(mp4_u8*)(aSrcBuffer.Ptr()), - frameSize, numberOfFrames, duration); - if ( error != MP4_OK ) - return KLeaveCode; - } - else - User::Panic(_L("CMovieProcessorImpl"), EComposerFailure); - - return KErrNone; - -} - - -TInt CMP4Composer::WriteFrames(TDesC8& aSrcBuffer, TInt aFrameSize, - TInt aDuration, TInt aKeyFrame, - TInt aNumberOfFrames, TInt aFrameType, - TInt& aMP4Size, TBool aModeChanged, - TBool aFirstFrameOfClip, TInt aMode, TBool /*aFromEncoder*/) -{ - MP4Err error = KErrNone; - - // get the parameters - TUint32 frameSize = aFrameSize; - TUint32 duration = aDuration; - mp4_bool keyframe = ( aKeyFrame ) ? ETrue : EFalse; - TInt numberOfFrames = aNumberOfFrames; - TFrameType frameType = (aFrameType > 0 ? (aFrameType == 1 ? EFrameTypeAudio : EFrameTypeVideo) - : EFrameTypeNone); - TUint8* dataPtr = (TUint8*)(aSrcBuffer.Ptr()); - TInt tmpSize = 0; - - // call this only for the first frame of every clip - if ( aFirstFrameOfClip && (iVideoType == MP4_TYPE_MPEG4_VIDEO) && (aMP4Size == 0)) - { - if ((tmpSize = GetMp4SpecificSize(aSrcBuffer,aModeChanged,aMode)) != 0) - aMP4Size = tmpSize; //This will be the new Mp4Size as it will be consider and since by reference it is maintained - } - - if (frameType == EFrameTypeVideo) - { - if ( iVideoType == MP4_TYPE_MPEG4_VIDEO ) - { - if ( iFirstWrite ) - { - // VOS - error = MP4ComposeWriteVideoDecoderSpecificInfo( iMP4Handle, - (mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/), aMP4Size ); - iFirstWrite = EFalse; - - error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/ + aMP4Size), - ( frameSize - aMP4Size ), duration, keyframe); - } - else - { - // for MPEG4 - check the first 32 bits to make sure we don't - // have VOS pre-pended to VOP data - if (dataPtr[0] == 0x00 && dataPtr[1] == 0x00 && dataPtr[2] == 0x01 && dataPtr[3] == 0xb0) - { // since intermediate Vos set to proper value - // Not Short Header may have User Data space problem with PSC - if ((tmpSize = GetMp4SpecificSize(aSrcBuffer,aModeChanged,aMode)) != 0) - aMP4Size = tmpSize; //This will be the new Mp4Size as it will be considered - dataPtr += aMP4Size; - frameSize -= aMP4Size; - } - - if (frameSize == 0) - return KErrWrite; - - error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr), - frameSize, duration, keyframe); - } - } - -#ifdef VIDEOEDITORENGINE_AVC_EDITING - else if ( iVideoType == MP4_TYPE_AVC_PROFILE_BASELINE ) - { - - if ( iFirstWrite || aFirstFrameOfClip) - { - if(iFirstWrite) - { - iFrameNumber = 0; - iFirstWrite = EFalse; - } - - aMP4Size = 0; - error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/ + aMP4Size), - ( frameSize - aMP4Size ), duration, keyframe); - } - else - { - error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr), - frameSize, duration, keyframe); - } - - iFrameNumber++; - } -#endif - - else // H.263 - { - error = MP4ComposeWriteVideoFrame(iMP4Handle, (mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/), - frameSize, duration, keyframe); - - } - if ( error != MP4_OK ) - return KLeaveCode; - } - else if (frameType == EFrameTypeAudio) - { - error = MP4ComposeWriteAudioFrames(iMP4Handle,(mp4_u8*)(dataPtr/*aSrcBuffer.Ptr()*/), - frameSize, numberOfFrames, duration); - if ( error != MP4_OK ) - return KLeaveCode; - } - else - User::Panic(_L("CMovieProcessorImpl"), EComposerFailure); - - return KErrNone; -} - - - -// --------------------------------------------------------- -// CMP4Composer::ComposeHeaderL -// Get relevant stream parameters by calling mp4 library functions -// (other items were commented in a header). -// --------------------------------------------------------- -// - - -void CMP4Composer::ComposeHeaderL(CComposer::TStreamParameters& aStreamParameters, TInt aOutputVideoTimeScale, - TInt aOutputAudioTimeScale, TInt aAudioFramesInSample) -{ - MP4Err iError=KErrNone; - - TInt width = aStreamParameters.iVideoWidth; - TInt height = aStreamParameters.iVideoHeight; - TInt avgbitrate = aStreamParameters.iStreamBitrate; - TInt maxbitrate = avgbitrate; - TInt audioFramesPerSample = aAudioFramesInSample;//aStreamParameters.iAudioFramesInSample; - TInt audioTimescale = aOutputAudioTimeScale; - TInt modeSet=0x8180; - - if(iAudioType == MP4_TYPE_MPEG4_AUDIO) // added for AAC support - { - // reset for AAC audio according to the code sent for AAC support. - audioFramesPerSample = 0; - modeSet = 0; - } - - // set this to first clip's time scale - TInt timescale = aOutputVideoTimeScale; - - iError = MP4ComposeAddAudioDescription(iMP4Handle,(mp4_u32)audioTimescale, - (mp4_u8)audioFramesPerSample,(mp4_u16)modeSet); - if (iError != MP4_OK) - User::Leave(KLeaveCode); - - // write video description - iError = MP4ComposeAddVideoDescription(iMP4Handle,(mp4_u32)timescale, - (mp4_u16)width,(mp4_u16)height,(mp4_u32)maxbitrate,(mp4_u32)avgbitrate); - - if (iError != MP4_OK) - User::Leave(KLeaveCode); - - if ( aStreamParameters.iVideoFormat == EVideoFormatH263Profile0Level10 ) - { - TVideoClipProperties prop; - prop.iH263Level = 10; - MP4ComposeSetVideoClipProperties(iMP4Handle, prop); - } - - else if ( aStreamParameters.iVideoFormat == EVideoFormatH263Profile0Level45 ) - { - TVideoClipProperties prop; - prop.iH263Level = 45; - MP4ComposeSetVideoClipProperties(iMP4Handle, prop); - } - - if (!iFsOpened) // Check if file server is open already - { - User::LeaveIfError(iFS.Connect()); - iFsOpened = ETrue; - } - - if (iFileHandle == 0) - { - // get target drive number - TParse fp; - User::LeaveIfError(iFS.Parse(iOutputMovieFileName, fp)); - TPtrC driveletter = fp.Drive(); - TChar drl = driveletter[0]; - User::LeaveIfError(RFs::CharToDrive(drl, iDriveNumber)); - } - else - { - // get target drive number - TDriveInfo info; - TInt error = iFileHandle->Drive(iDriveNumber, info); - } -} - -// ----------------------------------------------------------------------------- -// CMP4Composer::DriveFreeSpaceL -// Calculate free space on a drive in bytes. -// (other items were commented in a header). -// ----------------------------------------------------------------------------- -// -TInt64 CMP4Composer::DriveFreeSpaceL() -{ - TVolumeInfo volumeinfo; - - if (iFreeDiskSpaceCounter % KFreeDiskSpaceCounter == 0) - { - User::LeaveIfError(iFS.Volume(volumeinfo, iDriveNumber)); - iFreeDiskSpace = volumeinfo.iFree; - } - - iFreeDiskSpaceCounter++; - return iFreeDiskSpace; - -} - -// ----------------------------------------------------------------------------- -// CMP4Composer::GetComposedBuffer New Function added for Buffer support -// Gets the Composed buffer from the composer -// (other items were commented in a header). -// ----------------------------------------------------------------------------- -// -TUint8* CMP4Composer::GetComposedBuffer() -{ - return iComposeBuffer; -} - -// ----------------------------------------------------------------------------- -// CMP4Composer::GetComposedBufferSize New Function added for Buffer support -// Gets the Composed buffer size from the composer -// (other items were commented in a header). -// ----------------------------------------------------------------------------- -// -TUint CMP4Composer::GetComposedBufferSize() -{ - return iComposedSize; -} - -// --------------------------------------------------------- -// CMP4Composer::Close -// Closes the composer instance & creates the output 3gp file -// (other items were commented in a header). -// --------------------------------------------------------- -// -TInt CMP4Composer::Close() -{ - -#ifdef VIDEOEDITORENGINE_AVC_EDITING - - if (iVideoType == MP4_TYPE_AVC_PROFILE_BASELINE) - { - HBufC8* AVCDCR = NULL; - TInt error; - - TRAP(error, AVCDCR = (HBufC8*) HBufC8::NewL(16384)); - if (error != KErrNone) - return error; - - TPtr8 ptr = AVCDCR->Des(); - - // Construct AVC Decoder Configuration Record from the SPS / PPS sets - TRAP(error, iAvcEdit->ConstructAVCDecoderConfigurationRecordL(ptr)); - if (error != KErrNone) - { - delete AVCDCR; - return error; - } - - // Pass the AVC Decoder Configuration Record to the 3GPMP4 library - MP4Err mp4Error = MP4ComposeWriteVideoDecoderSpecificInfo( iMP4Handle, - (mp4_u8*)(ptr.Ptr()), ptr.Length()); - - delete AVCDCR; - - if (mp4Error != MP4_OK) - return EComposerFailure; - } - -#endif - - MP4Err error = MP4ComposeClose(iMP4Handle); - - iMP4Handle = 0; - - if (error != MP4_OK) - return EComposerFailure; - - if (iFsOpened) - { - iFS.Close(); - iFsOpened = EFalse; - } - - return KErrNone; -} - - -// ----------------------------------------------------------------------------- -// CMP4Composer::GetMp4SpecificSize -// Gets the length of MPEG-4 decoder specific info in aSrcBuf -// (other items were commented in a header). -// ----------------------------------------------------------------------------- -// -TInt CMP4Composer::GetMp4SpecificSize(TDesC8& aSrcBuf,TBool aModeChange,TInt aStreamMode) -{ - TUint8* dtPtr = (TUint8*)(aSrcBuf.Ptr()); - TInt mp4size =0; - TInt bufSize; - TInt flag; - - if (!aModeChange && (aStreamMode == 2)) //2 indicates short header in VedCommon - { - bufSize = aSrcBuf.Size()-3; - for(TInt i=0;i>2)<<2; - if (dtPtr[i] == 0x00 && dtPtr[i+1] == 0x00 && flag == 0x80) // user data ???????????? - { - mp4size=i; - break; - } - } - } - else - { - bufSize = aSrcBuf.Size()-4; - for(TInt i=0;i(aSrcBuf->Ptr()); - error = MP4ComposeWriteAudioDecoderSpecificInfo(iMP4Handle, aSrcB, aSrcBuf->Size()); - - if (error != MP4_OK) - return KErrGeneral; - - return KErrNone; -} - -// --------------------------------------------------------- -// CMP4Composer::WriteAudioSpecificInfo -// Writes the Audio decoder Specific info required in case of AAC -// Decoder specific info is derived from samplerate and # of channels -// (other items were commented in a header). -// --------------------------------------------------------- -// -// added to Support AAC audio files -TInt CMP4Composer::WriteAudioSpecificInfo(TInt aSampleRate, TInt aNumChannels) -{ - TInt error = KErrNone; - - TUint8 data[2]; - - data[0] = 2<<3; // AAC-LC - TUint8 rate = RateIndex(aSampleRate); - data[0] |= rate>>1; - data[1] = TUint8(rate<<7); - data[1] |= TUint8(aNumChannels<<3); - - error = MP4ComposeWriteAudioDecoderSpecificInfo(iMP4Handle, data, 2); - - if (error != MP4_OK) - return KErrGeneral; - - return KErrNone; -} - - -// ----------------------------------------------------------------------------- -// CMP4Composer::GetAVCDecoderSpecificInfoSize -// Gets the length of AVC decoder specific info in aSrcBuf -// (other items were commented in a header). -// ----------------------------------------------------------------------------- -// -TInt CMP4Composer::GetAVCDecoderSpecificInfoSize(TDesC8& aSrcBuf) -{ - TUint8* srcPtr = (TUint8*)(aSrcBuf.Ptr()); - TInt skip = 0; -// TInt error = KErrNone; - - // skip 4 bytes for - // configVersion, profile, profile compatibility and Level - skip += 4; - - // skip 1 bytes for lengthSizeMinusOne - skip += 1; - - // skip 1 bytes for num of seq Param sets - TInt numOfSSP = 0x1F & srcPtr[skip]; - skip += 1; - - for (TInt i = 0; i < numOfSSP; i++) - { - TInt sspSize = srcPtr[skip]*256 + srcPtr[skip+1]; - skip += 2; - skip += sspSize; - } - - TInt numOfPSP = srcPtr[skip]; - skip += 1; - - for (TInt i = 0; i < numOfPSP; i++) - { - TInt pspSize = srcPtr[skip]*256 + srcPtr[skip+1]; - skip += 2; - skip += pspSize; - } - - return skip; -} - - - -// End of File