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