dvrengine/CommonRecordingEngine/DvrRtpClipHandler/src/CRtpToFile.cpp
branchRCL_3
changeset 22 826cea16efd9
parent 21 798ee5f1972c
child 23 13a33d82ad98
equal deleted inserted replaced
21:798ee5f1972c 22:826cea16efd9
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:    Implementation of the Common Recording Engine RTP save format class.*
       
    15 */
       
    16 
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "CRtpToFile.h"
       
    22 #include <ipvideo/CRtpMetaHeader.h>
       
    23 #include <e32math.h>
       
    24 #include <bsp.h>
       
    25 #include "videoserviceutilsLogger.h"
       
    26 
       
    27 // CONSTANTS
       
    28 const TUint KMaxValidDelta( 500 );     // 0.5 s
       
    29 const TUint8 KDummyFullQuality( 100 ); // 100%
       
    30 
       
    31 // ============================ MEMBER FUNCTIONS ===============================
       
    32 
       
    33 // -----------------------------------------------------------------------------
       
    34 // CRtpToFile::NewL
       
    35 // Static two-phased constructor. Leaves object to cleanup stack.
       
    36 // -----------------------------------------------------------------------------
       
    37 //
       
    38 CRtpToFile* CRtpToFile::NewL(
       
    39     MRtpFileObserver& aFileObs,
       
    40     MRtpFileWriteObserver& aWriteObs )
       
    41     {
       
    42     CRtpToFile* self = new( ELeave ) CRtpToFile( aFileObs, aWriteObs );
       
    43     CleanupStack::PushL( self );
       
    44     self->ConstructL();
       
    45     CleanupStack::Pop( self );
       
    46     return self;
       
    47     }
       
    48 
       
    49 // -----------------------------------------------------------------------------
       
    50 // CRtpToFile::CRtpToFile
       
    51 // C++ default constructor can NOT contain any code, that might leave.
       
    52 // -----------------------------------------------------------------------------
       
    53 //
       
    54 CRtpToFile::CRtpToFile(
       
    55     MRtpFileObserver& aFileObs,
       
    56     MRtpFileWriteObserver& aWriteObs )
       
    57   : CRtpFileBase(),
       
    58     iFileObs( aFileObs ),
       
    59     iWriteObs( aWriteObs ),
       
    60     iCurrentTime( 0 ),
       
    61     iPreviousTime( 0 ),
       
    62     iPreviousDelta( 0 ),
       
    63     iReferenceTime( 0 ),
       
    64     iRecordEndTime( 0 ),
       
    65     iSeekArrayReference( 0 ),
       
    66     iGroupReUse( KErrNotFound ),
       
    67     iAction( MRtpFileWriteObserver::ESaveEnd )
       
    68     {
       
    69     // None
       
    70     }
       
    71 
       
    72 // -----------------------------------------------------------------------------
       
    73 // CRtpToFile::ConstructL
       
    74 // Symbian 2nd phase constructor can leave.
       
    75 // -----------------------------------------------------------------------------
       
    76 //
       
    77 void CRtpToFile::ConstructL()
       
    78     {
       
    79     LOG( "CRtpToFile::ConstructL()" );
       
    80     
       
    81     CRtpFileBase::ConstructL();
       
    82     iCurrentPath = HBufC::NewL( 0 );
       
    83     }
       
    84 
       
    85 // -----------------------------------------------------------------------------
       
    86 // Destructor
       
    87 //
       
    88 CRtpToFile::~CRtpToFile()
       
    89 // -----------------------------------------------------------------------------
       
    90     {
       
    91     LOG( "CRtpToFile::~CRtpToFile()" );
       
    92 
       
    93     Cancel();
       
    94     }
       
    95 
       
    96 // -----------------------------------------------------------------------------
       
    97 // CRtpToFile::InitRtpSaveL
       
    98 // Sets path of RTP file and initiates variables.
       
    99 // -----------------------------------------------------------------------------
       
   100 //
       
   101 void CRtpToFile::InitRtpSaveL(
       
   102     const MRtpFileWriteObserver::SRtpRecParams& aParams,
       
   103     const MRtpFileWriteObserver::TRtpSaveAction& aAction )
       
   104     {
       
   105     LOG1( "CRtpToFile::InitRtpSaveL() in, ClipPath: %S", &aParams.iClipPath );
       
   106     User::LeaveIfError( ( iMode != EModeNone ) * KErrInUse );
       
   107     
       
   108     // Mode
       
   109     switch ( aAction )
       
   110         {
       
   111         case MRtpFileWriteObserver::ESaveTimeShift:
       
   112             iMode = EModeTimeShift;
       
   113             break;
       
   114 
       
   115         default:
       
   116             iMode = EModeNormal;
       
   117             break;
       
   118         }
       
   119 
       
   120     // File server
       
   121     if ( !iFs.Handle() )
       
   122         {
       
   123         User::LeaveIfError( iFs.Connect() );
       
   124         }
       
   125 
       
   126     // Create clip
       
   127     CreateNewClipL( aParams );
       
   128 
       
   129     // Real clip's end time
       
   130     iPreviousTime = 0;
       
   131     iReferenceTime = iGroupTime * KSiKilo;
       
   132     UpdateCurrentTimeL();
       
   133     TInt64 duration( aParams.iEndTime.Int64() - 
       
   134                      aParams.iStartTime.Int64() ); 
       
   135     iRecordEndTime = iCurrentTime.Int64() + duration;
       
   136     
       
   137     // Prepare variables
       
   138     iSeekArrayReference = iGroupTime;
       
   139     iStartGroupTime = iGroupTime;
       
   140 
       
   141     LOG( "CRtpToFile::InitRtpSaveL() out" );
       
   142     }
       
   143 
       
   144 // -----------------------------------------------------------------------------
       
   145 // CRtpToFile::ActivateGroupsReuseL
       
   146 // Starts reuse packet groups for live record when they are played.
       
   147 // -----------------------------------------------------------------------------
       
   148 //
       
   149 void CRtpToFile::ActivateGroupsReuseL()
       
   150     {
       
   151     LOG2( "CRtpToFile::ActivateGroupsReuseL(), iMode: %d, iGroupReUse: %d",
       
   152                                               iMode, iGroupReUse );
       
   153     if ( iGroupReUse != KErrNotFound || iMode != EModeTimeShift )
       
   154         {
       
   155         User::Leave( KErrInUse );
       
   156         }
       
   157 
       
   158     iGroupReUse = KErrInUse;
       
   159     }
       
   160     
       
   161 // -----------------------------------------------------------------------------
       
   162 // CRtpToFile::SwapClipL
       
   163 // Sets new path of RTP file and initiates variables.
       
   164 // -----------------------------------------------------------------------------
       
   165 //
       
   166 void CRtpToFile::SwapClipL( const MRtpFileWriteObserver::SRtpRecParams& aParams )
       
   167     {
       
   168     LOG1( "CRtpToFile::SwapClipL(), aClipPath: %S", &aParams.iClipPath );
       
   169 
       
   170     User::LeaveIfError( ( iMode != EModeTimeShift ) * KErrGeneral );
       
   171 
       
   172     // Update old clip
       
   173     WriteSeekHeaderL();
       
   174     iGroupReUse = KErrNotFound;
       
   175         
       
   176     // Open new clip
       
   177     CreateNewClipL( aParams );
       
   178     }
       
   179     
       
   180 // -----------------------------------------------------------------------------
       
   181 // CRtpToFile::SaveNextRtpGroupL
       
   182 // Saves one RTP packet group to a specified file.
       
   183 // -----------------------------------------------------------------------------
       
   184 //
       
   185 TInt CRtpToFile::SaveNextGroupL(
       
   186     TPtr8& aGroup,
       
   187     TUint& aGroupLength,
       
   188     const MRtpFileWriteObserver::TRtpSaveAction& aAction )
       
   189     {
       
   190     // Verify data and mode
       
   191     User::LeaveIfError( iMode );
       
   192     
       
   193     // Group
       
   194     iDataPtr.Set( aGroup );
       
   195     
       
   196     // Set group variables
       
   197     AddGroupL();
       
   198     GroupTimeL( aGroupLength );
       
   199     AddGroupHeaderL(); 
       
   200 
       
   201     // Write to file
       
   202     iAction = aAction;
       
   203     iFile.Write( iThisGroup, iDataPtr, iGroupTotalLen, iStatus );
       
   204     SetActive();
       
   205 
       
   206     LOG2( "CRtpToFile::SaveNextGroupL(), iThisGroup: %d, iGroupTime: %u",
       
   207                                          iThisGroup, iGroupTime );
       
   208 #ifdef CR_ALL_LOGS
       
   209     LogVariables( _L( "SaveNextGroupL()" ) );
       
   210 #endif // CR_ALL_LOGS
       
   211     
       
   212     return iThisGroup;
       
   213     }
       
   214 
       
   215 // -----------------------------------------------------------------------------
       
   216 // CRtpToFile::UpdatePreviousTimeL
       
   217 // Updates previous time after pause.
       
   218 // -----------------------------------------------------------------------------
       
   219 //
       
   220 void CRtpToFile::UpdatePreviousTimeL()
       
   221     {
       
   222     UpdateCurrentTimeL();
       
   223     iPreviousTime = iCurrentTime.Int64();
       
   224     }
       
   225     
       
   226 // -----------------------------------------------------------------------------
       
   227 // CRtpToFile::StopRtpSave
       
   228 // Stops file saving and finalizes header.
       
   229 // -----------------------------------------------------------------------------
       
   230 //
       
   231 void CRtpToFile::StopRtpSave( const TInt aError )
       
   232     {
       
   233     Cancel();
       
   234     const TRtpFileMode mode( iMode ); 
       
   235     
       
   236     // If active
       
   237     if ( mode != EModeNone )
       
   238         {
       
   239 #ifdef CR_ALL_LOGS
       
   240         LogVariables( _L( "StopRtpSave()" ) );
       
   241 #endif // CR_ALL_LOGS
       
   242         iMode = EModeNone;
       
   243 
       
   244         // Update clip headers
       
   245         if ( mode != EModeTimeShift )
       
   246             {
       
   247             TRAP_IGNORE( WriteFinalMetaHeaderL( aError ) );
       
   248             }
       
   249         else
       
   250             {
       
   251             iLastSeekAddr = KMaxTInt;
       
   252             TRAP_IGNORE( WriteSeekHeaderL() );
       
   253             }
       
   254 
       
   255         // Close file
       
   256         iFile.Flush();
       
   257         iFile.Close();
       
   258 
       
   259         if ( aError == KErrNoMemory && !iGroupsTotalCount )
       
   260             {
       
   261             // Failed due to insufficient disk space, and couldn't save any
       
   262             // packets to clip. Happens when recording is started with disk 
       
   263             // space already below threshold, and failed to free any space.
       
   264             // Delete the clip completely, otherwise we are just consuming 
       
   265             // space below threshold(s).
       
   266             LOG( "CRtpToFile::StopRtpSave(), deleting file without packets !" );
       
   267             iFs.Delete( *iCurrentPath );
       
   268             }
       
   269         }
       
   270     }
       
   271 
       
   272 // -----------------------------------------------------------------------------
       
   273 // CRtpToFile::GetClipPath
       
   274 // Getter for full path of currently recorded clip.
       
   275 // -----------------------------------------------------------------------------
       
   276 //
       
   277 HBufC* CRtpToFile::ClipPath()
       
   278     {
       
   279     return iCurrentPath;
       
   280     }
       
   281 
       
   282 // -----------------------------------------------------------------------------
       
   283 // CRtpFromFile::GetCurrentLength
       
   284 // Gets the current length of the clip during recording.
       
   285 // -----------------------------------------------------------------------------
       
   286 //
       
   287 TUint CRtpToFile::GetCurrentLength()
       
   288     {
       
   289     return iGroupTime;
       
   290     }
       
   291     
       
   292 // -----------------------------------------------------------------------------
       
   293 // CRtpFromFile::UpdateRecordEndTime
       
   294 // Uppdates the current recording end time.
       
   295 // -----------------------------------------------------------------------------
       
   296 //
       
   297 void CRtpToFile::UpdateRecordEndTime( const TTime& aEndTime )
       
   298     {
       
   299     if ( aEndTime > iCurrentTime )
       
   300         {
       
   301         iRecordEndTime = aEndTime.Int64();
       
   302         }
       
   303     }
       
   304     
       
   305 // -----------------------------------------------------------------------------
       
   306 // CRtpToFile::UpdatePlayAttL
       
   307 // Updates clip's playback count and spot attributes after watching.
       
   308 // -----------------------------------------------------------------------------
       
   309 //
       
   310 void CRtpToFile::UpdatePlayAttL( const TInt aNewSpot )
       
   311     {
       
   312     CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC(
       
   313                                  iFile, CRtpMetaHeader::EMetaUpdate );
       
   314     CRtpMetaHeader::SAttributes att;
       
   315     metaheader->ReadAttributesL( att );
       
   316     
       
   317     // Step playback counter by one
       
   318     att.iPlayCount++;
       
   319     // Update playback spot
       
   320     att.iPlaySpot = ( aNewSpot > 0 && aNewSpot < iLastSeekAddr )? aNewSpot:
       
   321                                                                   KErrNone;
       
   322     metaheader->WriteAttributesL( att );
       
   323     CleanupStack::PopAndDestroy( metaheader );
       
   324     LOG2( "CRtpToFile::UpdatePlayAttL(), New playback count: %d, spot: %d", 
       
   325                                          att.iPlayCount, att.iPlaySpot );
       
   326     }
       
   327     
       
   328 // -----------------------------------------------------------------------------
       
   329 // CRtpToFile::RunL
       
   330 // -----------------------------------------------------------------------------
       
   331 //
       
   332 void CRtpToFile::RunL()
       
   333     {
       
   334     User::LeaveIfError( iStatus.Int() );
       
   335     User::LeaveIfError( iFile.Flush() );
       
   336     
       
   337     // Start packets re-use?
       
   338     if ( iGroupReUse == KErrInUse )
       
   339         {
       
   340         const TInt point( iFileObs.CurrentFileReadPoint( 0 ) );
       
   341         if ( point > ( iSeekHeaderPoint + KSeekHeaderBytes ) )
       
   342             {
       
   343             iGroupReUse = KErrNone;
       
   344             }
       
   345         }
       
   346 
       
   347     // Stop recording if time shift too close to live
       
   348     if ( iGroupReUse > KErrNone && 
       
   349          iFileObs.CurrentFileReadPoint( 1 ) < KErrNone )
       
   350         {
       
   351         iAction = MRtpFileWriteObserver::ESaveEnd;
       
   352         LOG( "CRtpToFile::RunL(), Time shift play too close to record !" );
       
   353         }
       
   354     
       
   355     // Stop recording if end time reached
       
   356     if ( iCurrentTime.Int64() > iRecordEndTime )
       
   357         {
       
   358         iAction = MRtpFileWriteObserver::ESaveEnd;
       
   359         LOG( "CRtpToFile::RunL(), Record end time reached !" );
       
   360         }
       
   361     
       
   362     iFileObs.RtpGroupSaved( iAction );
       
   363     }
       
   364     
       
   365 // -----------------------------------------------------------------------------
       
   366 // CRtpToFile::RunError
       
   367 // -----------------------------------------------------------------------------
       
   368 //
       
   369 TInt CRtpToFile::RunError( TInt aError )
       
   370     {
       
   371     LOG1( "CRtpToFile::RunError(), RunL Leaved: %d", aError );
       
   372 
       
   373     if ( &iWriteObs )
       
   374         {
       
   375         iWriteObs.WriteStatus( aError );
       
   376         }
       
   377     
       
   378     StopRtpSave( aError );
       
   379     return KErrNone;
       
   380     }
       
   381 
       
   382 // -----------------------------------------------------------------------------
       
   383 // CRtpToFile::DoCancel
       
   384 // -----------------------------------------------------------------------------
       
   385 //
       
   386 void CRtpToFile::DoCancel()
       
   387     {
       
   388     LOG( "CRtpToFile::DoCancel()" );
       
   389     }
       
   390 
       
   391 // -----------------------------------------------------------------------------
       
   392 // CRtpToFile::CreateNewClipL
       
   393 // Opens new clip and creates initial headers.
       
   394 // -----------------------------------------------------------------------------
       
   395 //
       
   396 void CRtpToFile::CreateNewClipL(
       
   397     const MRtpFileWriteObserver::SRtpRecParams& aParams )
       
   398     {
       
   399     // Open file
       
   400     iFile.Close();
       
   401     User::LeaveIfError( iFile.Replace( iFs, aParams.iClipPath,
       
   402                         EFileShareAny | EFileStream | EFileWrite ) );
       
   403     // Headers
       
   404     WriteInitialMetaHeaderL( aParams );
       
   405     WriteSeekHeaderL();
       
   406     const TInt firstGroup( iSeekHeaderPoint + KSeekHeaderBytes );
       
   407     
       
   408     // Variables
       
   409     iGroupTime = 0;
       
   410     iGroupsTotalCount = 0;
       
   411     iFirstSeekAddr = firstGroup;
       
   412     iLastSeekAddr = firstGroup;
       
   413     iNextGroupPoint = firstGroup;
       
   414     delete iCurrentPath; iCurrentPath = NULL;
       
   415     iCurrentPath = aParams.iClipPath.AllocL();
       
   416     }
       
   417     
       
   418 // -----------------------------------------------------------------------------
       
   419 // CRtpToFile::AddGroupL
       
   420 // Updates file and packet group header variables for a new group.
       
   421 // -----------------------------------------------------------------------------
       
   422 //
       
   423 void CRtpToFile::AddGroupL()
       
   424     {
       
   425     // New group
       
   426     iThisGroup = iNextGroupPoint;
       
   427     
       
   428     // Group header
       
   429     // Note ! KGroupHeaderBytes size is allocated to incoming group in 
       
   430     //        CCRRtpRecordSink::ResetGroupVariables(), but data does not exits
       
   431     //        before CRtpToFile::AddGroupHeaderL() method is called.
       
   432     iGroupTotalLen = KGroupHeaderBytes + iDataPtr.Length();
       
   433     iNextGroupPoint = iThisGroup + iGroupTotalLen;
       
   434     const TInt prevGroup( iLastSeekAddr );
       
   435 
       
   436     // Time shift handling
       
   437     if ( iGroupReUse > KErrNone )
       
   438         {
       
   439         iGroupReUse--;
       
   440         }
       
   441     else
       
   442         {
       
   443         iGroupsTotalCount++;
       
   444         iLastSeekAddr = ( iMode != EModeTimeShift )? iThisGroup: 0;
       
   445         }
       
   446     
       
   447     // Start write to the beginning of the clip?
       
   448     if ( iGroupReUse == KErrNone )
       
   449         {
       
   450         iGroupReUse = iGroupsTotalCount;
       
   451         iNextGroupPoint = iSeekHeaderPoint + KSeekHeaderBytes;
       
   452         LOG2( "CRtpToFile::AddGroupL(), iGroupReUse: %d, iNextGroupPoint: %d",
       
   453                                         iGroupReUse, iNextGroupPoint );
       
   454         }
       
   455 
       
   456     // First group in clip?
       
   457     if ( iGroupsTotalCount == 1 )
       
   458         {
       
   459         iPrevGroupPoint = 0;
       
   460         WriteSeekHeaderL();
       
   461         iSeekArrayReference = iGroupTime;
       
   462         }
       
   463     else
       
   464         {
       
   465         iPrevGroupPoint = prevGroup;
       
   466         }
       
   467     }
       
   468     
       
   469 // -----------------------------------------------------------------------------
       
   470 // CRtpToFile::GroupTimeL
       
   471 // Generates group time from group length reported by ring buffer and actual
       
   472 // network time difference to previous group. Reference time is used to avoid
       
   473 // running time error caused by network burst.
       
   474 // -----------------------------------------------------------------------------
       
   475 //
       
   476 void CRtpToFile::GroupTimeL( TUint& aGroupLength )
       
   477     {
       
   478     UpdateCurrentTimeL();
       
   479     TUint syncLength( 0 );
       
   480     
       
   481     // previous time initiated?
       
   482     if ( iPreviousTime > 0 )
       
   483         {
       
   484         const TInt64 delta( iCurrentTime.Int64() - iPreviousTime );
       
   485         iReferenceTime+= delta;
       
   486         const TInt timeDelta( delta / KSiKilo );
       
   487         const TInt burstDelta( Abs( timeDelta - iPreviousDelta ) );
       
   488 #ifdef CR_ALL_LOGS    
       
   489         LOG3( "CRtpToFile::GroupTimeL(), aGroupLength: %u, burstDelta: %d, timeDelta: %d",
       
   490                                          aGroupLength, burstDelta, timeDelta );
       
   491 #endif // CR_ALL_LOGS    
       
   492         
       
   493         // Use reference time?
       
   494         if ( timeDelta > KNormalRecGroupLength && 
       
   495              Abs( burstDelta - aGroupLength ) < KMaxValidDelta )
       
   496             {
       
   497             iPreviousDelta = 0;
       
   498             syncLength = iReferenceTime / KSiKilo;
       
   499             }
       
   500         else
       
   501             {
       
   502             iPreviousDelta = timeDelta;
       
   503             syncLength = aGroupLength;
       
   504             }
       
   505         }
       
   506     else
       
   507         {
       
   508         // In record start and after pause uses only the reported group length
       
   509         iPreviousDelta = 0;
       
   510         syncLength = aGroupLength;
       
   511         iReferenceTime+= aGroupLength * KSiKilo;
       
   512         }
       
   513 
       
   514     // Update group time
       
   515     iGroupTime += syncLength;
       
   516     iPreviousTime = iCurrentTime.Int64();
       
   517     
       
   518     // Time shift ongoing?
       
   519     if ( iMode == EModeTimeShift )
       
   520         {
       
   521         aGroupLength = syncLength;
       
   522         }
       
   523     else
       
   524         {
       
   525         // Update seek array
       
   526         aGroupLength = 0;
       
   527         if ( ( iGroupTime - iSeekArrayReference ) >= KSeekArrayInterval )
       
   528             {
       
   529             AppendSeekArrayL( iGroupTime, iThisGroup );
       
   530             iSeekArrayReference = iGroupTime;
       
   531             }
       
   532         }
       
   533     }
       
   534     
       
   535 // -----------------------------------------------------------------------------
       
   536 // CRtpToFile::WriteInitialMetaHeaderL
       
   537 // Writes initial meta data header of clip.
       
   538 // -----------------------------------------------------------------------------
       
   539 //
       
   540 void CRtpToFile::WriteInitialMetaHeaderL(
       
   541     const MRtpFileWriteObserver::SRtpRecParams& aParams )
       
   542     {
       
   543     LOG( "CRtpToFile::WriteInitialMetaHeaderL() in" );
       
   544 
       
   545     CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC(
       
   546                                  iFile, CRtpMetaHeader::EMetaWrite );
       
   547     // Attributes
       
   548     CRtpMetaHeader::SAttributes att;
       
   549     att.iOngoing = ETrue;
       
   550     att.iCompleted = EFalse;
       
   551     att.iProtected = EFalse;
       
   552     att.iFailed = EFalse;
       
   553     att.iVersion = KCurrentClipVersion;
       
   554     att.iQuality = KDummyFullQuality;
       
   555     att.iPostRule = aParams.iPostRule;
       
   556     att.iParental = aParams.iParental;
       
   557     att.iPlayCount = 0;
       
   558     att.iPlaySpot = KErrNone;
       
   559     metaheader->WriteAttributesL( att );
       
   560     LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), iPostRule: %d", att.iPostRule );
       
   561     LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), iParental: %d", att.iParental );
       
   562     
       
   563     // Start date/time
       
   564     metaheader->WriteStartTimeL( aParams.iStartTime );
       
   565     TName buf( KNullDesC );
       
   566 #if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
       
   567     aParams.iStartTime.FormatL( buf, KTimeDateFormat );
       
   568     LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), iStartTime: %S", &buf );
       
   569 #endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
       
   570 
       
   571     // End time
       
   572     metaheader->WriteEndTimeL( aParams.iEndTime );
       
   573 
       
   574     // Duration
       
   575     metaheader->WriteDurationL( 0 );
       
   576     
       
   577     // Seek array point
       
   578     metaheader->WriteSeekArrayPointL( 0 );
       
   579     
       
   580     // Mime info
       
   581     CRtpUtil::GetMimeInfo( buf );
       
   582     metaheader->WriteUserIdL( buf );
       
   583     LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), Mime: %S", &buf );
       
   584 
       
   585     // Device info
       
   586     CRtpUtil::GetImeiL( buf );
       
   587     metaheader->WriteDeviceInfoL( buf );
       
   588     LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), IMEI: %S", &buf );
       
   589 
       
   590     // ESG info
       
   591     metaheader->WriteEsgDataL( aParams.iService, aParams.iProgram );
       
   592     LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), Service: %S", 
       
   593                                                  &aParams.iService );
       
   594     LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), Program: %S", 
       
   595                                                  &aParams.iProgram );
       
   596     // SRTP data ( Reserved for future use )
       
   597     TBuf8<3> srtp;
       
   598     srtp.Num( KErrNotFound ); 
       
   599     metaheader->WriteSrtpDataL( srtp );
       
   600     
       
   601     // SDP file
       
   602     metaheader->WriteSdpDataL( aParams.iSdpData );
       
   603     LOG1( "CRtpToFile::WriteInitialMetaHeaderL(), SDP length: %d", 
       
   604                                                   aParams.iSdpData.Length() );
       
   605     metaheader->CommitL();
       
   606     iSeekHeaderPoint = metaheader->SeekHeaderPoint();
       
   607     CleanupStack::PopAndDestroy( metaheader );
       
   608 
       
   609     LOG( "CRtpToFile::WriteInitialMetaHeaderL() out" );
       
   610     }
       
   611     
       
   612 // -----------------------------------------------------------------------------
       
   613 // CRtpToFile::WriteFinalMetaHeaderL
       
   614 // Writes final meta data header of clip.
       
   615 // -----------------------------------------------------------------------------
       
   616 //
       
   617 void CRtpToFile::WriteFinalMetaHeaderL( const TInt aStatus )
       
   618     {
       
   619     LOG( "CRtpToFile::WriteFinalMetaHeaderL() in" );
       
   620     CRtpMetaHeader* metaheader = CRtpMetaHeader::NewLC(
       
   621                                  iFile, CRtpMetaHeader::EMetaUpdate );
       
   622     // Update duration
       
   623     UpdateDurationL( metaheader );
       
   624 
       
   625     // Attributes
       
   626     CRtpMetaHeader::SAttributes att;
       
   627     metaheader->ReadAttributesL( att );
       
   628     att.iOngoing = EFalse;
       
   629     att.iCompleted = !aStatus;
       
   630     att.iFailed = !iGroupsTotalCount;
       
   631     metaheader->WriteAttributesL( att );
       
   632     LOG1( "CRtpToFile::WriteFinalMetaHeaderL(), Completed: %d", att.iCompleted );
       
   633     LOG1( "CRtpToFile::WriteFinalMetaHeaderL(), iFailed  : %d", att.iFailed );
       
   634 
       
   635     // End date/time
       
   636     metaheader->ReadStartTimeL( iCurrentTime );
       
   637     iRecordEndTime = iCurrentTime.Int64() + iGroupTime;
       
   638     metaheader->WriteEndTimeL( iRecordEndTime );
       
   639 #if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
       
   640     TName buf( KNullDesC ); TTime( iRecordEndTime ).FormatL( buf, KTimeDateFormat );
       
   641     LOG1( "CRtpToFile::WriteFinalMetaHeaderL(), endTime: %S", &buf );
       
   642 #endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
       
   643 
       
   644     // Seek array point
       
   645     metaheader->WriteSeekArrayPointL( iNextGroupPoint );
       
   646     LOG1( "CRtpToFile::WriteFinalMetaHeaderL(), Seek array: %d", iNextGroupPoint );
       
   647     CleanupStack::PopAndDestroy( metaheader );
       
   648 
       
   649     // Final seek header
       
   650     SaveSeekArrayL();
       
   651     WriteSeekHeaderL();
       
   652     
       
   653     // Set orginal start time as file date
       
   654     iFile.SetModified( iCurrentTime );
       
   655 
       
   656     LOG( "CRtpToFile::WriteFinalMetaHeaderL() out" );
       
   657     }
       
   658  
       
   659 // -----------------------------------------------------------------------------
       
   660 // CRtpToFile::AddGroupHeaderL
       
   661 // Adds header of one RTP group.
       
   662 // Room for group header bytes and packets count comes from CCRRtpRecordSink.
       
   663 // -----------------------------------------------------------------------------
       
   664 //
       
   665 void CRtpToFile::AddGroupHeaderL()
       
   666     {
       
   667     // Packets count (PTC) is added in CCRRtpRecordSink::SaveGroup()
       
   668 
       
   669     // Group time
       
   670     HBufC8* bytes = CRtpUtil::MakeBytesLC( iGroupTime );
       
   671     iDataPtr.Insert( 0, bytes->Des() );
       
   672     CleanupStack::PopAndDestroy( bytes );
       
   673 
       
   674     // Previous group point
       
   675     bytes = CRtpUtil::MakeBytesLC( iPrevGroupPoint );
       
   676     iDataPtr.Insert( 0, bytes->Des() );
       
   677     CleanupStack::PopAndDestroy( bytes );
       
   678 
       
   679     // Next Group point
       
   680     bytes = CRtpUtil::MakeBytesLC( iNextGroupPoint );
       
   681     iDataPtr.Insert( 0, bytes->Des() );
       
   682     CleanupStack::PopAndDestroy( bytes );
       
   683 
       
   684     // Group total size
       
   685     bytes = CRtpUtil::MakeBytesLC( iGroupTotalLen );
       
   686     iDataPtr.Insert( 0, bytes->Des() );
       
   687     CleanupStack::PopAndDestroy( bytes );
       
   688     }
       
   689  
       
   690 // -----------------------------------------------------------------------------
       
   691 // CRtpToFile::UpdateDurationL
       
   692 // Updates clip's duration.
       
   693 // -----------------------------------------------------------------------------
       
   694 //
       
   695 void CRtpToFile::UpdateDurationL( CRtpMetaHeader* aMetaHeader )
       
   696     {
       
   697     aMetaHeader->WriteDurationL( TInt( iGroupTime ) );
       
   698     LOG1( "CRtpToFile::UpdateDurationL(), new duration: %u", iGroupTime );
       
   699     }
       
   700     
       
   701 // -----------------------------------------------------------------------------
       
   702 // CRtpToFile::UpdateCurrentTimeL
       
   703 // Gets current time as network time.
       
   704 // -----------------------------------------------------------------------------
       
   705 //
       
   706 void CRtpToFile::UpdateCurrentTimeL()
       
   707     {
       
   708     iCurrentTime.UniversalTime();
       
   709     }
       
   710 
       
   711 // End of File
       
   712