dvrengine/CommonRecordingEngine/src/CCRRtpFileSource.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 16:02:30 +0300
changeset 16 ae43a6765dd5
parent 0 822a42b6c3f1
permissions -rw-r--r--
Revision: 201009 Kit: 201015

/*
* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:    Class that reads RTP packets from propriatary file format.*
*/




// INCLUDE FILES
#include "CCRRtpFileSource.h"
#include <ipvideo/CRtpClipHandler.h>
#include "CCRPacketBuffer.h"
#include "videoserviceutilsLogger.h"

// CONSTANTS
const TInt KGroupsCountPoint( 0 );
const TInt KBufferThesholdCount( 20 );

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CCRRtpFileSource::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CCRRtpFileSource* CCRRtpFileSource::NewL(
    const SCRRtpPlayParams& aParams,
    CRtpClipHandler*& aClipHandler,
    MCRStreamObserver& aSessionObs,
    CCRStreamingSession& aOwningSession )
    {
    CCRRtpFileSource* self = new( ELeave )
        CCRRtpFileSource( aClipHandler, aSessionObs, aOwningSession );
    CleanupStack::PushL( self );
    self->ConstructL( aParams );
    CleanupStack::Pop();
    return self;
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CCRRtpFileSource* CCRRtpFileSource::NewL(
    const RFile& aRtpHandle,
    CRtpClipHandler*& aClipHandler,
    MCRStreamObserver& aSessionObs,
    CCRStreamingSession& aOwningSession )
    {
    CCRRtpFileSource* self = new( ELeave )
        CCRRtpFileSource( aClipHandler, aSessionObs, aOwningSession );
    CleanupStack::PushL( self );
    self->ConstructL( aRtpHandle );
    CleanupStack::Pop();
    return self;
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::CCRRtpFileSource
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
CCRRtpFileSource::CCRRtpFileSource(
    CRtpClipHandler*& aClipHandler,
    MCRStreamObserver& aSessionObs,
    CCRStreamingSession& aOwningSession )
  : CCRPacketSourceBase( aOwningSession, CCRStreamingSession::ECRRtpSourceId ),
    iClipHandler( aClipHandler ),
    iSessionObs( aSessionObs ),
    iInitialTime( KMaxTUint ),
    iClipPauseSent( 0 )
    {
    // None
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CCRRtpFileSource::ConstructL( const SCRRtpPlayParams& aParams )
    {
    const TBool timeShift( 
        aParams.iFileName.Find( KDvrTimeShiftFile ) > KErrNotFound );
    LOG1( "CCRRtpFileSource::ConstructL() in, timeShift: %d", timeShift );

    // RTP clip handler
    User::LeaveIfNull( iClipHandler );
    iClipHandler->RegisterReadObserver( this );
    iClipHandler->StartPlayBackL( aParams, timeShift );
    
    LOG( "CCRRtpFileSource::ConstructL() out" );
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CCRRtpFileSource::ConstructL( const RFile& aRtpHandle )
    {
    LOG( "CCRRtpFileSource::ConstructL() in" );

    User::LeaveIfNull( iClipHandler );
    iClipHandler->RegisterReadObserver( this );
    iClipHandler->StartPlayBackL( aRtpHandle );
    
    LOG( "CCRRtpFileSource::ConstructL() out" );
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::~CCRRtpFileSource
// Destructor.
// -----------------------------------------------------------------------------
//
CCRRtpFileSource::~CCRRtpFileSource()
    {
    LOG( "CCRRtpFileSource::~CCRRtpFileSource()" );

    if ( iClipHandler )
        {
        iClipHandler->StopPlayBack( KErrNone, 0 );
        }

    delete iSdp;
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::GetSdp
// -----------------------------------------------------------------------------
//
TInt CCRRtpFileSource::GetSdp( TPtrC8& aSdp )
    {
    if ( iSdp )
        {
        aSdp.Set( iSdp->Des() );
        return KErrNone;
        }

    return KErrNotReady;
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::SetBuffer
// -----------------------------------------------------------------------------
//
void CCRRtpFileSource::SetBuffer( CCRPacketBuffer* aBuffer )
    {
    iBuffer = aBuffer;
    iBuffer->ContinousStream( EFalse );
    iBuffer->MoreComing( EFalse );
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::PostActionL
// -----------------------------------------------------------------------------
//
void CCRRtpFileSource::PostActionL()
    {
    LOG( "CCRRtpFileSource::PostActionL(), SDP will be handled !" );

    // SDP
    if ( iClipHandler )
        {
        iSdp = iClipHandler->GetClipSdpL();
        }

    // Notify that SDP available
    iSessionObs.StatusChanged( MCRPacketSource::ERtpStateSdpAvailable );
    delete iSdp; iSdp = NULL;
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::Restore
// -----------------------------------------------------------------------------
//
void CCRRtpFileSource::Restore()
    {
    const TInt err( NextClipGroup( ETrue ) );
    if ( err && err != KErrEof )
        {
        LOG1( "CCRRtpFileSource::Restore(), NextClipGroup() err: %d", err );
        iSessionObs.StatusChanged( MCRPacketSource::ERtpStateClosing );
        }
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::Play
//
// -----------------------------------------------------------------------------
//      
TInt CCRRtpFileSource::Play( const TReal& aStartPos, const TReal& aEndPos )
    {
    LOG3( "CCRRtpFileSource::Play(), aStartPos: %f, aEndPos: %f, iClipPauseSent: %d", 
                                     aStartPos, aEndPos, iClipPauseSent );
    // Play for player?
    if ( aStartPos == KRealZero && aEndPos == KRealZero )
        {
        iInitialTime = KMaxTUint;
        return NextClipGroup( EFalse );
        }
    
    // Loading started in player?
    if ( aStartPos == KRealMinusOne && aEndPos == KRealMinusOne )
        {
        const TBool pauseSent( iClipPauseSent > 0 );
        if ( pauseSent )
            {
            iClipPauseSent--;
            iBuffer->ResetBuffer();
            }

        // Read more from clip
        TInt err( NextClipGroup( EFalse ) );
        if ( !err && pauseSent )
            {
            iInitialTime = KMaxTUint;
            err = ECRStreamPauseHanling;
            LOG( "CCRRtpFileSource::Play(), ECRStreamPauseHanling" );
            }
        else
            {
            if ( err == KErrEof )
                {
                err = KErrNone;
                if ( iClipHandler )
                    {
                    TRAP( err, iClipHandler->SetSeekPointL( 0 ) );
                    }
                if ( !err )
                    {
                    err = ECRStreamEndHandling;
                    LOG( "CCRRtpFileSource::Play(), ECRStreamEndHandling" );
                    }
                }
            }
        
        return err;
        }
    
    return KErrCompletion;
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::Stop
// -----------------------------------------------------------------------------
//
TInt CCRRtpFileSource::Stop()
    {
    LOG( "CCRRtpFileSource::Stop()" );

    return RtpPosition( 0 );
    }
    
// -----------------------------------------------------------------------------
// CCRRtpFileSource::SetPosition
//
// -----------------------------------------------------------------------------
//      
TInt CCRRtpFileSource::SetPosition( const TInt64 aPosition )
    {
    TInt err( RtpPosition( TUint( aPosition / KSiKilo ) ) );
    if ( !err )
        {
        err = NextClipGroup( EFalse );
        }
    
    return err;
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::GetPosition
//
// -----------------------------------------------------------------------------
//      
TInt CCRRtpFileSource::GetPosition( TInt64& aPosition, TInt64& aDuration )
    {
    if ( iBuffer && iClipHandler )
        {
        if ( iInitialTime != KMaxTUint )
            {
            aPosition += TInt64( iInitialTime ) * KSiKilo;
            }
        else
            {
            LOG( "CCRRtpFileSource::GetPosition(), iInitialTime not valid !" );
            }
        
        aDuration = TInt64( iClipHandler->GetCurrentLength() ) * KSiKilo;
#ifdef CR_ALL_LOGS
        LOG2( "CCRRtpFileSource::GetPosition(), aPosition: %u, aDuration: %u", 
            ( TUint )( aPosition / KSiKilo ), ( TUint )( aDuration / KSiKilo ) );
#endif // CR_ALL_LOGS
        return KErrNone;
        }

    return KErrCompletion;
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::GroupReadedL
// Adds packets to the buffer when finished asyncronous group reading.
// -----------------------------------------------------------------------------
//
void CCRRtpFileSource::GroupReadedL(
    const TDesC8& aGroup,
    const TUint aGroupTime,
    const TBool aLastGroup )
    {
    // Group time
    if ( iInitialTime == KMaxTUint )
        {
        iInitialTime = aGroupTime;
        }
    
    // Data valid?
    TInt point( KGroupsCountPoint + KPacketsCountBytes );
    const TInt total( aGroup.Length() );
    if ( point > total ) 
        {
        LOG( "CCRRtpFileSource::GroupReadedL(), No Packets Total Count !" );
        User::Leave( KErrCorrupt );
        }

    // Packets total count (PTC)
    const TInt totalCount( CRtpUtil::GetValueL(
                           aGroup.Mid( KGroupsCountPoint, KPacketsCountBytes ) ) );
    if ( totalCount > 0 )
        {
        iBuffer->MoreComing( ETrue );
        }
    
    // Loop all packets
    for ( TInt i( 0 ); i < totalCount; i++ )
        {
        // Corrupted?
        if ( ( point + KPacketSizeBytesLen ) > total )
            {
            LOG( "CCRRtpFileSource::GroupReadedL(), No Packets Size !" );
            User::Leave( KErrCorrupt );
            }

        // Packet total Size (PTS)
        TInt packetSize( CRtpUtil::GetValueL( 
                         aGroup.Mid( point, KPacketSizeBytesLen ) ) );
        // Corrupted?
        if ( packetSize <= 0 || ( point + packetSize ) > total )
            {
            LOG( "CCRRtpFileSource::GroupReadedL(), No Packets Payload !" );
            User::Leave( KErrCorrupt );
            }
        
        // Packet type
        point += KPacketSizeBytesLen;
        const MRtpFileWriteObserver::TRtpType type( 
            ( MRtpFileWriteObserver::TRtpType )( aGroup[point] ) );
        point += KPacketTypeBytesLen;
        packetSize -= ( KPacketSizeBytesLen + KPacketTypeBytesLen );

        // Insert packet to the buffer
        const TPtrC8 packet( aGroup.Mid( point, packetSize ) );

#ifdef CR_ALL_LOGS
        const TUint8* pointer( &packet[2] );
        TInt seq( BigEndian::Get16( pointer ) );
        LOG3( "CCRRtpFileSource::GroupReadedL(), type: %d, packet: %d, seq: %d", 
                                                 type, packet.Length(), seq );
        //RFileLogger::WriteFormat( _L( "livetv" ), _L( "play.log" ), EFileLoggingModeAppend, 
        //    _L( "GroupReadedL(), type: %d, packet: %d, seq: %d" ), type, packet.Length(), seq );
#endif // CR_ALL_LOGS

        MCRPacketSource::TCRPacketStreamId stream( MCRPacketSource::EStreamIdCount );
        if ( TypeToStream( type, stream ) )
            {
            // Last packet in group?
            if ( i >= ( totalCount - 1 ) )
                {
                iBuffer->MoreComing( EFalse );
                if ( aLastGroup && stream != MCRPacketSource::EStreamEndTag )
                    {
                    LOG( "CCRRtpFileSource::GroupReadedL(), Misses last group from clip !" );
                    stream = MCRPacketSource::EStreamEndTag;
                    }
                }
            
            // Packet to buffer
            iBuffer->AddPacket( stream, packet );
            }
        
        point+= packetSize;
        }
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::ReadStatus
// -----------------------------------------------------------------------------
//
void CCRRtpFileSource::ReadStatus( TInt aStatus  )
    {
    LOG1( "CCRRtpFileSource::ReadStatus(), aStatus: %d", aStatus );

    switch ( aStatus )
        {
        case MRtpFileReadObserver::ERtpTimeShifTEnd:
            break;
        
        default:
            iSessionObs.StatusChanged( MCRPacketSource::ERtpStateClosing );
            break;
        }
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::NextClipGroup
// -----------------------------------------------------------------------------
//
TInt CCRRtpFileSource::NextClipGroup( const TBool aForce )
    {
    if ( iBuffer && iClipHandler )
        {
        if ( aForce || iBuffer->PacketsMinCount() < KBufferThesholdCount )
            {
            TRAPD( err, iClipHandler->NextClipGroupL() );
            return err;
            }
        
        return KErrNone;
        }
    
    return KErrNotReady;
    }

// -----------------------------------------------------------------------------
// CCRRtpFileSource::RtpPosition
// -----------------------------------------------------------------------------
//
TInt CCRRtpFileSource::RtpPosition( const TUint aPosition )
    {
    LOG1( "CCRRtpFileSource::RtpPosition(), aPosition: %d", aPosition ); 

    TInt err( KErrCompletion );
    if ( iBuffer && iClipHandler )
        {
        TRAP( err, iClipHandler->SetSeekPointL( aPosition ) );
        if ( !err )
            {
            iInitialTime = KMaxTUint;
            iBuffer->ResetBuffer();
            }
        }
    
    return err;
    }
    
// -----------------------------------------------------------------------------
// CCRRtpFileSource::TypeToStream
// -----------------------------------------------------------------------------
//
TBool CCRRtpFileSource::TypeToStream(
    const MRtpFileWriteObserver::TRtpType& aType,
    MCRPacketSource::TCRPacketStreamId& aStream )
    {
    switch ( aType )
        {
        case MRtpFileWriteObserver::ERtpAudio:
            aStream = MCRPacketSource::EAudioStream;
            break;

        case MRtpFileWriteObserver::ERtcpAudio:
            aStream = MCRPacketSource::EAudioControlStream;
            break;

        case MRtpFileWriteObserver::ERtpVideo:
            aStream = MCRPacketSource::EVideoStream;
            break;

        case MRtpFileWriteObserver::ERtcpVideo:
            aStream = MCRPacketSource::EVideoControlStream;
            break;

        case MRtpFileWriteObserver::ERtpSubTitle:
            aStream = MCRPacketSource::ESubTitleStream;
            break;

        case MRtpFileWriteObserver::ERtcpSubTitle:
            aStream = MCRPacketSource::ESubTitleControlStream;
            break;

        case MRtpFileWriteObserver::ERtpClipPause:
            LOG( "CCRRtpFileSource::TypeToStream(), ERtpClipPause" );
            iClipPauseSent = ETrue;
            aStream = MCRPacketSource::EDisContinousStream;
            break;
        
        case MRtpFileWriteObserver::ERtpClipEnd:
            LOG( "CCRRtpFileSource::TypeToStream(), ERtpClipEnd" );
            aStream = MCRPacketSource::EStreamEndTag;
            break;

        default:
            LOG1( "CCRRtpFileSource::TypeToStream(), Default case, aType: %d",
                                                                   aType );
            return EFalse;
        }
    
    return ETrue;
    }
    
//  End of File