videoeditorengine/audioeditorengine/src/ProcInFileHandler.cpp
changeset 0 951a5db380a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/audioeditorengine/src/ProcInFileHandler.cpp	Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,881 @@
+/*
+* 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:  
+*
+*/
+
+
+
+#include <f32file.h>
+#include "AudPanic.h"
+#include "ProcInFileHandler.h"
+#include "AudClipInfo.h"
+#include "ProcTools.h"
+#include "audconstants.h"
+
+// Debug print macro
+#if defined _DEBUG 
+#include <e32svr.h>
+#define PRINT(x) RDebug::Print x;
+#else
+#define PRINT(x)
+#endif
+
+CProcInFileHandler::~CProcInFileHandler() 
+    {
+
+    if (iFileOpen && iOwnsFile)
+        {
+        iFile.Close();
+        iFs.Close();
+        }
+
+
+    if (iProperties != 0)
+        {
+        delete iProperties;
+        iProperties = 0;
+        }
+
+
+    delete iRawSilentFrame;
+    
+    delete iInputBuffer;
+    
+    delete iWavFrameHandler;
+
+    }
+
+
+TBool CProcInFileHandler::DecodingRequired()
+    {
+    return iDecodingRequired;
+    }
+    
+
+TInt CProcInFileHandler::GetDecodedFrameSize()
+    {
+    if (iProperties == 0)
+        {
+        return 0;
+        }
+    else
+        {
+        
+        // divided by 1000000/2 cause time is in 
+        // microseconds and 16 bits are used for one sample
+#ifdef EKA2
+        TInt frameSize = (iProperties->iFrameDuration.Int64())*(iTargetSampleRate)/(1000000/2);
+#else
+        TInt frameSize = (iProperties->iFrameDuration.Int64().GetTInt())*(iTargetSampleRate)/(1000000/2);
+#endif        
+        
+        
+        if (iChannelMode == EAudStereo)
+            {
+            frameSize *= 2;
+            }
+        
+        return frameSize;
+        }
+    
+    
+    }
+
+
+void CProcInFileHandler::SetDecodingRequired(TBool aDecodingRequired)
+    {
+    iDecodingRequired = aDecodingRequired;
+    
+    }
+
+TBool CProcInFileHandler::GetAudioFrameL(HBufC8*& aFrame, TInt& aSize, TInt32& aTime, TBool& aRawFrame) 
+    {
+
+    if (iDecodingRequired)
+        {
+        aRawFrame = ETrue;
+        return GetRawAudioFrameL(aFrame, aSize, aTime);
+        }
+    else
+        {
+        aRawFrame = EFalse;
+        return GetEncAudioFrameL(aFrame, aSize, aTime);
+        
+        }
+    }
+    
+    
+TBool CProcInFileHandler::GetRawAudioFrameL(HBufC8*& aFrame, TInt& aSize, TInt32& aTime)
+    {
+    
+    
+    while (iInputBuffer == 0 || iInputBuffer->Length() < iRawFrameLength)
+        {
+        TBool ret = GetOneRawAudioFrameL(aFrame, aSize, aTime);
+        if (!ret)
+            {
+            return ret;
+            }
+        
+        WriteDataToInputBufferL(*aFrame);
+        delete aFrame;
+        aFrame = 0;
+    
+        }
+        
+    if (iInputBuffer->Length() >= iRawFrameLength)
+        {
+        aFrame = HBufC8::NewL(iRawFrameLength);
+        aFrame->Des().Append(iInputBuffer->Left(iRawFrameLength));
+        
+        
+        TInt bytesInSecond = iTargetSampleRate*2;
+            
+        if (iChannelMode == EAudStereo)
+            {
+            bytesInSecond *= 2;
+            }
+        
+        
+        // Fix for synchronizing problem ---------------------------------->
+        // If the accurate frame length cannot be represented in milliseconds
+        // store the remainder and increase the output frame lenght by one ms 
+        // when needed. Accuracy depends on sampling rate
+        
+        TReal accurateFrameLen = TReal(aFrame->Length()*1000)/bytesInSecond;
+        aTime = TUint((aFrame->Length()*1000)/bytesInSecond);
+        
+        iFrameLenRemainderMilli += accurateFrameLen - aTime;
+        
+        if (iFrameLenRemainderMilli > 1)
+            {
+            aTime += 1;
+            iFrameLenRemainderMilli -= 1;
+            }
+        // <---------------------------------- Fix for synchronizing problem
+            
+        iInputBuffer->Des().Delete(0, iRawFrameLength);
+
+        
+        }
+    
+    return ETrue;
+    
+    
+    }
+
+    
+TBool CProcInFileHandler::GetOneRawAudioFrameL(HBufC8*& aFrame, TInt& aSize, TInt32& aTime)
+    {
+    
+
+    TInt size = 0;
+        
+    TInt32 time = 0;
+        
+    HBufC8* frame = 0;
+        
+    TBool encFrameRead = GetEncAudioFrameL(frame, size, time);    
+    
+    if (encFrameRead) 
+        {
+        CleanupStack::PushL(frame);
+        }
+    
+    aTime = time;
+    
+    if (!encFrameRead)
+        {
+        return EFalse;
+        }
+    
+    TRAPD(err, iDecoder->FillDecBufferL(frame, aFrame));
+    if (err == KErrNotFound)
+        {
+        // S60 audio decoders seem to leave with KErrNotFound if they find problems in input clips. 
+        // However, sometimes the problem is only in one frame, e.g. the 1st frame may contain some metadata that can't be decoded,
+        // but decoding can continue after that. But if there are many errors, the clip is most likely unusable.
+	    PRINT((_L("CProcInFileHandler::GetOneRawAudioFrameL() iDecoder->FillDecBufferL leaved with %d"),err));
+        if ( iDecoderErrors > 0 )
+            {
+            // several errors, leave, but change the error code to more readable
+    	    PRINT((_L("CProcInFileHandler::GetOneRawAudioFrameL() leave with %d"),KErrCorrupt));
+            User::Leave(KErrCorrupt);
+            }
+        iDecoderErrors++;
+        }
+    else if (err == KErrNone)
+        {
+        // keep filling the decoder buffer; the decoder seem to leave with KErrNone if it can't get enough data, ignore the leave
+        }
+    else
+        {
+        // some other error
+	    PRINT((_L("CProcInFileHandler::GetOneRawAudioFrameL() iDecoder->FillDecBufferL leaved with %d, leaving"),err));
+        User::Leave(err);
+        }
+    
+    if (encFrameRead) 
+        {
+        CleanupStack::PopAndDestroy(frame);
+        frame = 0;
+        
+        }
+    
+    while (aFrame == 0 || aFrame->Size() == 0)
+        {
+        
+        encFrameRead = GetEncAudioFrameL(frame, size, time);
+    
+        if (encFrameRead) 
+            {
+            CleanupStack::PushL(frame);
+            }
+        else
+            {
+            return EFalse;
+            }
+    
+        
+        aTime += time;
+        
+        
+        
+        iDecoder->FillDecBufferL(frame, aFrame);
+        if (encFrameRead) 
+            {
+            CleanupStack::PopAndDestroy(frame);
+            frame = 0;
+            }        
+        
+        }
+    
+    
+    aSize = aFrame->Length();
+    
+    if (iProperties->iAudioTypeExtension != EAudExtensionTypeNoExtension) 
+        {
+        
+        // AACPlus is always decoded, therefore the gain manipulation can be done
+        // in time domain
+        
+        ManipulateGainL(aFrame);
+        aSize = aFrame->Length();
+        
+        
+        }
+    
+    
+    return ETrue;
+        
+    }
+
+
+TBool CProcInFileHandler::SetRawAudioFrameSize(TInt aSize)
+    {
+    
+    const TInt KMaxRawFrameSize = 4096;
+    if (aSize > 0 && aSize <= KMaxRawFrameSize)
+        {
+        iRawFrameLength = aSize;
+        return ETrue;
+        }
+        
+    return EFalse;
+    }
+
+TBool CProcInFileHandler::GetSilentAudioFrameL(HBufC8*& aFrame, TInt& aSize, TInt32& aTime, TBool& aRawFrame)
+    {
+    
+    if (iDecodingRequired)
+        {
+        aRawFrame = ETrue;
+        return GetRawSilentAudioFrameL(aFrame, aSize, aTime);
+        
+        }
+        
+    else
+        {
+        aRawFrame = EFalse;
+        return GetEncSilentAudioFrameL(aFrame, aSize, aTime);
+        }
+    }
+    
+    
+
+
+TBool CProcInFileHandler::GetRawSilentAudioFrameL(HBufC8*& aFrame, TInt& aSize, TInt32& aDuration)
+    {
+    
+    
+    aFrame = HBufC8::NewL(iRawFrameLength);    
+    aFrame->Des().Fill(0, aFrame->Des().MaxLength());
+
+    TInt bytesInSecond = iTargetSampleRate*2;
+            
+    if (iChannelMode == EAudStereo)
+        {
+        bytesInSecond *= 2;
+        }
+    
+    aDuration = TUint((aFrame->Length()*1000)/bytesInSecond);
+    aSize = aFrame->Length();
+  
+    
+    // input buffer is created only if needed
+    if (iInputBuffer)
+        {
+        iInputBuffer->Des().Delete(0, iInputBuffer->Size());
+        
+        }
+    return ETrue;
+        
+    }
+
+TBool CProcInFileHandler::GetEncSilentAudioFrameL(HBufC8*& aFrame, TInt& aSize, TInt32& aDuration)
+    {
+    
+    if (iSilentFrame == 0)
+        {
+        return EFalse;
+        }
+    
+    aFrame = HBufC8::NewL(iSilentFrame->Size());    
+    aFrame->Des().Append(iSilentFrame->Des());
+
+    aDuration = iSilentFrameDuration;
+    aSize = iSilentFrame->Size();
+    return ETrue;
+
+    }
+
+
+CProcInFileHandler::CProcInFileHandler() : iFileOpen(EFalse)
+    {
+    
+    
+
+    }
+    
+TInt32 CProcInFileHandler::GetCurrentTimeMilliseconds() 
+    {
+    return iCurrentTimeMilliseconds;
+
+    }
+
+// default implementation for files that do not have buffered bytes
+TBool CProcInFileHandler::ReadAudioDecoderSpecificInfoL(HBufC8*& /*aBytes*/, TInt /*aBufferSize*/)
+    {
+    return EFalse;
+    }
+
+TBool CProcInFileHandler::OpenFileForReadingL() 
+    {   
+
+    if (iFileOpen)
+        {
+        User::Leave(KErrGeneral);
+        }
+ 
+    TInt err = iFs.Connect();
+    if (err != KErrNone) 
+        {
+        iFileOpen = EFalse;
+        User::Leave(err);
+        }
+
+    err=iFile.Open(iFs, iFileName->Des(), EFileShareReadersOnly);
+    if (err != KErrNone) 
+        {
+        err=iFile.Open(iFs, iFileName->Des(), EFileShareAny);
+        }
+    if (err != KErrNone) 
+        {
+        iFileOpen = EFalse;
+        iFs.Close();
+        User::Leave(err);
+        }
+    else 
+        {
+        iFileOpen = ETrue;
+        return ETrue;
+        }
+
+    return EFalse;
+
+    }
+
+TBool CProcInFileHandler::
+SetPropertiesL(TAudFileProperties aProperties) 
+{
+  if(iProperties == 0)
+    iProperties = new (ELeave) TAudFileProperties();
+
+  iProperties->iAudioType = aProperties.iAudioType;
+  iProperties->iBitrate = aProperties.iBitrate;
+  iProperties->iBitrateMode = aProperties.iBitrateMode;
+  iProperties->iChannelMode = aProperties.iChannelMode;
+  iProperties->iDuration = 0;
+  iProperties->iFileFormat = aProperties.iFileFormat;
+  iProperties->iSamplingRate = aProperties.iSamplingRate;
+  iProperties->iFrameLen = aProperties.iFrameLen;
+  iProperties->iFrameDuration = aProperties.iFrameDuration;
+  iProperties->iFrameCount = aProperties.iFrameCount;
+  
+  return (ETrue);
+}
+
+TBool CProcInFileHandler::SetPriority(TInt aPriority)
+    {
+    if (aPriority < 0) return EFalse;
+
+    iPriority = aPriority;
+
+    return ETrue;
+
+    }
+TInt CProcInFileHandler::Priority() const
+    {
+    return iPriority;
+
+    }
+
+TBool CProcInFileHandler::CloseFile() 
+    {
+
+    if (iOwnsFile)
+    {        
+        iFile.Close();
+        iFs.Close();
+        iFileOpen = EFalse;
+    }
+    
+    return ETrue;
+
+    }
+
+
+
+TBool CProcInFileHandler::InitAndOpenFileL(const TDesC& aFileName, 
+                                           RFile* aFileHandle,
+                                           TInt aReadBufferSize) 
+    {
+
+    
+    iBufferStartOffset = 0;
+    iBufferEndOffset = 0;
+    iCutInTime = 0;
+
+    if (!aFileHandle)
+    {        
+        iFileName = HBufC::NewL(aFileName.Length());
+        *iFileName = aFileName;
+    }
+        
+    iReadBufferSize = aReadBufferSize;
+    iReadBuffer = HBufC8::NewL(iReadBufferSize);
+    
+    const TInt KVedACSizeAMRBuffer = 320;
+    
+    // [JK]: Moved from OpenFileForReadingL
+    // AMR buffer is the smallest possible
+    // buffersize fill be increased if needed
+    iRawFrameLength = KVedACSizeAMRBuffer;
+    iInputBuffer = HBufC8::NewL(iRawFrameLength);
+
+    if (aFileHandle)
+    {
+        iFile = *aFileHandle;
+        iOwnsFile = EFalse;
+        iFileOpen = ETrue;
+        return 0;
+    }
+    
+    TBool err = OpenFileForReadingL();
+    if (!err) iFileOpen = ETrue;
+    
+    iOwnsFile = ETrue;
+    
+    return err;
+
+    }
+
+void CProcInFileHandler::ResetAndCloseFile()
+    {
+
+    if (iFileOpen) 
+        {
+        CloseFile();
+        }
+    if (iFileName != 0)
+        delete iFileName;
+    iFileName = 0;
+    if (iReadBuffer != 0)
+        delete iReadBuffer;
+    iReadBuffer = 0;
+    
+    delete iRawSilentFrame;
+    iRawSilentFrame = 0;
+    
+
+
+    }
+
+TInt CProcInFileHandler::BufferedFileRead(TInt aPos,TDes8& aDes) 
+    {
+    TInt bufSize;
+    
+    if (!iFileOpen) 
+        {
+        TAudPanic::Panic(TAudPanic::EInternal);
+        }
+    
+    TBool readingNeeded = EFalse;
+    
+    if (aPos < iBufferStartOffset || aPos + aDes.MaxSize() > iBufferEndOffset) 
+        {
+        readingNeeded = ETrue;
+        }
+    
+    if(readingNeeded) 
+        {
+        TInt fSize;
+
+        iFile.Size(fSize);
+        if(aPos >= fSize) 
+            {
+            aDes.SetLength(0);
+            return 0;
+            }
+
+        TPtr8 tmpDes((TPtr8)iReadBuffer->Des());
+
+        iFile.Read(aPos, (TPtr8&)tmpDes, iReadBufferSize);
+
+        iBufferStartOffset = aPos;
+        iBufferEndOffset = aPos+iReadBuffer->Des().Size()-1;        
+        }
+
+    if (iReadBuffer->Size() == 0) 
+        {
+        return 0;
+        }
+    else 
+        {
+        bufSize = Min(iReadBuffer->Des().Length(), aDes.MaxSize());
+        aDes.Copy(iReadBuffer->Des().Mid(aPos-iBufferStartOffset, bufSize));
+        iFilePos = aPos+aDes.Size();
+
+        return aDes.Size();
+        }
+    }
+
+TInt CProcInFileHandler::BufferedFileRead(TDes8& aDes) 
+    {
+
+    if (!iFileOpen) 
+        {
+        TAudPanic::Panic(TAudPanic::EInternal);
+        }
+
+    return BufferedFileRead(iFilePos, aDes);
+    
+
+    }
+
+TInt CProcInFileHandler::BufferedFileRead(TDes8& aDes,TInt aLength) 
+    {
+    TInt bufSize;
+
+    if (!iFileOpen) 
+        {
+        TAudPanic::Panic(TAudPanic::EInternal);
+        }
+    
+    aDes.Zero();
+
+    TBool readingNeeded = EFalse;
+    
+    if (iFilePos < iBufferStartOffset || iFilePos + aLength-1 > iBufferEndOffset) 
+        {
+        readingNeeded = ETrue;
+        }
+    
+    if(readingNeeded) 
+        {
+        TPtr8 tmpDes((TPtr8)iReadBuffer->Des());
+
+        iFile.Read(iFilePos, (TPtr8&)tmpDes, iReadBufferSize);
+        
+        if (iReadBuffer->Size() == 0) return 0; 
+        iFile.Seek(ESeekStart, iFilePos);
+        iBufferStartOffset = iFilePos;
+        iBufferEndOffset = iFilePos+iReadBuffer->Des().Size()-1;        
+        }
+    bufSize = Min(iReadBuffer->Des().Length(), aLength);
+    aDes.Copy(iReadBuffer->Des().Mid(iFilePos-iBufferStartOffset, bufSize));
+    iFilePos = iFilePos+aDes.Size();
+    return aDes.Size();
+
+    }
+
+TInt CProcInFileHandler::BufferedFileReadChar(TInt aPos, TUint8& aChar)
+    {
+
+    TBuf8<1> cha;
+    BufferedFileRead(aPos, cha);
+
+    if (cha.Size() == 1)
+        {
+        aChar = cha[0];
+        return 1;
+        }
+    else
+        {
+        return 0;
+        }
+
+    }
+
+TBool CProcInFileHandler::BufferedFileSetFilePos(TInt aPos) 
+    {
+
+    
+    TInt fileSize = 0;
+    iFile.Seek(ESeekEnd, fileSize);
+
+    iFile.Seek(ESeekStart, aPos);
+
+    if (aPos == 0)
+        {
+        iBufferStartOffset = 0;
+        iBufferEndOffset = 0;
+
+        }
+    
+    if (aPos < 0) 
+        {
+        return EFalse;
+        }
+    else if (aPos > fileSize) 
+        {
+        return EFalse;
+        }
+    else 
+        {
+        iFilePos = aPos;
+        }
+    return ETrue;
+    }
+
+TInt CProcInFileHandler::BufferedFileGetFilePos() 
+    {
+
+    return iFilePos;
+
+    }
+
+TInt CProcInFileHandler::BufferedFileGetSize()
+    {
+
+    TInt fileSize = 0;
+    iFile.Size(fileSize);
+
+    return fileSize;
+
+
+    }
+
+    
+TInt8 CProcInFileHandler::NormalizingMargin() const 
+    {
+    return iNormalizingMargin;
+    }
+    
+TBool CProcInFileHandler::ManipulateGainL(HBufC8*& aFrameIn) 
+    {
+    
+    if (iClip == 0)
+        {
+        return ETrue;
+        }
+                
+    if (iProperties->iAudioTypeExtension != EAudExtensionTypeNoExtension)
+        {
+        
+        // gain manipulation with AACPlus is done in time domain
+        
+        if (iWavFrameHandler == 0)
+            {
+            
+            const TInt KBitDepth = 16;
+            iWavFrameHandler = CProcWAVFrameHandler::NewL(KBitDepth);
+            }
+            
+        
+        }
+                
+    
+    // check if the clip is normalized
+    TInt8 normalizingGain1 = iNormalizingMargin;
+    
+    // check what is the current gain according to dynamic level marks
+    TInt8 newGain1 = GetGainNow();
+    
+    
+    // the combination of dynamic level marks + normalizing
+    TInt8 normalizedGain1 = 0;
+    if ( ((TInt)newGain1+normalizingGain1) > (TInt)KMaxTInt8)
+        {
+        normalizedGain1 = KMaxTInt8;
+        }
+    else
+        {
+        normalizedGain1 = static_cast<TInt8>(newGain1+normalizingGain1); 
+        }
+        
+    
+    if (normalizedGain1 != 0)
+        {
+        HBufC8* frameOut = 0;    
+        // if we need to adjust gain...
+        TBool manip = ETrue;
+        if (iProperties->iAudioTypeExtension != EAudExtensionTypeNoExtension)
+            {
+            
+            manip = iWavFrameHandler->ManipulateGainL(aFrameIn, frameOut, normalizedGain1);
+            }
+        else
+            {
+            manip = iFrameHandler->ManipulateGainL(aFrameIn, frameOut, normalizedGain1);    
+            }
+        
+        
+        if (manip)
+            {
+        
+            CleanupStack::PushL(aFrameIn);
+            CleanupStack::PushL(frameOut);
+            
+            if (frameOut->Size() > aFrameIn->Size())
+                {
+                // if manipulated frame was longer than the original
+                aFrameIn = aFrameIn->ReAllocL(frameOut->Size());
+                
+                }
+            aFrameIn->Des().Delete(0, aFrameIn->Size());
+            aFrameIn->Des().Copy(frameOut->Des());
+            
+            CleanupStack::PopAndDestroy(frameOut);
+            CleanupStack::Pop(); // aFrameIn
+            }
+        
+    
+        }
+    else
+        {
+        return EFalse;
+        }
+        
+    return ETrue;
+    }
+
+TInt8 CProcInFileHandler::GetGainNow() 
+    {
+    TInt markAmount = iClip->DynamicLevelMarkCount();
+    TTimeIntervalMicroSeconds ti(0);
+    TAudDynamicLevelMark previous(ti,0);
+    //TInt32 durationMilliseconds =     (aClip->Info()->Properties().iDuration.Int64()/1000).GetTInt();
+    TAudDynamicLevelMark next(iClip->Info()->Properties().iDuration,0);
+
+    for (TInt a = 0 ; a < markAmount ; a++) 
+        {
+        TAudDynamicLevelMark markNow = iClip->DynamicLevelMark(a);
+        
+        if (ProcTools::MilliSeconds(markNow.iTime) > iCurrentTimeMilliseconds) 
+            {
+            next = markNow;
+            break;
+            }
+
+        previous = markNow;
+
+        }
+
+    TInt32 previousMilli = ProcTools::MilliSeconds(previous.iTime);
+    
+    TInt32 nextMilli = ProcTools::MilliSeconds(next.iTime);
+    
+    TInt32 timeDifference = nextMilli - previousMilli;
+    
+    TInt8 previousLevel = previous.iLevel;
+    TInt8 nextLevel = next.iLevel;
+    
+    // If the levels are positive then the amount of gain needs to be reduced
+    if (previousLevel > 0)
+        {
+        previousLevel /= KAedPositiveGainDivider;
+        }
+    if (nextLevel > 0)
+        {
+        nextLevel /= KAedPositiveGainDivider;
+        }
+
+    if (timeDifference == 0) 
+        {
+        return previousLevel;
+        }
+        
+    TInt32 fraction = ((iCurrentTimeMilliseconds-previousMilli)*100)/timeDifference;
+    TInt8 newGain = 0;
+    
+    TInt8 levelDifference = static_cast<TInt8>(Abs(nextLevel - previousLevel));
+    TInt8 inc = 0;
+    if (fraction > 0) 
+        {
+        inc = static_cast<TInt8>((levelDifference*fraction)/100);
+        }
+
+    if (nextLevel - previousLevel >= 0) 
+        {
+        newGain = static_cast<TInt8>(previousLevel + inc);
+        }
+    else 
+        {
+        newGain = static_cast<TInt8>(previousLevel - inc);
+        }
+    
+    return newGain;
+
+    }
+    
+TBool CProcInFileHandler::WriteDataToInputBufferL(const TDesC8& aData)
+    {
+    
+    if (iInputBuffer == 0)
+        {
+        iInputBuffer = HBufC8::NewL(aData.Size());
+        }
+    else if (iInputBuffer->Des().MaxSize() < iInputBuffer->Length() + aData.Length())
+        {
+        iInputBuffer = iInputBuffer->ReAllocL(iInputBuffer->Length() + aData.Length());
+        }
+     
+    iInputBuffer->Des().Append(aData);
+    
+    return ETrue;
+    
+    }