os/mm/mmplugins/lib3gp/impl/src/filewriter.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 "filewriter.h"
    22 
    23 // MACROS
    24 // Debug print macro
    25 #ifdef _DEBUG
    26 #include <e32svr.h>
    27 //#define PRINT(x) RDebug::Print x
    28 #define PRINT(x)
    29 #else
    30 #define PRINT(x)
    31 #endif
    32 
    33 // ============================ MEMBER FUNCTIONS ===============================
    34 
    35 // -----------------------------------------------------------------------------
    36 // CFileWriter::CFileWriter
    37 // C++ default constructor can NOT contain any code, that
    38 // might leave.
    39 // -----------------------------------------------------------------------------
    40 //
    41 CFileWriter::CFileWriter( TInt aInitSetSize, TInt aOutputBufferSizeSmall, TInt aOutputBufferSizeLarge ):
    42 	CActive( EPriorityHigh ),
    43 	iSetSize( aInitSetSize ),
    44 	iOutputBufferSizeSmall( aOutputBufferSizeSmall ),
    45 	iOutputBufferSizeLarge( aOutputBufferSizeLarge )
    46     {
    47     }
    48 
    49 // -----------------------------------------------------------------------------
    50 // CFileWriter::ConstructL
    51 // Symbian 2nd phase constructor can leave.
    52 // -----------------------------------------------------------------------------
    53 //
    54 void CFileWriter::ConstructL( RFile64& aFile )
    55     {
    56     PRINT((_L("CFileWriter::ConstructL() in")));         
    57     iFlush = EFalse;
    58     iError = KErrNone;
    59 
    60     iOutputFile = &aFile;
    61     iWritingStarted = EFalse;
    62     iOutputBufferSize = KFileWriterBufferSizeSmall;
    63     iMaxOutputBufHardLimit = KFileWriterHardBufLimit;
    64     iMaxOutputBufSoftLimit = KFileWriterSoftBufLimit;
    65 
    66     iMemReadyForWriting = EFalse;
    67     iInputBuf = NULL;
    68     iEmptyBufferQueue.Reset();
    69     iFullBufferQueue.Reset();
    70 
    71     AllocateBuffersL();
    72     CActiveScheduler::Add(this);
    73     PRINT((_L("CFileWriter::ConstructL() out")));         
    74     }
    75 
    76 // -----------------------------------------------------------------------------
    77 // CFileWriter::NewL
    78 // Two-phased constructor.
    79 // -----------------------------------------------------------------------------
    80 //
    81 CFileWriter* CFileWriter::NewL( RFile64& aFile, TInt aInitSetSize, TInt aOutputBufferSizeSmall, TInt aOutputBufferSizeLarge )
    82     {
    83     CFileWriter* self = new(ELeave) CFileWriter( aInitSetSize, aOutputBufferSizeSmall, aOutputBufferSizeLarge );
    84     CleanupStack::PushL(self);
    85     self->ConstructL( aFile );
    86     CleanupStack::Pop(self);
    87     return self;
    88     }
    89 
    90 
    91 // Destructor
    92 CFileWriter::~CFileWriter()
    93     {
    94     PRINT((_L("CFileWriter::~CFileWriter() in")));         
    95     if ( IsActive() )
    96         {
    97         if ( iAsyncWritingOngoing )
    98             {
    99             Cancel();    
   100             }
   101         else
   102             {
   103             TRequestStatus* status = &iStatus;
   104             User::RequestComplete( status, KErrNone );
   105             Cancel();
   106             }
   107         }
   108 
   109     if ( iInputBuf )
   110         {
   111         delete iInputBuf;
   112         }
   113 
   114     iEmptyBufferQueue.ResetAndDestroy();
   115     iFullBufferQueue.ResetAndDestroy();
   116     PRINT((_L("CFileWriter::~CFileWriter() out")));         
   117     }
   118 
   119 // -----------------------------------------------------------------------------
   120 // CFileWriter::UpdateOutputFileSize()
   121 // Updates output file size and reserves extra space for following writing 
   122 // if iSetSize is set.  
   123 // Takes into account if the position in the file was changed.
   124 // -----------------------------------------------------------------------------
   125 //
   126 void CFileWriter::UpdateOutputFileSize()
   127     {
   128     TInt64 pos = 0;
   129     PRINT((_L("e_cfilewriter_write_updateoutputfilesize_seek 1")));
   130     iOutputFile->Seek(ESeekCurrent, pos);
   131     PRINT((_L("e_cfilewriter_write_updateoutputfilesize_seek 0")));
   132     
   133     PRINT((_L("CFileWriter::UpdateOutputFileSize() pos: %Ld"), pos));
   134     PRINT((_L("CFileWriter::UpdateOutputFileSize() iOutputFileSize: %Ld"), iOutputFileSize));
   135     PRINT((_L("CFileWriter::UpdateOutputFileSize() iSetSize: %Ld"), iSetSize));
   136     
   137     if (pos > iOutputFileSize) 
   138         {
   139         iOutputFileSize = pos;
   140         }
   141     
   142     while (iOutputFileSize >= iSetSize) 
   143         {
   144         iSetSize += static_cast<TInt64>(iOutputBufferSize) * (static_cast<TInt64>(iMaxOutputBufHardLimit) >> 1); 
   145         PRINT((_L("e_cfilewriter_updateoutputfilesize_setsize 1")));                     
   146         iOutputFile->SetSize( iSetSize );
   147         PRINT((_L("e_cfilewriter_updateoutputfilesize_setsize 0")));                     
   148         }
   149     }
   150 
   151 // -----------------------------------------------------------------------------
   152 // CFileWriter::Write( const TDesC8& aBuf )
   153 // Writes incoming buffer data to internal buffers for writing to disk.
   154 // (other items were commented in a header).
   155 // -----------------------------------------------------------------------------
   156 //
   157 TInt CFileWriter::Write( const TDesC8& aBuf )
   158     {
   159     PRINT(_L("CFileWriter::Write() in"));
   160     PRINT((_L("e_cfilewriter_write 1")));
   161 
   162     iWritingStarted = ETrue;
   163     
   164     if ( !iMemReadyForWriting )
   165     	{
   166     	return KErrNoMemory;
   167     	}
   168 
   169     PRINT((_L("e_cfilewriter_write_adddatatobuffer 1")));	
   170     TInt error = AddDataToBuffer( aBuf );
   171     PRINT((_L("e_cfilewriter_write_adddatatobuffer 0")));	    
   172     
   173     if ( error != KErrNone )
   174         {
   175         PRINT((_L("CFileWriter::Write() buffer write error: %d"), error));         
   176         return error;
   177         }
   178 
   179     PRINT((_L("CFileWriter::Write() Write Buffer, Status: Full:%d Empty:%d "), 
   180                     iFullBufferQueue.Count(), iEmptyBufferQueue.Count() ));
   181 
   182     if ( iAsyncWritingOngoing )
   183         {
   184         if ( iFullBufferQueue.Count() >= iMaxOutputBufHardLimit )
   185             {
   186             PRINT((_L("CFileWriter::Write() Waiting async write to complete")));
   187 			PRINT((_L("e_cfilewriter_write_wait_async 1")));            
   188             User::WaitForRequest( iStatus );
   189 			PRINT((_L("e_cfilewriter_write_wait_async 0")));            
   190             PRINT((_L("CFileWriter::Write() Async write done")));
   191             TRAP(error, RunL());
   192             if (error != KErrNone)
   193             	{
   194             	PRINT((_L("CFileWriter::Write() call runL leave, error: %d"), error));         
   195                 return error;
   196             	}
   197             }
   198         }
   199     else
   200         {
   201         if ( iFullBufferQueue.Count() )
   202             {
   203             PRINT(_L("CFileWriter::Write() writing async"));                     
   204             PRINT((_L("e_cfilewriter_write_startwrite 1")));                     
   205             iOutputFile->Write( *iFullBufferQueue[0], iStatus );
   206             PRINT((_L("e_cfilewriter_write_startwrite 0")));
   207             iAsyncWritingOngoing = ETrue;
   208             if ( !IsActive() )
   209                 {
   210                 SetActive();
   211                 }
   212             }
   213         }
   214 
   215     PRINT(_L("CFileWriter::Write() out"));
   216     PRINT((_L("e_cfilewriter_write 0")));    
   217     return error;
   218     }
   219 
   220 // -----------------------------------------------------------------------------
   221 // CFileWriter::Flush( const TDesC8& aBuf )
   222 // Flush internal buffers to disk.
   223 // (other items were commented in a header).
   224 // -----------------------------------------------------------------------------
   225 //
   226 TInt CFileWriter::Flush( const TDesC8& aBuf )
   227     {
   228     PRINT(_L("CFileWriter::Flush() in"));
   229     PRINT((_L("e_cfilewriter_flush 1")));
   230  
   231  	if ( !iMemReadyForWriting )
   232  		{
   233  		return KErrNoMemory;
   234  		}
   235  	
   236     iWritingStarted = ETrue;
   237 
   238     PRINT((_L("e_cfilewriter_flush_adddatatobuf 1")));
   239     TInt error = AddDataToBuffer( aBuf );
   240     if ( error != KErrNone )
   241         {
   242         return error;
   243         }
   244 	PRINT((_L("e_cfilewriter_flush_adddatatobuf 0")));        
   245 
   246     PRINT((_L("CFileWriter::Flush() FullCount: %d "), iFullBufferQueue.Count()));
   247     iFlush = ETrue;
   248 
   249     if ( iAsyncWritingOngoing )
   250         {
   251         PRINT((_L("CFileWriter::Flush() Waiting async write to complete")));
   252         PRINT((_L("e_cfilewriter_flush_waitasynctostop 1")));
   253         User::WaitForRequest( iStatus );
   254         PRINT((_L("e_cfilewriter_flush_waitasynctostop 0")));
   255         PRINT((_L("CFileWriter::Flush() Async write done, flushing")));
   256         TRAP(error, RunL());
   257         if (error != KErrNone)
   258         	{
   259         	PRINT((_L("CFileWriter::Flush() call runL leave, error: %d"), error));         
   260             return error;
   261         	}
   262         }
   263 
   264     while ( iFullBufferQueue.Count() )
   265         {
   266         PRINT((_L("e_cfilewriter_flush_writequeue_sync 1")));
   267         error = iOutputFile->Write( *iFullBufferQueue[0] );
   268         PRINT((_L("e_cfilewriter_flush_writequeue_sync 0")));
   269         PRINT((_L("e_cfilewriter_flush_remove_buf 1")));
   270         if ( error == KErrNone )
   271             {
   272             UpdateOutputFileSize();
   273             iFullBufferQueue[0]->Des().Zero();
   274             if ( iEmptyBufferQueue.Append( iFullBufferQueue[0] ) )
   275                 {
   276                 PRINT(_L("CFileWriter::Flush() Append failed"));
   277                 delete ( iFullBufferQueue[0] ); 
   278                 }
   279             iFullBufferQueue.Remove( 0 );
   280             }
   281         else
   282             {
   283             PRINT((_L("CFileWriter::Flush() fullBufQueue write failed, error: %d"), error));
   284             iFlush = EFalse;
   285             return error;
   286             }
   287         PRINT((_L("e_cfilewriter_flush_remove_buf 0")));    
   288         }
   289 
   290     if ( iInputBuf->Length() )
   291         {
   292         PRINT((_L("e_cfilewriter_flush_writeinput_sync 1")));
   293         error = iOutputFile->Write( *iInputBuf );
   294         PRINT((_L("e_cfilewriter_flush_writeinput_sync 0")));
   295         if ( error == KErrNone )
   296             {
   297             UpdateOutputFileSize();
   298             iInputBuf->Des().Zero();
   299             }
   300         else
   301             {
   302             PRINT((_L("CFileWriter::Flush() inputbuf write failed, error: %d"), error));
   303             iFlush = EFalse;
   304             return error;
   305             }
   306         }
   307         
   308     iFlush = EFalse;
   309     PRINT((_L("CFileWriter::Flush() FullCount: %d <= Should be 0"), iFullBufferQueue.Count()));
   310     PRINT(_L("CFileWriter::Flush() out"));
   311     PRINT((_L("e_cfilewriter_flush 0")));    
   312     return KErrNone;
   313     }
   314 
   315 
   316 // -----------------------------------------------------------------------------
   317 // CFileWriter::SetOutputBufferSize( TOutputBufferSize aBufferSize )
   318 // Set output buffer sizes.
   319 // (other items were commented in a header).
   320 // -----------------------------------------------------------------------------
   321 //
   322 TInt CFileWriter::SetOutputBufferSize( TOutputBufferSize aBufferSize, MP4Handle aHandle )
   323     {
   324     MP4HandleImp handle = (MP4HandleImp)aHandle;    
   325     TInt size = 0;
   326 
   327     if ( iWritingStarted )
   328         {
   329         return KErrNotReady;
   330         }
   331 
   332     if ( aBufferSize == EBufferSizeSmall ) 
   333         {
   334         size = iOutputBufferSizeSmall;
   335         }
   336     else if ( aBufferSize == EBufferSizeLarge ) 
   337         {
   338         size = iOutputBufferSizeLarge;
   339         }
   340     else if ( aBufferSize == EBufferSizeCustom )
   341         {
   342         size = handle->mediaWriteBufferSize;
   343         }
   344     else
   345         {
   346         return KErrArgument;    
   347         }
   348 
   349     if ( size == iOutputBufferSize )
   350         {
   351         return KErrNone;
   352         }
   353     else
   354         {
   355         iOutputBufferSize = size;
   356         }
   357 
   358     iMemReadyForWriting = EFalse;
   359     delete iInputBuf;
   360     iInputBuf = NULL;
   361     iEmptyBufferQueue.ResetAndDestroy();
   362     iFullBufferQueue.ResetAndDestroy();
   363 
   364     TRAPD(err, AllocateBuffersL() );
   365     return err;
   366     }
   367 
   368 // -----------------------------------------------------------------------------
   369 // CFileWriter::SetOutputBufferCount( MP4Handle aHandle )
   370 // Set output buffer count.
   371 // (other items were commented in a header).
   372 // -----------------------------------------------------------------------------
   373 //
   374 void CFileWriter::SetOutputBufferCount( MP4Handle aHandle )
   375     {
   376     MP4HandleImp handle = (MP4HandleImp)aHandle;    
   377 
   378     if (  handle->writeBufferMaxCount >= 6 )     
   379         {
   380         iMaxOutputBufHardLimit = handle->writeBufferMaxCount;
   381         iMaxOutputBufSoftLimit = KFileWriterMinBufferCount + ((iMaxOutputBufHardLimit-KFileWriterMinBufferCount)/2);
   382         }
   383     }
   384 
   385 
   386 // -----------------------------------------------------------------------------
   387 // CFileWriter::AddDataToBuffer( const TDesC8& aBuf )
   388 // Writes incoming data to internal buffers and buffer queues..
   389 // (other items were commented in a header).
   390 // -----------------------------------------------------------------------------
   391 //
   392 TInt CFileWriter::AddDataToBuffer( const TDesC8& aBuf )
   393     {
   394     PRINT(_L("CFileWriter::AddDataToBuffer() in"));
   395 
   396     TInt byteswritten = 0;
   397     TInt numbytes = 0;
   398     TInt available = 0; // Available bytes in write buffer
   399     TInt error = KErrNone;
   400 
   401     if ( iError != KErrNone )
   402         {
   403         PRINT((_L("CFileWriter::AddDataToBuffer() out, RunL iError: %d"), iError));
   404         return iError;
   405         }
   406 
   407     if ( iInputBuf == NULL )
   408     	{
   409     	return KErrNoMemory;
   410     	}
   411 
   412     while (byteswritten < aBuf.Length() )
   413         {
   414         available = iOutputBufferSize - iInputBuf->Length();
   415 
   416         if (available > 0)
   417             {
   418             numbytes = aBuf.Length() - byteswritten;
   419             if (numbytes > available)
   420                 {
   421                 numbytes = available;
   422                 }
   423             iInputBuf->Des().Append( aBuf.Mid( byteswritten, numbytes ) );
   424             byteswritten += numbytes;
   425             }
   426         else // Buffer is full, write it to disk
   427             {
   428             // input is full, move full inputbuf to full buf queue
   429             if ( iFullBufferQueue.Append( iInputBuf ) != KErrNone )
   430                 {
   431                 PRINT(_L("CFileWriter::AddDataToBuffer() Append failed"));
   432                 delete iInputBuf;
   433                 iInputBuf = NULL;
   434                 }
   435             if ( iEmptyBufferQueue.Count() == 0 )
   436                 {
   437                 // no empty buffers in queue, allocating new one
   438                 TRAP(error, iInputBuf = HBufC8::NewL( iOutputBufferSize ));
   439                 if ( error != KErrNone )
   440                     {
   441                     PRINT((_L("CFileWriter::AddDataToBuffer(), memory alloc failed: %d"), error));
   442                     iInputBuf = NULL;
   443                     iError = error;
   444                     break;
   445                     }
   446                 }
   447             else
   448                 {
   449                 iInputBuf = iEmptyBufferQueue[ 0 ];
   450                 iEmptyBufferQueue.Remove( 0 );
   451                 }
   452             }
   453         }
   454 
   455     PRINT((_L("CFileWriter::AddDataToBuffer() out, error: %d"), error));
   456     return error;
   457     }
   458 
   459 // -----------------------------------------------------------------------------
   460 // CFileWriter::AllocateBuffersL()
   461 // Allocates input and output buffers.
   462 // (other items were commented in a header).
   463 // -----------------------------------------------------------------------------
   464 //
   465 void CFileWriter::AllocateBuffersL()
   466     {
   467     PRINT((_L("CFileWriter::AllocateBuffersL() in, outbufsize: %d"), iOutputBufferSize));
   468     HBufC8* buf = NULL;
   469     TInt err = 0;
   470     iMemReadyForWriting = EFalse;
   471 
   472     iInputBuf = HBufC8::NewL( iOutputBufferSize );
   473     for( TInt i=0; i<KFileWriterMinBufferCount; i++ )
   474         {
   475         buf = HBufC8::NewL( iOutputBufferSize );
   476         err = iEmptyBufferQueue.Append( buf );
   477         if ( err )
   478             {
   479             delete ( buf );
   480             User::Leave( err );
   481             }
   482         }
   483     iMemReadyForWriting = ETrue;
   484     PRINT((_L("CFileWriter::AllocateBuffersL() out")));
   485     }
   486 
   487 // -----------------------------------------------------------------------------
   488 // CFileWriter::DoCancel()
   489 // From CActive Cancels async request.
   490 // -----------------------------------------------------------------------------
   491 //
   492 void CFileWriter::DoCancel()
   493     {
   494     }
   495 
   496 // -----------------------------------------------------------------------------
   497 // CFileWriter::RunL()
   498 // From CActive Called when async request completes.
   499 // -----------------------------------------------------------------------------
   500 //
   501 void CFileWriter::RunL()
   502     {
   503     PRINT(_L("CFileWriter::RunL() in"));
   504 	PRINT((_L("e_cfilewriter_runl 1")));    
   505     iAsyncWritingOngoing = EFalse;
   506 
   507     if ( iStatus == KErrNone )
   508         {
   509         UpdateOutputFileSize();                    
   510         iFullBufferQueue[0]->Des().Zero();
   511         iError = iEmptyBufferQueue.Append( iFullBufferQueue[0] );
   512         if ( iError )
   513             {
   514             PRINT((_L("CFileWriter::RunL() Append failed 1 %d"), iError ));
   515             delete ( iFullBufferQueue[0] );
   516             iFullBufferQueue.Remove( 0 );
   517             return;
   518             }
   519         iFullBufferQueue.Remove( 0 );
   520         }
   521     else
   522         {
   523         PRINT((_L("CFileWriter::RunL() Write error in previous async: %d "), iStatus.Int() ));
   524         iError = iStatus.Int();
   525         return;
   526         }
   527 
   528     PRINT((_L("CFileWriter::RunL() Buffer written, Status: Full:%d Empty:%d Filesize:%Ld"), iFullBufferQueue.Count(), iEmptyBufferQueue.Count(), iOutputFileSize ));
   529     
   530     if ( iFlush )
   531         {
   532         PRINT(_L("CFileWriter::RunL() out, flushing"));
   533         PRINT((_L("e_cfilewriter_runl 0")));  
   534         return;
   535         }
   536 
   537     if ( iFullBufferQueue.Count() >= iMaxOutputBufHardLimit )
   538         {
   539         while ( iFullBufferQueue.Count() > iMaxOutputBufSoftLimit )
   540             {
   541             PRINT((_L("e_cfilewriter_runl_write 1")));                     
   542             iError = iOutputFile->Write( *iFullBufferQueue[0]);
   543             PRINT((_L("e_cfilewriter_runl_write 0")));                     
   544             if ( iError == KErrNone )
   545                 {
   546                 UpdateOutputFileSize();
   547                 iFullBufferQueue[0]->Des().Zero();
   548                 iError = iEmptyBufferQueue.Append( iFullBufferQueue[0] );
   549                 if ( iError )
   550                     {
   551                     PRINT((_L("CFileWriter::RunL() Append failed 2 %d"), iError));
   552                     delete ( iFullBufferQueue[0] );
   553                     iFullBufferQueue.Remove( 0 );
   554                     return;
   555                     }
   556                 iFullBufferQueue.Remove( 0 );
   557     			PRINT((_L("CFileWriter::RunL() Hardlimit : Buffer sync written, Status: Full:%d Empty:%d Filesize:%Ld"), iFullBufferQueue.Count(), iEmptyBufferQueue.Count(), iOutputFileSize ));
   558                 }   
   559             else
   560                 {
   561                 PRINT((_L("CFileWriter::RunL() Write error: %d "), iError));
   562                 return;
   563                 }   
   564             }
   565         }
   566 
   567     if ( iFullBufferQueue.Count() >= iMaxOutputBufSoftLimit )
   568         {
   569         PRINT((_L("e_cfilewriter_runl_outfile_write 1")));                     
   570         iError = iOutputFile->Write( *iFullBufferQueue[0]);
   571         PRINT((_L("e_cfilewriter_runl_outfile_write 0")));                     
   572         if ( iError == KErrNone )
   573             {
   574             UpdateOutputFileSize();
   575             iFullBufferQueue[0]->Des().Zero();
   576             iError = iEmptyBufferQueue.Append( iFullBufferQueue[0] );
   577             if ( iError )
   578                 {
   579                 PRINT((_L("CFileWriter::RunL() Append failed 3 %d"), iError));
   580                 delete ( iFullBufferQueue[0] );
   581                 iFullBufferQueue.Remove( 0 );
   582                 return;
   583                 }
   584             iFullBufferQueue.Remove( 0 );
   585     		PRINT((_L("CFileWriter::RunL() Softlimit : Buffer sync written, Status: Full:%d Empty:%d Filesize:%Ld"), iFullBufferQueue.Count(), iEmptyBufferQueue.Count(), iOutputFileSize ));
   586             }   
   587         else
   588             {
   589             PRINT((_L("CFileWriter::RunL() Write error: %d "), iError));
   590             return;
   591             }
   592         }
   593 
   594     if ( iFullBufferQueue.Count() )
   595         {
   596         PRINT((_L("e_cfilewriter_runl_outfile2_write 1")));                     
   597         iOutputFile->Write( *iFullBufferQueue[0], iStatus );
   598         PRINT((_L("e_cfilewriter_runl_outfile2_write 0")));                     
   599         iAsyncWritingOngoing = ETrue;
   600         if ( !IsActive() )
   601             {
   602             SetActive();
   603             }
   604         }
   605 
   606 	PRINT((_L("e_cfilewriter_runl 0")));  
   607     PRINT((_L("CFileWriter::RunL() out, iError=%d"), iError));
   608     }
   609 
   610 //  End of File