mmplugins/lib3gp/impl/src/metadatafilewriter.cpp
changeset 0 40261b775718
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmplugins/lib3gp/impl/src/metadatafilewriter.cpp	Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,555 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "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:
+//
+// Description:
+//
+
+
+// INCLUDE FILES
+#include <e32base.h>
+#include <f32file.h>
+#include "mp4atom.h"
+#include "metadatafilewriter.h"
+
+// MACROS
+// Debug print macro
+#ifdef _DEBUG
+#include <e32svr.h>
+#define PRINT(x)
+#else
+#define PRINT(x)
+#endif
+
+const TInt KMetaDataWriterBufferSize        = (4*4096);
+const TInt KMetaDataWriterInputBufCount     = 10;
+const TInt KMetaDataWriterOutputBufCount    = 4;
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+CMetaDataWriterBuffer::~CMetaDataWriterBuffer()
+    {
+    delete iData;
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataFileWriter::CMetaDataFileWriter
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CMetaDataFileWriter::CMetaDataFileWriter() : CActive( EPriorityHigh ) 
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataFileWriter::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CMetaDataFileWriter::ConstructL( )
+    {
+    PRINT(_L("CMetaDataFileWriter::ConstructL() in"));
+
+    iError = KErrNone;
+    iAsyncWritingOngoing = EFalse;
+    iFlush = EFalse;
+    iFlushDone = EFalse;
+
+    for (TInt i=0; i<KMetaDataWriterInputBufCount; i++)
+        {
+        iOutputFile.AppendL(NULL);
+
+        CMetaDataWriterBuffer* emptyInputBuffer = new (ELeave) CMetaDataWriterBuffer;
+        CleanupStack::PushL(emptyInputBuffer);
+        
+        emptyInputBuffer->iData = HBufC8::NewL(KMetaDataWriterBufferSize);
+        emptyInputBuffer->iOutputFileNum = i;
+        iInputBufferArray.AppendL(emptyInputBuffer);
+        
+        CleanupStack::Pop(emptyInputBuffer);
+        
+        iInputBufferArrayDelivered[i] = 0;
+        }
+
+    for (TInt j=0; j<KMetaDataWriterOutputBufCount; j++)
+        {
+        CMetaDataWriterBuffer* emptyOutputBuffer = new (ELeave) CMetaDataWriterBuffer;
+        CleanupStack::PushL(emptyOutputBuffer);
+        
+        emptyOutputBuffer->iData = HBufC8::NewL(KMetaDataWriterBufferSize);
+        emptyOutputBuffer->iOutputFileNum = -1;
+        iEmptyBufferQueue.AppendL(emptyOutputBuffer);
+        
+        CleanupStack::Pop(emptyOutputBuffer);
+        }
+
+    CActiveScheduler::Add(this);
+
+    PRINT(_L("CMetaDataFileWriter::ConstructL() out"));
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataFileWriter::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CMetaDataFileWriter* CMetaDataFileWriter::NewL()
+    {
+    PRINT(_L("CMetaDataFileWriter::NewL() in"));
+    
+    CMetaDataFileWriter* self = new(ELeave) CMetaDataFileWriter;
+    CleanupStack::PushL(self);
+    self->ConstructL( );
+    CleanupStack::Pop(self);
+
+    PRINT(_L("CMetaDataFileWriter::NewL() out"));
+    return self;
+    }
+
+
+// Destructor
+CMetaDataFileWriter::~CMetaDataFileWriter()
+    {
+    PRINT(_L("CMetaDataFileWriter::~CMetaDataFileWriter() in"));
+
+
+    if ( IsActive() )
+        {
+        if ( iAsyncWritingOngoing )
+            {
+            Cancel();    
+            }
+        else
+            {
+            TRequestStatus* status = &iStatus;
+            User::RequestComplete( status, KErrNone );
+            Cancel();
+            }
+        }
+
+    iOutputFile.Reset();
+    iInputBufferArray.ResetAndDestroy();
+    iOutputBufferQueue.ResetAndDestroy();
+    iEmptyBufferQueue.ResetAndDestroy();
+    PRINT(_L("CMetaDataFileWriter::~CMetaDataFileWriter() out"));
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataFileWriter::Write( const TDesC8& aBuf )
+// Writes incoming buffer data to internal buffers for writing to disk.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMetaDataFileWriter:: Write( RFile64& aFile, const TInt aFileNumber, const TDesC8& aBuf )
+    {
+    PRINT(_L("CMetaDataFileWriter::Write() in"));
+    PRINT((_L("e_cmetadatawriter_write 1")));
+
+    iOutputFile[aFileNumber] = &aFile;
+
+	PRINT((_L("e_cmetadatawriter_write_adddatatobuffer 1")));
+    TInt error = AddDataToBuffer( aFileNumber, aBuf );
+    if ( error != KErrNone )
+        {
+        PRINT((_L("CMetaDataFileWriter::Write() buffer write error: %d"), error));         
+        return error;
+        }
+	PRINT((_L("e_cmetadatawriter_write_adddatatobuffer 0")));
+
+    PRINT((_L("CMetaDataFileWriter::Write() Write Buffer, Status: Full:%d Empty:%d "), 
+                    iOutputBufferQueue.Count(), iEmptyBufferQueue.Count() ));
+
+    if ( iAsyncWritingOngoing )
+        {
+        if ( iOutputBufferQueue.Count() >= KFileWriterHardBufLimit )
+            {
+            PRINT((_L("CMetaDataFileWriter::Write() Waiting async write to complete")));
+			PRINT((_L("e_cmetadatawriter_write_waitasync 1")));            
+            User::WaitForRequest( iStatus );
+			PRINT((_L("e_cmetadatawriter_write_waitasync 0")));            
+            PRINT((_L("CMetaDataFileWriter::Write() Async write done")));
+            TRAP(error, RunL());
+            if (error != KErrNone)
+            	{
+            	PRINT((_L("CMetaDataFileWriter::Write() runL leave, error: %d"), error));         
+                return error;
+            	}
+            }
+        }
+    else
+        {
+        if ( iOutputBufferQueue.Count() )
+            {
+            PRINT(_L("CMetaDataFileWriter::Write() writing async"));       
+
+			PRINT((_L("e_cmetadatawriter_write_startwrite 1")));
+			
+            iOutputFile[iOutputBufferQueue[0]->iOutputFileNum]->Write( *(iOutputBufferQueue[0]->iData), iStatus );
+			PRINT((_L("e_cmetadatawriter_write_startwrite 0")));            
+            iAsyncWritingOngoing = ETrue;
+            if ( !IsActive() )
+                {
+                SetActive();
+                }
+            }
+        }
+
+    PRINT(_L("CMetaDataFileWriter::Write() out"));
+    PRINT((_L("e_cmetadatawriter_write 0")));    
+    return error;
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataFileWriter::Flush( )
+// Flush internal buffers to disk.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMetaDataFileWriter::Flush( )
+    {
+    PRINT(_L("CMetaDataFileWriter::Flush() in"));
+    PRINT((_L("e_cmetadatawriter_flush 1")));
+    PRINT((_L("CMetaDataFileWriter::Flush() FullCount: %d "), iOutputBufferQueue.Count()));
+
+    TInt error = KErrNone;
+    iFlush = ETrue;
+
+    if ( iAsyncWritingOngoing )
+        {
+        PRINT((_L("CMetaDataFileWriter::Flush() Waiting async write to complete")));
+        PRINT((_L("e_cmetadatawriter_flush_waitasyncstop 1")));
+        User::WaitForRequest( iStatus );
+		PRINT((_L("e_cmetadatawriter_flush_waitasyncstop 0")));        
+        PRINT((_L("CMetaDataFileWriter::Flush() Async write done, flushing")));
+        TRAP(error, RunL());
+        if (error != KErrNone)
+        	{
+        	PRINT((_L("CMetaDataFileWriter::Flush() call runL leave, error: %d"), error));         
+            return error;
+        	}
+        }
+
+    while ( iOutputBufferQueue.Count() )
+        {
+        PRINT((_L("e_cmetadatawriter_flush_writesync 1")));
+        
+        error = iOutputFile[iOutputBufferQueue[0]->iOutputFileNum]->Write( *(iOutputBufferQueue[0]->iData) );
+        if ( error == KErrNone )
+            {
+            error = iEmptyBufferQueue.Append(iOutputBufferQueue[0]);
+            if (error == KErrNone)
+            	{                   
+            	iOutputBufferQueue[0]->iData->Des().Zero();
+            	iOutputBufferQueue[0]->iOutputFileNum = -1;
+            	iOutputBufferQueue.Remove(0);
+            	}
+            else
+            	{
+            	PRINT((_L("CMetaDataFileWriter::Flush() iEmptyBufferQueue.Append failed, error: %d"), error));
+            	return error;
+            	}
+            }
+        else
+            {
+            PRINT((_L("CMetaDataFileWriter::Flush() fullBufQueue write failed, error: %d"), error));
+            iFlush = EFalse;
+            return error;
+            }
+		PRINT((_L("e_cmetadatawriter_flush_writesync 0")));            
+        }
+
+    if ( !iFlushDone ) // Flush only once
+        {
+        iFlushDone = ETrue;
+        for ( TInt i=0; i < KMetaDataWriterInputBufCount; i++ )
+            {
+            if ( iOutputFile[i] )
+                {
+		    	PRINT((_L("e_cmetadatawriter_flush_write_tempfiles 1")));
+                error = iOutputFile[i]->Flush();
+    			PRINT((_L("e_cmetadatawriter_flush_write_tempfiles 0")));
+                PRINT((_L("CMetaDataFileWriter::Flush() inputbuf[%d] flush return code: %d"), i, error));
+                }
+	        }
+        }
+
+    iFlush = EFalse;
+    PRINT((_L("CMetaDataFileWriter::Flush() FullCount: %d <= Should be 0"), iOutputBufferQueue.Count()));
+    PRINT(_L("CMetaDataFileWriter::Flush() out"));
+    PRINT((_L("e_cmetadatawriter_flush 0")));
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataFileWriter::AddDataToBuffer( const TDesC8& aBuf )
+// Writes incoming data to internal buffers and buffer queues..
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CMetaDataFileWriter::AddDataToBuffer(const TInt aFileNumber, const TDesC8& aBuf )
+    {
+    PRINT(_L("CMetaDataFileWriter::AddDataToBuffer() in"));
+
+    TInt byteswritten = 0;
+    TInt numbytes = 0;
+    TInt available = 0; // Available bytes in write buffer
+    TInt error = KErrNone;
+    
+    HBufC8* inputBuf = iInputBufferArray[aFileNumber]->iData;
+
+    if ( iError != KErrNone )
+        {
+        PRINT((_L("CMetaDataFileWriter::AddDataToBuffer() out, RunL iError: %d"), iError));
+        return iError;
+        }
+
+    PRINT((_L("CMetaDataFileWriter::AddDataToBuffer() Save Buffer, Size: %d "),  aBuf.Length() ));
+
+    while (byteswritten < aBuf.Length() )
+        {
+        available = (inputBuf->Des()).MaxLength() - inputBuf->Length();
+
+        if (available > 0)
+            {
+            numbytes = aBuf.Length() - byteswritten;
+            if (numbytes > available)
+                {
+                numbytes = available;
+                }
+            inputBuf->Des().Append( aBuf.Mid( byteswritten, numbytes ) );
+            byteswritten += numbytes;
+            }
+        else // Buffer is full, move it to outputqueue and use empty/new buf as input.
+            {
+            if ( iEmptyBufferQueue.Count() == 0 )
+                {
+                CMetaDataWriterBuffer* emptyInputBuffer = 0;
+
+                emptyInputBuffer = new CMetaDataWriterBuffer;
+                if ( !emptyInputBuffer )
+                    {
+                    PRINT((_L("CMetaDataFileWriter::AddDataToBuffer(), memory alloc failed")));
+                    iError = KErrNoMemory;
+                    break;
+                    }
+
+                TRAP(error, emptyInputBuffer->iData = HBufC8::NewL( KMetaDataWriterBufferSize ));
+                if ( error != KErrNone )
+                    {
+                    PRINT((_L("CMetaDataFileWriter::AddDataToBuffer(), memory alloc failed: %d"), error));
+                    delete emptyInputBuffer;
+                    emptyInputBuffer = NULL;
+                    iError = error;
+                    break;
+                    }
+                else
+                    {                    
+                    error = iOutputBufferQueue.Append(iInputBufferArray[aFileNumber]);
+                    if (error != KErrNone)
+                    	{
+                        PRINT((_L("CMetaDataFileWriter::AddDataToBuffer(), memory alloc failed: %d"), error));
+                        delete emptyInputBuffer;
+                        emptyInputBuffer = NULL;
+                        iError = error;
+                        break;
+                    	}
+                    
+                	// old full buffer to output queue.
+                    emptyInputBuffer->iOutputFileNum = aFileNumber;
+                    
+                    // new buffer to input.
+                    iInputBufferArray[aFileNumber] = emptyInputBuffer;
+                    }
+                }
+            else
+                {
+                // old full buffer to output queue.
+                TInt err = iOutputBufferQueue.Append( iInputBufferArray[aFileNumber] );
+                if (err != KErrNone)
+                	{
+                	PRINT((_L("CMetaDataFileWriter::AddDataToBuffer(), iOutputBufferQueue.Append failed: %d"), err));
+                	iError = err;
+                	break;
+                	}
+                
+                // empty buffer from empty queue to input.
+                iInputBufferArray[aFileNumber] = iEmptyBufferQueue[0];
+                iInputBufferArray[aFileNumber]->iData->Des().Zero();
+                iInputBufferArray[aFileNumber]->iOutputFileNum = aFileNumber;
+                iEmptyBufferQueue.Remove(0);                
+                }
+
+            inputBuf = iInputBufferArray[aFileNumber]->iData;
+            }
+        }
+
+    PRINT((_L("CMetaDataFileWriter::AddDataToBuffer() out, error: %d"), error));
+    return error;
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataFileWriter::DoCancel()
+// From CActive Cancels async request.
+// -----------------------------------------------------------------------------
+//
+void CMetaDataFileWriter::DoCancel()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataFileWriter::RunL()
+// From CActive Called when async request completes.
+// -----------------------------------------------------------------------------
+//
+void CMetaDataFileWriter::RunL()
+    {
+    PRINT(_L("CMetaDataFileWriter::RunL() in"));
+	PRINT((_L("e_cmetadatawriter_runl 1")));
+    iAsyncWritingOngoing = EFalse;
+
+    if ( iStatus == KErrNone )
+        {
+        iEmptyBufferQueue.AppendL( iOutputBufferQueue[0] );        
+        iOutputBufferQueue[0]->iData->Des().Zero();
+        iOutputBufferQueue[0]->iOutputFileNum = -1;
+        iOutputBufferQueue.Remove( 0 );
+        }
+    else
+        {
+        PRINT((_L("CMetaDataFileWriter::RunL() Write error in previous async: %d "), iStatus.Int() ));
+        iError = iStatus.Int();
+        return;
+        }
+
+    PRINT((_L("CMetaDataFileWriter::RunL() Buffer written, Status: Full:%d Empty:%d "), iOutputBufferQueue.Count(), iEmptyBufferQueue.Count() ));
+    
+    if ( iFlush )
+        {
+        PRINT(_L("CMetaDataFileWriter::RunL() out, flushing"));
+        PRINT((_L("e_cmetadatawriter_runl 0")));
+        return;
+        }
+
+    if ( iOutputBufferQueue.Count() >= KFileWriterHardBufLimit )
+        {
+        while ( iOutputBufferQueue.Count() > KFileWriterSoftBufLimit )
+            {
+        	PRINT((_L("e_cmetadatawriter_runl1_write 1")));
+            iError = iOutputFile[iOutputBufferQueue[0]->iOutputFileNum]->Write( *(iOutputBufferQueue[0]->iData));
+        	PRINT((_L("e_cmetadatawriter_runl1_write 0")));
+            if ( iError == KErrNone )
+                {
+                iEmptyBufferQueue.AppendL( iOutputBufferQueue[0] );
+                iOutputBufferQueue[0]->iData->Des().Zero();
+                iOutputBufferQueue[0]->iOutputFileNum = -1;                
+                iOutputBufferQueue.Remove( 0 );
+                }   
+            else
+                {
+                PRINT((_L("CMetaDataFileWriter::RunL() Write error: %d "), iError));
+                return;
+                }   
+            }
+        }
+
+    if ( iOutputBufferQueue.Count() >= KFileWriterSoftBufLimit )
+        {
+      	PRINT((_L("e_cmetadatawriter_runl2_write 1")));
+        iError = iOutputFile[iOutputBufferQueue[0]->iOutputFileNum]->Write(  *(iOutputBufferQueue[0]->iData));
+      	PRINT((_L("e_cmetadatawriter_runl2_write 0")));
+        if ( iError == KErrNone )
+            {
+            iEmptyBufferQueue.AppendL( iOutputBufferQueue[0] );            
+            iOutputBufferQueue[0]->iData->Des().Zero();
+            iOutputBufferQueue[0]->iOutputFileNum = -1;
+            iOutputBufferQueue.Remove( 0 );
+            }   
+        else
+            {
+            PRINT((_L("CMetaDataFileWriter::RunL() Write error: %d "), iError));
+            return;
+            }
+        }
+
+    if ( iOutputBufferQueue.Count() )
+        {
+      	PRINT((_L("e_cmetadatawriter_runl3_write 1")));
+        iOutputFile[iOutputBufferQueue[0]->iOutputFileNum]->Write( *(iOutputBufferQueue[0]->iData), iStatus );
+      	PRINT((_L("e_cmetadatawriter_runl3_write 0")));
+        iAsyncWritingOngoing = ETrue;
+        if ( !IsActive() )
+            {
+            SetActive();
+            }
+        }
+
+	PRINT((_L("e_cmetadatawriter_runl 0")));
+    PRINT(_L("CMetaDataFileWriter::RunL() out"));
+    }
+
+// -----------------------------------------------------------------------------
+// CMetaDataFileWriter::RunError
+// -----------------------------------------------------------------------------
+//
+ TInt CMetaDataFileWriter::RunError(TInt aError)
+	 {
+	 //RunL can leave.
+	 iError = aError;
+	 return KErrNone ;
+	 }
+ 
+// -----------------------------------------------------------------------------
+// CMetaDataFileWriter::ReadBuffer
+// -----------------------------------------------------------------------------
+//
+TInt CMetaDataFileWriter::ReadBuffer( const TInt aFileNumber, TDes8& aBuf, TInt bytestoread )
+    {
+    PRINT(_L("CMetaDataFileWriter::ReadBuffer() in"));
+	PRINT((_L("e_cmetadatawriter_readbuffer 1")));
+    TInt bytesread;
+    
+    PRINT((_L("CMetaDataFileWriter::ReadBuffer() iInputBufferArray[%d]->iData->Length(): %d, requested %d"), aFileNumber, iInputBufferArray[aFileNumber]->iData->Length(), bytestoread));
+    if ( !iInputBufferArray[aFileNumber]->iData->Length() )
+        {
+        bytesread = 0;
+        }
+    else if ( (iInputBufferArray[aFileNumber]->iData->Length() -
+        iInputBufferArrayDelivered[aFileNumber]) >= bytestoread )
+        {
+        bytesread = bytestoread;
+        aBuf.Append( iInputBufferArray[aFileNumber]->iData->Mid( iInputBufferArrayDelivered[aFileNumber], bytesread ) );
+        iInputBufferArrayDelivered[aFileNumber] += bytesread;
+        
+        // If the buffer is read empty, release it
+        if ( iInputBufferArray[aFileNumber]->iData->Length() == iInputBufferArrayDelivered[aFileNumber] )
+            {
+            PRINT((_L("CMetaDataFileWriter::ReadBuffer() iInputBufferArray[%d] %d delivered"), aFileNumber, iInputBufferArray[aFileNumber]->iData->Length()));
+            iInputBufferArray[aFileNumber]->iData->Des().Zero();
+            }
+        }
+    else
+        {
+        bytesread = iInputBufferArray[aFileNumber]->iData->Length() - iInputBufferArrayDelivered[aFileNumber];
+        aBuf.Append( iInputBufferArray[aFileNumber]->iData->Mid( iInputBufferArrayDelivered[aFileNumber], bytesread ) );
+        iInputBufferArrayDelivered[aFileNumber] += bytesread;
+
+        PRINT((_L("CMetaDataFileWriter::ReadBuffer() iInputBufferArray[%d] %d bytes delivered"), aFileNumber, iInputBufferArray[aFileNumber]->iData->Length()));
+        iInputBufferArray[aFileNumber]->iData->Des().Zero();
+        }
+        
+	PRINT((_L("e_cmetadatawriter_readbuffer 0")));
+    PRINT(_L("CMetaDataFileWriter::ReadBuffer() out"));
+
+    return ( bytesread );
+    }
+
+//  End of File