--- /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