os/mm/mmplugins/lib3gp/impl/src/metadatafilewriter.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 
    17 // INCLUDE FILES
    18 #include <e32base.h>
    19 #include <f32file.h>
    20 #include "mp4atom.h"
    21 #include "metadatafilewriter.h"
    22 
    23 // MACROS
    24 // Debug print macro
    25 #ifdef _DEBUG
    26 #include <e32svr.h>
    27 #define PRINT(x)
    28 #else
    29 #define PRINT(x)
    30 #endif
    31 
    32 const TInt KMetaDataWriterBufferSize        = (4*4096);
    33 const TInt KMetaDataWriterInputBufCount     = 10;
    34 const TInt KMetaDataWriterOutputBufCount    = 4;
    35 
    36 // ============================ MEMBER FUNCTIONS ===============================
    37 
    38 CMetaDataWriterBuffer::~CMetaDataWriterBuffer()
    39     {
    40     delete iData;
    41     }
    42 
    43 // -----------------------------------------------------------------------------
    44 // CMetaDataFileWriter::CMetaDataFileWriter
    45 // C++ default constructor can NOT contain any code, that
    46 // might leave.
    47 // -----------------------------------------------------------------------------
    48 //
    49 CMetaDataFileWriter::CMetaDataFileWriter() : CActive( EPriorityHigh ) 
    50     {
    51     }
    52 
    53 // -----------------------------------------------------------------------------
    54 // CMetaDataFileWriter::ConstructL
    55 // Symbian 2nd phase constructor can leave.
    56 // -----------------------------------------------------------------------------
    57 //
    58 void CMetaDataFileWriter::ConstructL( )
    59     {
    60     PRINT(_L("CMetaDataFileWriter::ConstructL() in"));
    61 
    62     iError = KErrNone;
    63     iAsyncWritingOngoing = EFalse;
    64     iFlush = EFalse;
    65     iFlushDone = EFalse;
    66 
    67     for (TInt i=0; i<KMetaDataWriterInputBufCount; i++)
    68         {
    69         iOutputFile.AppendL(NULL);
    70 
    71         CMetaDataWriterBuffer* emptyInputBuffer = new (ELeave) CMetaDataWriterBuffer;
    72         CleanupStack::PushL(emptyInputBuffer);
    73         
    74         emptyInputBuffer->iData = HBufC8::NewL(KMetaDataWriterBufferSize);
    75         emptyInputBuffer->iOutputFileNum = i;
    76         iInputBufferArray.AppendL(emptyInputBuffer);
    77         
    78         CleanupStack::Pop(emptyInputBuffer);
    79         
    80         iInputBufferArrayDelivered[i] = 0;
    81         }
    82 
    83     for (TInt j=0; j<KMetaDataWriterOutputBufCount; j++)
    84         {
    85         CMetaDataWriterBuffer* emptyOutputBuffer = new (ELeave) CMetaDataWriterBuffer;
    86         CleanupStack::PushL(emptyOutputBuffer);
    87         
    88         emptyOutputBuffer->iData = HBufC8::NewL(KMetaDataWriterBufferSize);
    89         emptyOutputBuffer->iOutputFileNum = -1;
    90         iEmptyBufferQueue.AppendL(emptyOutputBuffer);
    91         
    92         CleanupStack::Pop(emptyOutputBuffer);
    93         }
    94 
    95     CActiveScheduler::Add(this);
    96 
    97     PRINT(_L("CMetaDataFileWriter::ConstructL() out"));
    98     }
    99 
   100 // -----------------------------------------------------------------------------
   101 // CMetaDataFileWriter::NewL
   102 // Two-phased constructor.
   103 // -----------------------------------------------------------------------------
   104 //
   105 CMetaDataFileWriter* CMetaDataFileWriter::NewL()
   106     {
   107     PRINT(_L("CMetaDataFileWriter::NewL() in"));
   108     
   109     CMetaDataFileWriter* self = new(ELeave) CMetaDataFileWriter;
   110     CleanupStack::PushL(self);
   111     self->ConstructL( );
   112     CleanupStack::Pop(self);
   113 
   114     PRINT(_L("CMetaDataFileWriter::NewL() out"));
   115     return self;
   116     }
   117 
   118 
   119 // Destructor
   120 CMetaDataFileWriter::~CMetaDataFileWriter()
   121     {
   122     PRINT(_L("CMetaDataFileWriter::~CMetaDataFileWriter() in"));
   123 
   124 
   125     if ( IsActive() )
   126         {
   127         if ( iAsyncWritingOngoing )
   128             {
   129             Cancel();    
   130             }
   131         else
   132             {
   133             TRequestStatus* status = &iStatus;
   134             User::RequestComplete( status, KErrNone );
   135             Cancel();
   136             }
   137         }
   138 
   139     iOutputFile.Reset();
   140     iInputBufferArray.ResetAndDestroy();
   141     iOutputBufferQueue.ResetAndDestroy();
   142     iEmptyBufferQueue.ResetAndDestroy();
   143     PRINT(_L("CMetaDataFileWriter::~CMetaDataFileWriter() out"));
   144     }
   145 
   146 // -----------------------------------------------------------------------------
   147 // CMetaDataFileWriter::Write( const TDesC8& aBuf )
   148 // Writes incoming buffer data to internal buffers for writing to disk.
   149 // (other items were commented in a header).
   150 // -----------------------------------------------------------------------------
   151 //
   152 TInt CMetaDataFileWriter:: Write( RFile64& aFile, const TInt aFileNumber, const TDesC8& aBuf )
   153     {
   154     PRINT(_L("CMetaDataFileWriter::Write() in"));
   155     PRINT((_L("e_cmetadatawriter_write 1")));
   156 
   157     iOutputFile[aFileNumber] = &aFile;
   158 
   159 	PRINT((_L("e_cmetadatawriter_write_adddatatobuffer 1")));
   160     TInt error = AddDataToBuffer( aFileNumber, aBuf );
   161     if ( error != KErrNone )
   162         {
   163         PRINT((_L("CMetaDataFileWriter::Write() buffer write error: %d"), error));         
   164         return error;
   165         }
   166 	PRINT((_L("e_cmetadatawriter_write_adddatatobuffer 0")));
   167 
   168     PRINT((_L("CMetaDataFileWriter::Write() Write Buffer, Status: Full:%d Empty:%d "), 
   169                     iOutputBufferQueue.Count(), iEmptyBufferQueue.Count() ));
   170 
   171     if ( iAsyncWritingOngoing )
   172         {
   173         if ( iOutputBufferQueue.Count() >= KFileWriterHardBufLimit )
   174             {
   175             PRINT((_L("CMetaDataFileWriter::Write() Waiting async write to complete")));
   176 			PRINT((_L("e_cmetadatawriter_write_waitasync 1")));            
   177             User::WaitForRequest( iStatus );
   178 			PRINT((_L("e_cmetadatawriter_write_waitasync 0")));            
   179             PRINT((_L("CMetaDataFileWriter::Write() Async write done")));
   180             TRAP(error, RunL());
   181             if (error != KErrNone)
   182             	{
   183             	PRINT((_L("CMetaDataFileWriter::Write() runL leave, error: %d"), error));         
   184                 return error;
   185             	}
   186             }
   187         }
   188     else
   189         {
   190         if ( iOutputBufferQueue.Count() )
   191             {
   192             PRINT(_L("CMetaDataFileWriter::Write() writing async"));       
   193 
   194 			PRINT((_L("e_cmetadatawriter_write_startwrite 1")));
   195 			
   196             iOutputFile[iOutputBufferQueue[0]->iOutputFileNum]->Write( *(iOutputBufferQueue[0]->iData), iStatus );
   197 			PRINT((_L("e_cmetadatawriter_write_startwrite 0")));            
   198             iAsyncWritingOngoing = ETrue;
   199             if ( !IsActive() )
   200                 {
   201                 SetActive();
   202                 }
   203             }
   204         }
   205 
   206     PRINT(_L("CMetaDataFileWriter::Write() out"));
   207     PRINT((_L("e_cmetadatawriter_write 0")));    
   208     return error;
   209     }
   210 
   211 // -----------------------------------------------------------------------------
   212 // CMetaDataFileWriter::Flush( )
   213 // Flush internal buffers to disk.
   214 // (other items were commented in a header).
   215 // -----------------------------------------------------------------------------
   216 //
   217 TInt CMetaDataFileWriter::Flush( )
   218     {
   219     PRINT(_L("CMetaDataFileWriter::Flush() in"));
   220     PRINT((_L("e_cmetadatawriter_flush 1")));
   221     PRINT((_L("CMetaDataFileWriter::Flush() FullCount: %d "), iOutputBufferQueue.Count()));
   222 
   223     TInt error = KErrNone;
   224     iFlush = ETrue;
   225 
   226     if ( iAsyncWritingOngoing )
   227         {
   228         PRINT((_L("CMetaDataFileWriter::Flush() Waiting async write to complete")));
   229         PRINT((_L("e_cmetadatawriter_flush_waitasyncstop 1")));
   230         User::WaitForRequest( iStatus );
   231 		PRINT((_L("e_cmetadatawriter_flush_waitasyncstop 0")));        
   232         PRINT((_L("CMetaDataFileWriter::Flush() Async write done, flushing")));
   233         TRAP(error, RunL());
   234         if (error != KErrNone)
   235         	{
   236         	PRINT((_L("CMetaDataFileWriter::Flush() call runL leave, error: %d"), error));         
   237             return error;
   238         	}
   239         }
   240 
   241     while ( iOutputBufferQueue.Count() )
   242         {
   243         PRINT((_L("e_cmetadatawriter_flush_writesync 1")));
   244         
   245         error = iOutputFile[iOutputBufferQueue[0]->iOutputFileNum]->Write( *(iOutputBufferQueue[0]->iData) );
   246         if ( error == KErrNone )
   247             {
   248             error = iEmptyBufferQueue.Append(iOutputBufferQueue[0]);
   249             if (error == KErrNone)
   250             	{                   
   251             	iOutputBufferQueue[0]->iData->Des().Zero();
   252             	iOutputBufferQueue[0]->iOutputFileNum = -1;
   253             	iOutputBufferQueue.Remove(0);
   254             	}
   255             else
   256             	{
   257             	PRINT((_L("CMetaDataFileWriter::Flush() iEmptyBufferQueue.Append failed, error: %d"), error));
   258             	return error;
   259             	}
   260             }
   261         else
   262             {
   263             PRINT((_L("CMetaDataFileWriter::Flush() fullBufQueue write failed, error: %d"), error));
   264             iFlush = EFalse;
   265             return error;
   266             }
   267 		PRINT((_L("e_cmetadatawriter_flush_writesync 0")));            
   268         }
   269 
   270     if ( !iFlushDone ) // Flush only once
   271         {
   272         iFlushDone = ETrue;
   273         for ( TInt i=0; i < KMetaDataWriterInputBufCount; i++ )
   274             {
   275             if ( iOutputFile[i] )
   276                 {
   277 		    	PRINT((_L("e_cmetadatawriter_flush_write_tempfiles 1")));
   278                 error = iOutputFile[i]->Flush();
   279     			PRINT((_L("e_cmetadatawriter_flush_write_tempfiles 0")));
   280                 PRINT((_L("CMetaDataFileWriter::Flush() inputbuf[%d] flush return code: %d"), i, error));
   281                 }
   282 	        }
   283         }
   284 
   285     iFlush = EFalse;
   286     PRINT((_L("CMetaDataFileWriter::Flush() FullCount: %d <= Should be 0"), iOutputBufferQueue.Count()));
   287     PRINT(_L("CMetaDataFileWriter::Flush() out"));
   288     PRINT((_L("e_cmetadatawriter_flush 0")));
   289     return KErrNone;
   290     }
   291 
   292 // -----------------------------------------------------------------------------
   293 // CMetaDataFileWriter::AddDataToBuffer( const TDesC8& aBuf )
   294 // Writes incoming data to internal buffers and buffer queues..
   295 // (other items were commented in a header).
   296 // -----------------------------------------------------------------------------
   297 //
   298 TInt CMetaDataFileWriter::AddDataToBuffer(const TInt aFileNumber, const TDesC8& aBuf )
   299     {
   300     PRINT(_L("CMetaDataFileWriter::AddDataToBuffer() in"));
   301 
   302     TInt byteswritten = 0;
   303     TInt numbytes = 0;
   304     TInt available = 0; // Available bytes in write buffer
   305     TInt error = KErrNone;
   306     
   307     HBufC8* inputBuf = iInputBufferArray[aFileNumber]->iData;
   308 
   309     if ( iError != KErrNone )
   310         {
   311         PRINT((_L("CMetaDataFileWriter::AddDataToBuffer() out, RunL iError: %d"), iError));
   312         return iError;
   313         }
   314 
   315     PRINT((_L("CMetaDataFileWriter::AddDataToBuffer() Save Buffer, Size: %d "),  aBuf.Length() ));
   316 
   317     while (byteswritten < aBuf.Length() )
   318         {
   319         available = (inputBuf->Des()).MaxLength() - inputBuf->Length();
   320 
   321         if (available > 0)
   322             {
   323             numbytes = aBuf.Length() - byteswritten;
   324             if (numbytes > available)
   325                 {
   326                 numbytes = available;
   327                 }
   328             inputBuf->Des().Append( aBuf.Mid( byteswritten, numbytes ) );
   329             byteswritten += numbytes;
   330             }
   331         else // Buffer is full, move it to outputqueue and use empty/new buf as input.
   332             {
   333             if ( iEmptyBufferQueue.Count() == 0 )
   334                 {
   335                 CMetaDataWriterBuffer* emptyInputBuffer = 0;
   336 
   337                 emptyInputBuffer = new CMetaDataWriterBuffer;
   338                 if ( !emptyInputBuffer )
   339                     {
   340                     PRINT((_L("CMetaDataFileWriter::AddDataToBuffer(), memory alloc failed")));
   341                     iError = KErrNoMemory;
   342                     break;
   343                     }
   344 
   345                 TRAP(error, emptyInputBuffer->iData = HBufC8::NewL( KMetaDataWriterBufferSize ));
   346                 if ( error != KErrNone )
   347                     {
   348                     PRINT((_L("CMetaDataFileWriter::AddDataToBuffer(), memory alloc failed: %d"), error));
   349                     delete emptyInputBuffer;
   350                     emptyInputBuffer = NULL;
   351                     iError = error;
   352                     break;
   353                     }
   354                 else
   355                     {                    
   356                     error = iOutputBufferQueue.Append(iInputBufferArray[aFileNumber]);
   357                     if (error != KErrNone)
   358                     	{
   359                         PRINT((_L("CMetaDataFileWriter::AddDataToBuffer(), memory alloc failed: %d"), error));
   360                         delete emptyInputBuffer;
   361                         emptyInputBuffer = NULL;
   362                         iError = error;
   363                         break;
   364                     	}
   365                     
   366                 	// old full buffer to output queue.
   367                     emptyInputBuffer->iOutputFileNum = aFileNumber;
   368                     
   369                     // new buffer to input.
   370                     iInputBufferArray[aFileNumber] = emptyInputBuffer;
   371                     }
   372                 }
   373             else
   374                 {
   375                 // old full buffer to output queue.
   376                 TInt err = iOutputBufferQueue.Append( iInputBufferArray[aFileNumber] );
   377                 if (err != KErrNone)
   378                 	{
   379                 	PRINT((_L("CMetaDataFileWriter::AddDataToBuffer(), iOutputBufferQueue.Append failed: %d"), err));
   380                 	iError = err;
   381                 	break;
   382                 	}
   383                 
   384                 // empty buffer from empty queue to input.
   385                 iInputBufferArray[aFileNumber] = iEmptyBufferQueue[0];
   386                 iInputBufferArray[aFileNumber]->iData->Des().Zero();
   387                 iInputBufferArray[aFileNumber]->iOutputFileNum = aFileNumber;
   388                 iEmptyBufferQueue.Remove(0);                
   389                 }
   390 
   391             inputBuf = iInputBufferArray[aFileNumber]->iData;
   392             }
   393         }
   394 
   395     PRINT((_L("CMetaDataFileWriter::AddDataToBuffer() out, error: %d"), error));
   396     return error;
   397     }
   398 
   399 // -----------------------------------------------------------------------------
   400 // CMetaDataFileWriter::DoCancel()
   401 // From CActive Cancels async request.
   402 // -----------------------------------------------------------------------------
   403 //
   404 void CMetaDataFileWriter::DoCancel()
   405     {
   406     }
   407 
   408 // -----------------------------------------------------------------------------
   409 // CMetaDataFileWriter::RunL()
   410 // From CActive Called when async request completes.
   411 // -----------------------------------------------------------------------------
   412 //
   413 void CMetaDataFileWriter::RunL()
   414     {
   415     PRINT(_L("CMetaDataFileWriter::RunL() in"));
   416 	PRINT((_L("e_cmetadatawriter_runl 1")));
   417     iAsyncWritingOngoing = EFalse;
   418 
   419     if ( iStatus == KErrNone )
   420         {
   421         iEmptyBufferQueue.AppendL( iOutputBufferQueue[0] );        
   422         iOutputBufferQueue[0]->iData->Des().Zero();
   423         iOutputBufferQueue[0]->iOutputFileNum = -1;
   424         iOutputBufferQueue.Remove( 0 );
   425         }
   426     else
   427         {
   428         PRINT((_L("CMetaDataFileWriter::RunL() Write error in previous async: %d "), iStatus.Int() ));
   429         iError = iStatus.Int();
   430         return;
   431         }
   432 
   433     PRINT((_L("CMetaDataFileWriter::RunL() Buffer written, Status: Full:%d Empty:%d "), iOutputBufferQueue.Count(), iEmptyBufferQueue.Count() ));
   434     
   435     if ( iFlush )
   436         {
   437         PRINT(_L("CMetaDataFileWriter::RunL() out, flushing"));
   438         PRINT((_L("e_cmetadatawriter_runl 0")));
   439         return;
   440         }
   441 
   442     if ( iOutputBufferQueue.Count() >= KFileWriterHardBufLimit )
   443         {
   444         while ( iOutputBufferQueue.Count() > KFileWriterSoftBufLimit )
   445             {
   446         	PRINT((_L("e_cmetadatawriter_runl1_write 1")));
   447             iError = iOutputFile[iOutputBufferQueue[0]->iOutputFileNum]->Write( *(iOutputBufferQueue[0]->iData));
   448         	PRINT((_L("e_cmetadatawriter_runl1_write 0")));
   449             if ( iError == KErrNone )
   450                 {
   451                 iEmptyBufferQueue.AppendL( iOutputBufferQueue[0] );
   452                 iOutputBufferQueue[0]->iData->Des().Zero();
   453                 iOutputBufferQueue[0]->iOutputFileNum = -1;                
   454                 iOutputBufferQueue.Remove( 0 );
   455                 }   
   456             else
   457                 {
   458                 PRINT((_L("CMetaDataFileWriter::RunL() Write error: %d "), iError));
   459                 return;
   460                 }   
   461             }
   462         }
   463 
   464     if ( iOutputBufferQueue.Count() >= KFileWriterSoftBufLimit )
   465         {
   466       	PRINT((_L("e_cmetadatawriter_runl2_write 1")));
   467         iError = iOutputFile[iOutputBufferQueue[0]->iOutputFileNum]->Write(  *(iOutputBufferQueue[0]->iData));
   468       	PRINT((_L("e_cmetadatawriter_runl2_write 0")));
   469         if ( iError == KErrNone )
   470             {
   471             iEmptyBufferQueue.AppendL( iOutputBufferQueue[0] );            
   472             iOutputBufferQueue[0]->iData->Des().Zero();
   473             iOutputBufferQueue[0]->iOutputFileNum = -1;
   474             iOutputBufferQueue.Remove( 0 );
   475             }   
   476         else
   477             {
   478             PRINT((_L("CMetaDataFileWriter::RunL() Write error: %d "), iError));
   479             return;
   480             }
   481         }
   482 
   483     if ( iOutputBufferQueue.Count() )
   484         {
   485       	PRINT((_L("e_cmetadatawriter_runl3_write 1")));
   486         iOutputFile[iOutputBufferQueue[0]->iOutputFileNum]->Write( *(iOutputBufferQueue[0]->iData), iStatus );
   487       	PRINT((_L("e_cmetadatawriter_runl3_write 0")));
   488         iAsyncWritingOngoing = ETrue;
   489         if ( !IsActive() )
   490             {
   491             SetActive();
   492             }
   493         }
   494 
   495 	PRINT((_L("e_cmetadatawriter_runl 0")));
   496     PRINT(_L("CMetaDataFileWriter::RunL() out"));
   497     }
   498 
   499 // -----------------------------------------------------------------------------
   500 // CMetaDataFileWriter::RunError
   501 // -----------------------------------------------------------------------------
   502 //
   503  TInt CMetaDataFileWriter::RunError(TInt aError)
   504 	 {
   505 	 //RunL can leave.
   506 	 iError = aError;
   507 	 return KErrNone ;
   508 	 }
   509  
   510 // -----------------------------------------------------------------------------
   511 // CMetaDataFileWriter::ReadBuffer
   512 // -----------------------------------------------------------------------------
   513 //
   514 TInt CMetaDataFileWriter::ReadBuffer( const TInt aFileNumber, TDes8& aBuf, TInt bytestoread )
   515     {
   516     PRINT(_L("CMetaDataFileWriter::ReadBuffer() in"));
   517 	PRINT((_L("e_cmetadatawriter_readbuffer 1")));
   518     TInt bytesread;
   519     
   520     PRINT((_L("CMetaDataFileWriter::ReadBuffer() iInputBufferArray[%d]->iData->Length(): %d, requested %d"), aFileNumber, iInputBufferArray[aFileNumber]->iData->Length(), bytestoread));
   521     if ( !iInputBufferArray[aFileNumber]->iData->Length() )
   522         {
   523         bytesread = 0;
   524         }
   525     else if ( (iInputBufferArray[aFileNumber]->iData->Length() -
   526         iInputBufferArrayDelivered[aFileNumber]) >= bytestoread )
   527         {
   528         bytesread = bytestoread;
   529         aBuf.Append( iInputBufferArray[aFileNumber]->iData->Mid( iInputBufferArrayDelivered[aFileNumber], bytesread ) );
   530         iInputBufferArrayDelivered[aFileNumber] += bytesread;
   531         
   532         // If the buffer is read empty, release it
   533         if ( iInputBufferArray[aFileNumber]->iData->Length() == iInputBufferArrayDelivered[aFileNumber] )
   534             {
   535             PRINT((_L("CMetaDataFileWriter::ReadBuffer() iInputBufferArray[%d] %d delivered"), aFileNumber, iInputBufferArray[aFileNumber]->iData->Length()));
   536             iInputBufferArray[aFileNumber]->iData->Des().Zero();
   537             }
   538         }
   539     else
   540         {
   541         bytesread = iInputBufferArray[aFileNumber]->iData->Length() - iInputBufferArrayDelivered[aFileNumber];
   542         aBuf.Append( iInputBufferArray[aFileNumber]->iData->Mid( iInputBufferArrayDelivered[aFileNumber], bytesread ) );
   543         iInputBufferArrayDelivered[aFileNumber] += bytesread;
   544 
   545         PRINT((_L("CMetaDataFileWriter::ReadBuffer() iInputBufferArray[%d] %d bytes delivered"), aFileNumber, iInputBufferArray[aFileNumber]->iData->Length()));
   546         iInputBufferArray[aFileNumber]->iData->Des().Zero();
   547         }
   548         
   549 	PRINT((_L("e_cmetadatawriter_readbuffer 0")));
   550     PRINT(_L("CMetaDataFileWriter::ReadBuffer() out"));
   551 
   552     return ( bytesread );
   553     }
   554 
   555 //  End of File