dvrengine/CommonRecordingEngine/src/CCRXpsSink.cpp
changeset 35 381bc1d93c7b
parent 31 07dea94512a2
equal deleted inserted replaced
31:07dea94512a2 35:381bc1d93c7b
     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:    Class that takes packet from the buffer and forward them thrue*
       
    15 */
       
    16 
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDES
       
    21 #include "CCRXpsSink.h"
       
    22 #include "CCRPacketBuffer.h"
       
    23 #include "CCRStreamingSession.h"
       
    24 #include <ipvideo/CDvrSdpParser.h>
       
    25 #include "CCRTimer.h"
       
    26 #include "CRtpPacket.h"
       
    27 #include "CRtpTsConverter.h"
       
    28 #include <CXPSPacketSink.h>
       
    29 
       
    30 // CONSTANTS
       
    31 _LIT( KCRXpsServerName, "IpVideoXps" );
       
    32 _LIT8( KAttributeDefRange, "a=range:npt=0-86400.0" );
       
    33 #ifdef VIA_FEA_IPTV_USE_IPDC
       
    34 _LIT8( KMtvAvc, "X-MTV-AVC" );
       
    35 _LIT8( KHxAvc1, "X-HX-AVC1" );
       
    36 #endif // VIA_FEA_IPTV_USE_IPDC
       
    37 const TInt KRangeIdentifierLen( 8 );
       
    38 const TInt KXpsBufferedPackets( 300 );      // about 3s
       
    39 const TInt KXpsOverflowDelay( 300 * 1000 ); // 300ms
       
    40 
       
    41 // ============================ MEMBER FUNCTIONS ===============================
       
    42 
       
    43 // -----------------------------------------------------------------------------
       
    44 // CCRXpsSink::NewL
       
    45 // Two-phased constructor.
       
    46 // -----------------------------------------------------------------------------
       
    47 //  
       
    48 CCRXpsSink* CCRXpsSink::NewL(
       
    49     CCRStreamingSession::TCRSinkId aSinkId,
       
    50     CCRStreamingSession& aOwningSession )
       
    51     {
       
    52     CCRXpsSink* self = new( ELeave ) 
       
    53     CCRXpsSink( aSinkId, aOwningSession );
       
    54     CleanupStack::PushL( self );
       
    55     self->ConstructL();
       
    56     CleanupStack::Pop( self );
       
    57     return self;
       
    58     }
       
    59 
       
    60 // -----------------------------------------------------------------------------
       
    61 // CCRXpsSink::CCRXpsSink
       
    62 // C++ default constructor can NOT contain any code, that might leave.
       
    63 // -----------------------------------------------------------------------------
       
    64 //  
       
    65 CCRXpsSink::CCRXpsSink(
       
    66     CCRStreamingSession::TCRSinkId aSinkId,
       
    67     CCRStreamingSession& aOwningSession )
       
    68   : CCRPacketSinkBase( aOwningSession, aSinkId ),
       
    69     iWaitPlayer( KErrNotFound ),
       
    70     iRequested( KErrNotFound ),
       
    71     iXpsResetOk( EFalse ),
       
    72     iAudioStreamId( KErrNotFound ),
       
    73     iVideoStreamId( KErrNotFound ),
       
    74     iTitleStreamId( KErrNotFound )
       
    75     {
       
    76     // None
       
    77     }
       
    78 
       
    79 // -----------------------------------------------------------------------------
       
    80 // CCRXpsSink::ConstructL
       
    81 // 2nd phase. 
       
    82 // -----------------------------------------------------------------------------
       
    83 //  
       
    84 void CCRXpsSink::ConstructL()
       
    85     {
       
    86     LOG( "CCRXpsSink::ConstructL() in" );
       
    87 
       
    88     iRtpPacket = CRtpPacket::NewL();
       
    89     iPacketSink = CXPSPacketSink::New();
       
    90     LOG1( "CCRXpsSink::ConstructL(), iPacketSink: %d", iPacketSink );
       
    91     User::LeaveIfNull( iPacketSink );
       
    92     TInt err( iPacketSink->Init( KCRXpsServerName, this ) );
       
    93     if ( err )
       
    94         {
       
    95         LOG1( "CCRXpsSink::ConstructL(), iPacketSink->Init() err: %d", err );
       
    96         User::Leave( err );
       
    97         }
       
    98 
       
    99     LOG( "CCRXpsSink::ConstructL() out" );
       
   100     }
       
   101     
       
   102 // -----------------------------------------------------------------------------
       
   103 // CCRXpsSink::~CCRXpsSink
       
   104 // Destructor.
       
   105 // -----------------------------------------------------------------------------
       
   106 //
       
   107 CCRXpsSink::~CCRXpsSink()
       
   108     {    
       
   109     LOG( "CCRXpsSink::~CCRXpsSink()" );
       
   110 
       
   111     // Delete variables
       
   112     StopTimer();
       
   113     delete iPacketSink;
       
   114     delete iAudioConv;
       
   115     delete iVideoConv;
       
   116     delete iTitleConv;
       
   117     delete iRtpPacket;
       
   118 
       
   119 #ifdef VIA_FEA_IPTV_USE_IPDC
       
   120     delete iVideoDepacketizer;
       
   121 #endif // VIA_FEA_IPTV_USE_IPDC
       
   122     }
       
   123     
       
   124 // -----------------------------------------------------------------------------
       
   125 // CCRXpsSink::SetSdpL
       
   126 // Sets SDP, parses it and initiates XPS.
       
   127 // -----------------------------------------------------------------------------
       
   128 //  
       
   129 void CCRXpsSink::SetSdpL( const TDesC8& aSdp )
       
   130     {
       
   131     LOG1( "CCRXpsSink::SetSdpL(), SDP len: %d", aSdp.Length() );
       
   132 
       
   133 #if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
       
   134     LOG( "CCRXpsSink::SetSdpL(), SDP content:" );
       
   135     TName d( KNullDesC );
       
   136     for ( TInt i( 0 );  i < aSdp.Length(); i++ )
       
   137         {
       
   138         TChar c = aSdp[i];
       
   139         d.Append( c );
       
   140         if ( ( i > 0 ) && ( i % 80 ) == 0 )
       
   141             {
       
   142             LOG1( ">%S<", &d );
       
   143             d.Zero();
       
   144             }
       
   145         }
       
   146     
       
   147     LOG1( ">%S<", &d );
       
   148 #endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
       
   149     
       
   150     if ( iWaitPlayer != KErrNotFound )
       
   151         {
       
   152         LOG( "CCRXpsSink::SetSdpL(), SDP already set !" );
       
   153         return;
       
   154         }
       
   155          
       
   156     // SDP parser
       
   157     CDvrSdpParser* sdpParser = CDvrSdpParser::NewLC();
       
   158     sdpParser->TryParseL( aSdp );
       
   159     
       
   160     // TS converter
       
   161     delete iAudioConv; iAudioConv = NULL;
       
   162     iAudioConv = CRtpTsConverter::NewL( sdpParser->AudioTimerGranularity() );
       
   163     LOG1( "CCRXpsSink::SetSdpL(), AudioTimerGranularity: %d",
       
   164                                   sdpParser->AudioTimerGranularity() );
       
   165     
       
   166     delete iVideoConv; iVideoConv = NULL;
       
   167     iVideoConv = CRtpTsConverter::NewL( sdpParser->VideoTimerGranularity() );
       
   168     LOG1( "CCRXpsSink::SetSdpL(), VideoTimerGranularity: %d",
       
   169                                   sdpParser->VideoTimerGranularity() );
       
   170 
       
   171     delete iTitleConv; iTitleConv = NULL;
       
   172     
       
   173     // Streams count
       
   174     TInt streams( 0 );
       
   175     const CDvrSdpParser::TDvrPacketProvidings providings(
       
   176         sdpParser->SupportedContent() );
       
   177     if ( providings == CDvrSdpParser::EDvrAudioOnly ||
       
   178          providings == CDvrSdpParser::EDvrVideoOnly )
       
   179         {
       
   180         streams = 1;
       
   181         }
       
   182     if ( providings == CDvrSdpParser::EDvrBothAudioAndVideo )
       
   183         {
       
   184         streams = 2;
       
   185         }
       
   186 
       
   187     // Stream ids
       
   188     iAudioStreamId = sdpParser->AudioStreamId();
       
   189     iVideoStreamId = sdpParser->VideoStreamId();
       
   190     LOG2( "CCRXpsSink::SetSdpL(), iAudioStreamId: %d, iVideoStreamId: %d",
       
   191                                   iAudioStreamId, iVideoStreamId );
       
   192     // Verify/update range
       
   193     if ( aSdp.FindC( 
       
   194          KAttributeDefRange().Left( KRangeIdentifierLen ) ) == KErrNotFound )
       
   195     	{
       
   196     	LOG( "CCRXpsSink::SetSdpL(), setting default range" );
       
   197     	iRangeKnown = EFalse;
       
   198     	sdpParser->NewLineL( KErrNotFound, KAttributeDefRange );
       
   199 	    }
       
   200 	else
       
   201         {
       
   202         LOG( "CCRXpsSink::SetSdpL() sdp already did contain range, not changed" );
       
   203         iRangeKnown = ETrue;
       
   204         }
       
   205 
       
   206     // Get SDP data
       
   207     TPtrC8 sdp( NULL, 0 );
       
   208     User::LeaveIfError( sdpParser->GetSdp( sdp ) );
       
   209     HBufC8* tmpSdpData = NULL;
       
   210     
       
   211     // See if recorded from ISMA crypted content
       
   212 #ifdef VIA_FEA_IPTV_USE_IPDC
       
   213     TInt mimePos( sdp.Find( KMtvAvc ) );
       
   214     if ( mimePos != KErrNotFound || sdp.Find( KHxAvc1 ) != KErrNotFound )
       
   215         {
       
   216         LOG( "CCRXpsSink::SetSdpL(), Playback of ISMA clip.." );
       
   217         delete iVideoDepacketizer; iVideoDepacketizer = NULL;
       
   218         iVideoDepacketizer = CH264Mpeg4GenrToFileformat::New();
       
   219         User::LeaveIfNull( iVideoDepacketizer );
       
   220         HBufC8* fmtp = FindFmtpLC( sdp );
       
   221         TInt err( iVideoDepacketizer->Init( *fmtp ) );
       
   222         CleanupStack::PopAndDestroy( fmtp );
       
   223         if ( err )
       
   224             {
       
   225             delete iVideoDepacketizer; iVideoDepacketizer = NULL;
       
   226             LOG1( "CCRXpsSink::SetSdpL(), Depacketizer Init() failed: %d", err );
       
   227             }
       
   228         else
       
   229             {
       
   230             // Change MIME type from X-MTV-AVC to X-HX-AVC1 for playback
       
   231             // KMtvAvc mime prevents Helix crash in non DVB-H phones
       
   232             if ( mimePos != KErrNotFound )
       
   233                 {
       
   234                 tmpSdpData = HBufC8::NewLC( sdp.Length() -
       
   235                     KMtvAvc().Length() + KHxAvc1().Length() );
       
   236                 TPtr8 ptr( tmpSdpData->Des() );
       
   237                 ptr.Copy( sdp.Left( mimePos ) );
       
   238                 ptr.Append( KHxAvc1 );
       
   239                 ptr.Append( sdp.Mid( mimePos + KMtvAvc().Length() ) );
       
   240                 sdp.Set( ptr );
       
   241                 }
       
   242             }
       
   243         }
       
   244 #endif // VIA_FEA_IPTV_USE_IPDC
       
   245 
       
   246     // Pass SDP to XPS
       
   247     LOG( "CCRXpsSink::SetSdpL(), iPacketSink->SetSessionDescription.." );
       
   248     User::LeaveIfError( iPacketSink->SetSessionDescription( sdp, streams ) );
       
   249     if ( tmpSdpData != NULL )
       
   250         {
       
   251         CleanupStack::PopAndDestroy( tmpSdpData );
       
   252         }
       
   253     
       
   254     // Config streams
       
   255     for ( TInt i( 0 ); i < streams; i++ )
       
   256         {
       
   257         LOG2( "CCRXpsSink::SetSdpL(), iPacketSink->ConfigStream: %d, KXpsBufferedPackets: %d",
       
   258             i, KXpsBufferedPackets );
       
   259         User::LeaveIfError( iPacketSink->ConfigStream( i, KXpsBufferedPackets ) ); 
       
   260         }
       
   261 
       
   262     CleanupStack::PopAndDestroy( sdpParser );
       
   263     iWaitPlayer = KErrNone;
       
   264     }
       
   265 
       
   266 // -----------------------------------------------------------------------------
       
   267 // CCRXpsSink::NewPacketAvailable
       
   268 // From CCRPacketSinkBase.
       
   269 // -----------------------------------------------------------------------------
       
   270 //      
       
   271 void CCRXpsSink::NewPacketAvailable()
       
   272     {
       
   273     // Kill flow timer
       
   274     StopTimer();
       
   275 
       
   276     // Ok to enqueue?
       
   277     if ( iBuffer )
       
   278         {
       
   279         if ( iWaitPlayer == KErrNone )
       
   280             {
       
   281             // Enqueue packet
       
   282             if ( SendPacket() )
       
   283                 {
       
   284                 // Keep buffer size reasonable
       
   285                 iBuffer->HandleBufferSize();
       
   286                 }
       
   287         	
       
   288             if ( iBuffer->ContinousStream() )
       
   289                 {
       
   290                 // Make sure all will be sent from the buffer in continous stream case
       
   291                 if ( iBuffer->PacketsCount( iSinkId ) > KErrNotFound )
       
   292                     {
       
   293                     StartTimer( 0 );
       
   294                     }
       
   295                 }
       
   296             else
       
   297                 {
       
   298                 // Group done, need request more
       
   299                 if ( !iBuffer->MoreComing() )
       
   300                     {
       
   301                     StartTimer( 0 );
       
   302                     }
       
   303                 }
       
   304             }
       
   305         else
       
   306             {
       
   307             iBuffer->HandleBufferSize();
       
   308             // Make sure that process never end  
       
   309             if ( !iBuffer->ContinousStream() )
       
   310                 {
       
   311                 StartTimer( KXpsOverflowDelay );
       
   312                 }
       
   313             }
       
   314         }
       
   315     }
       
   316 
       
   317 // -----------------------------------------------------------------------------
       
   318 // CCRXpsSink::BufferResetting
       
   319 // From CCRPacketSinkBase.
       
   320 // -----------------------------------------------------------------------------
       
   321 //      
       
   322 void CCRXpsSink::BufferResetDone()
       
   323     {
       
   324     StopTimer();
       
   325     iWaitPlayer = KErrNone;
       
   326 	iRequested = KErrNotFound;
       
   327     
       
   328     // XPS reset possible?
       
   329     if ( iXpsResetOk )
       
   330         {
       
   331         LOG( "CCRXpsSink::BufferResetDone(), Resets XPS.." );
       
   332         iPacketSink->Reset();
       
   333         iXpsResetOk = EFalse;
       
   334         }
       
   335     
       
   336     // Uninit TS converters
       
   337     LOG( "CCRXpsSink::BufferResetDone(), Uninitiates TS converters.." );
       
   338     if ( iAudioConv )
       
   339         {
       
   340         iAudioConv->UnInitiate();
       
   341         }
       
   342     if ( iVideoConv )
       
   343         {
       
   344         iVideoConv->UnInitiate();
       
   345         }
       
   346     if ( iTitleConv )
       
   347         {
       
   348         iTitleConv->UnInitiate();
       
   349         }
       
   350 
       
   351 #if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
       
   352     iLogXps = 0;
       
   353 #endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
       
   354     }
       
   355     
       
   356 // -----------------------------------------------------------------------------
       
   357 // CCRXpsSink::TimerExpired
       
   358 // From MCRTimerObserver.
       
   359 // -----------------------------------------------------------------------------
       
   360 //
       
   361 void CCRXpsSink::TimerExpired( CCRTimer* /*aTimer*/ )
       
   362     {
       
   363     RestoreSink();
       
   364     }
       
   365 
       
   366 // -----------------------------------------------------------------------------
       
   367 // CCRXpsSink::RestorePacketSupply
       
   368 // From CCRPacketSinkBase.
       
   369 // -----------------------------------------------------------------------------
       
   370 //      
       
   371 void CCRXpsSink::RestorePacketSupply( TUint aStreamId )
       
   372     {
       
   373 #if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
       
   374     if ( iLogXps < 5 )
       
   375         {
       
   376         iLogXps++;
       
   377         LOG2( "CCRXpsSink::RestorePacketSupply(), aStreamId: %d, iWaitPlayer: %d",
       
   378             aStreamId, iWaitPlayer );
       
   379         }
       
   380 #endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
       
   381 
       
   382     if ( iWaitPlayer != TInt( ETrue ) )
       
   383         {
       
   384         if ( iBuffer->ContinousStream() )
       
   385             {
       
   386             iRequested = aStreamId;
       
   387             iWaitPlayer = KErrNone;
       
   388             RestoreSink();
       
   389             }
       
   390         else
       
   391             {
       
   392             iWaitPlayer = KErrNone;
       
   393             StartTimer( KXpsOverflowDelay );
       
   394             }
       
   395         }
       
   396     }
       
   397 
       
   398 // -----------------------------------------------------------------------------
       
   399 // CCRXpsSink::RestoreSink
       
   400 // -----------------------------------------------------------------------------
       
   401 //
       
   402 void CCRXpsSink::RestoreSink()
       
   403     {
       
   404     if ( iBuffer )
       
   405         {
       
   406         // See if more waits in packet buffer
       
   407         if ( iBuffer->PacketsCount( iSinkId ) > KErrNotFound )
       
   408             {
       
   409             NewPacketAvailable();
       
   410             }
       
   411         else
       
   412             {
       
   413             StopTimer();
       
   414             // This is only for non continous stream, like .rtp clip
       
   415             iOwningSession.SourceRestore();
       
   416             }
       
   417         }
       
   418     }
       
   419 
       
   420 // -----------------------------------------------------------------------------
       
   421 // CCRXpsSink::SendPacket
       
   422 // Initialises time stamp converter for audio and video stream and passes RTP
       
   423 // packets with adjusted time stamp to XPS interface. All packets before
       
   424 // converter has beeen initialized are dumbed.
       
   425 // -----------------------------------------------------------------------------
       
   426 //
       
   427 TBool CCRXpsSink::SendPacket()
       
   428     {
       
   429     TBool packetSent( ETrue );
       
   430     MCRPacketSource::TCRPacketStreamId bufferId( MCRPacketSource::EStreamIdCount );
       
   431     const TInt book( iBuffer->GetStream( iSinkId, bufferId ) );
       
   432     TPtr8 packet( NULL, 0 );
       
   433 
       
   434     // Packet type related action
       
   435     TInt err( KErrNone );
       
   436     switch ( bufferId )
       
   437         {
       
   438         case MCRPacketSource::EAudioStream:
       
   439             if ( iAudioConv->Initiated() )
       
   440                 {
       
   441                 iBuffer->GetPacket( book, packet );
       
   442                 if ( iRequested == KErrNotFound || iRequested == iAudioStreamId )
       
   443                 	{
       
   444                 	iRequested = KErrNotFound;
       
   445                 	err = SendAudioPacket( packet );
       
   446                 	}
       
   447                 else
       
   448                 	{
       
   449                     LOG( "CCRXpsSink::SendPacket(), Audio packet DROPPED after XPS overflow !" ) 
       
   450                 	}
       
   451                 }
       
   452             else
       
   453                 {
       
   454                 packetSent = EFalse; 
       
   455                 SearchForControlStreamPackets();
       
   456                 }
       
   457             break;
       
   458 
       
   459         case MCRPacketSource::EAudioControlStream:
       
   460             {
       
   461             iBuffer->GetPacket( book, packet );
       
   462             if ( !iAudioConv->Initiated() )
       
   463                 {
       
   464                 iAudioConv->Init( packet );
       
   465                 LOG1( "CCRXpsSink::SendPacket(), Audio TS initiated, status: %d", 
       
   466                     iAudioConv->Initiated() )
       
   467                 }
       
   468             }
       
   469             break;
       
   470 
       
   471         case MCRPacketSource::EVideoStream:
       
   472             if ( iVideoConv->Initiated() )
       
   473                 {
       
   474                 iBuffer->GetPacket( book, packet );
       
   475                 if ( iRequested == KErrNotFound || iRequested == iVideoStreamId )
       
   476                 	{
       
   477                 	iRequested = KErrNotFound;
       
   478                 	err = SendVideoPacket( packet );
       
   479                 	}
       
   480                 else
       
   481                 	{
       
   482                     LOG( "CCRXpsSink::SendPacket(), Video packet DROPPED after XPS overflow !" ) 
       
   483                 	}
       
   484                 }
       
   485             else
       
   486                 {
       
   487                 packetSent = EFalse;
       
   488                 SearchForControlStreamPackets();
       
   489                 }
       
   490             break;
       
   491 
       
   492         case MCRPacketSource::EVideoControlStream:
       
   493             {
       
   494             iBuffer->GetPacket( book, packet );
       
   495             if ( !iVideoConv->Initiated() )
       
   496                 {
       
   497                 iVideoConv->Init( packet );
       
   498                 LOG1( "CCRXpsSink::SendPacket(), Video TS initiated, status: %d", 
       
   499                     iVideoConv->Initiated() )
       
   500                 }
       
   501             }
       
   502             break;
       
   503         
       
   504         case MCRPacketSource::ESubTitleStream:
       
   505             if ( iTitleConv->Initiated() )
       
   506                 {
       
   507                 iBuffer->GetPacket( book, packet );
       
   508                 err = SendTitlePacket( packet );
       
   509                 }
       
   510             else
       
   511                 {
       
   512                 packetSent = EFalse;
       
   513                 SearchForControlStreamPackets();
       
   514                 }
       
   515             break;
       
   516 
       
   517         case MCRPacketSource::ESubTitleControlStream:
       
   518             {
       
   519             iBuffer->GetPacket( book, packet );
       
   520             if ( !iTitleConv->Initiated() )
       
   521                 {
       
   522                 iTitleConv->Init( packet );
       
   523                 LOG1( "CCRXpsSink::SendPacket(), Title TS initiated, status: %d", 
       
   524                     iTitleConv->Initiated() )
       
   525                 }
       
   526             }
       
   527             break;
       
   528         
       
   529         case MCRPacketSource::EDisContinousStream:
       
   530         	{
       
   531             LOG( "CCRXpsSink::SendPacket(), EDiscontinousStream" );
       
   532             // Just wait player's "MvloLoadingStartedL" event,
       
   533             // PlayCommand( -1.0, -1.0 ) will then handle pause packet
       
   534             iWaitPlayer = ETrue;
       
   535             // Used packet out from the buffer
       
   536             iBuffer->GetPacket( book, packet );
       
   537         	}
       
   538             break;
       
   539 
       
   540         case MCRPacketSource::EStreamEndTag:
       
   541             LOG1( "CCRXpsSink::SendPacket(), EStreamEndTag, iRangeKnown: %d", iRangeKnown );
       
   542         	if ( iRangeKnown )
       
   543         		{
       
   544                 if ( iAudioStreamId > KErrNotFound )
       
   545                 	{
       
   546         		    iPacketSink->StreamEnd( iAudioStreamId );
       
   547                 	}
       
   548                 if ( iVideoStreamId > KErrNotFound )
       
   549                 	{
       
   550         	        iPacketSink->StreamEnd( iVideoStreamId );
       
   551                 	}
       
   552         		}
       
   553         	//else
       
   554         	//	{
       
   555         	//  Just wait player's "MvloLoadingStartedL" event,
       
   556             //  Play ends with PlayCommand( -1.0, -1.0 ) in .rtp clip case and/or
       
   557         	//  VIA will stop the play if play position goes beond the clip's lenght
       
   558             //  }
       
   559             
       
   560         	// Used packet out from the buffer
       
   561             iBuffer->GetPacket( book, packet );
       
   562             break;
       
   563         
       
   564         default:
       
   565             LOG1( "CCRXpsSink::SendPacket(), Bad bufferId: %d", bufferId );
       
   566         	// Used packet out from the buffer
       
   567             iBuffer->GetPacket( book, packet );
       
   568             break;
       
   569         }
       
   570     
       
   571     // Stop sink if error?
       
   572     if ( err )
       
   573         {
       
   574         LOG2( "CCRXpsSink::SendPacket(), error: %d, bufferId: %d", err, bufferId );
       
   575         LOG2( "CCRXpsSink::SendPacket(), iAudioStreamId: %d, iVideoStreamId: %d",
       
   576                                          iAudioStreamId, iVideoStreamId );
       
   577         iOwningSession.SinkStops( Id() );
       
   578         }
       
   579     
       
   580     return packetSent;
       
   581     }
       
   582 
       
   583 // -----------------------------------------------------------------------------
       
   584 // CCRXpsSink::SendAudioPacket
       
   585 // Adjust RTP timestamp and enqueue the packet.
       
   586 // -----------------------------------------------------------------------------
       
   587 //
       
   588 TInt CCRXpsSink::SendAudioPacket( const TDesC8& aPacket )
       
   589     {
       
   590     // Parse packet
       
   591     TInt err( iRtpPacket->ParseRtp( aPacket ) );
       
   592     if ( err )
       
   593         {
       
   594         LOG1( "CCRXpsSink::SendAudioPacket(), Parsing error: %d", err );
       
   595         return err;
       
   596         }
       
   597     
       
   598     // Adjust time stamp
       
   599     iRtpPacket->SetTimeStamp(
       
   600         iAudioConv->ConvertTs( iRtpPacket->iRtpRecvHeader.iTimestamp ) );
       
   601 
       
   602     // Send to player
       
   603     return EnqueuePacket( iAudioStreamId );
       
   604     }
       
   605 
       
   606 // -----------------------------------------------------------------------------
       
   607 // CCRXpsSink::SendVideoPacket
       
   608 // Adjust RTP timestamp and enqueue the packet.
       
   609 // -----------------------------------------------------------------------------
       
   610 //
       
   611 TInt CCRXpsSink::SendVideoPacket( const TDesC8& aPacket )
       
   612     {
       
   613     TPtrC8 packet( aPacket );
       
   614 
       
   615 #ifdef VIA_FEA_IPTV_USE_IPDC
       
   616     // Do ISMA Depacketizer
       
   617     if ( iVideoDepacketizer != NULL )
       
   618         {
       
   619         TInt result( iVideoDepacketizer->PushPacket( packet ) );
       
   620         if ( result != KErrCompletion ) // KErrCompletion means Ok
       
   621             {
       
   622             return KErrNone;
       
   623             }
       
   624 
       
   625         // Next packet should be available
       
   626         TInt err( iVideoDepacketizer->NextFrame( packet ) );
       
   627         if ( err )
       
   628             {
       
   629             LOG1( "CCRXpsSink::SendVideoPacket(), NextFrame error: %d", err );
       
   630             return err;
       
   631             }
       
   632         }
       
   633 #endif // VIA_FEA_IPTV_USE_IPDC
       
   634 
       
   635     // Parse packet
       
   636     TInt err( iRtpPacket->ParseRtp( packet ) );
       
   637     if ( err )
       
   638         {
       
   639         LOG1( "CCRXpsSink::SendVideoPacket(), Parsing error: %d", err );
       
   640         return err;
       
   641         }
       
   642     
       
   643     // Adjust time stamp
       
   644     iRtpPacket->SetTimeStamp( 
       
   645         iVideoConv->ConvertTs( iRtpPacket->iRtpRecvHeader.iTimestamp ) );
       
   646     
       
   647     // Send to player
       
   648     return EnqueuePacket( iVideoStreamId );
       
   649     }
       
   650 
       
   651 // -----------------------------------------------------------------------------
       
   652 // CCRXpsSink::SendTitlePacket
       
   653 // Adjust RTP timestamp and enqueue the packet.
       
   654 // -----------------------------------------------------------------------------
       
   655 //
       
   656 TInt CCRXpsSink::SendTitlePacket( const TDesC8& /*aPacket*/ )
       
   657     {
       
   658     // Title implementation unknown
       
   659     return KErrNotSupported;
       
   660     }
       
   661 
       
   662 // -----------------------------------------------------------------------------
       
   663 // CCRXpsSink::EnqueuePacket
       
   664 // Sends packet to the player.
       
   665 // -----------------------------------------------------------------------------
       
   666 //
       
   667 TInt CCRXpsSink::EnqueuePacket( const TUint aStreamId )
       
   668     {
       
   669     TInt err( iPacketSink->Enqueue(
       
   670         aStreamId, iRtpPacket->iRtpRecvHeader, iRtpPacket->iPayload ) );
       
   671 
       
   672 #if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
       
   673     if ( err && ( iLogXps < 5 || err != KErrOverflow ) )
       
   674         {
       
   675         LOG3( "CCRXpsSink::EnqueuePacket(), aStreamId: %d, err: %d, payload len: %d",
       
   676             aStreamId, err, iRtpPacket->iPayload.Length() );
       
   677         }
       
   678 #endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
       
   679 
       
   680     if ( err == KErrOverflow )
       
   681         {
       
   682         iWaitPlayer = err;
       
   683         return KErrNone;
       
   684         }
       
   685     
       
   686     // XPS reset can not be done before first packet is enqued
       
   687     iXpsResetOk = ETrue;
       
   688     return err; 
       
   689     }
       
   690     
       
   691 // -----------------------------------------------------------------------------
       
   692 // CCRXpsSink::SearchForControlStreamPackets
       
   693 // Checks buffer for control stream packets.
       
   694 // -----------------------------------------------------------------------------
       
   695 //
       
   696 void CCRXpsSink::SearchForControlStreamPackets()
       
   697     {
       
   698     // Check if RTCP packet already in buffer
       
   699     if ( CheckBufferForControlStreamPackets() )
       
   700         {
       
   701         iBuffer->AdjustBuffer();
       
   702         }
       
   703     else
       
   704         {
       
   705         // Get more packets if group not contains any RTCP packet(s)
       
   706         if ( !iBuffer->ContinousStream() && !iBuffer->MoreComing() )
       
   707             {
       
   708             iBuffer->AdjustBuffer();
       
   709             iOwningSession.SourceRestore();
       
   710             }
       
   711         }
       
   712     }
       
   713 
       
   714 // -----------------------------------------------------------------------------
       
   715 // CCRXpsSink::CheckBufferForControlStreamPackets
       
   716 // Checks buffer for control stream packets.
       
   717 // -----------------------------------------------------------------------------
       
   718 //
       
   719 TBool CCRXpsSink::CheckBufferForControlStreamPackets()
       
   720     {
       
   721     TBool audioOk( iAudioConv->Initiated() || iAudioStreamId == KErrNotFound );
       
   722     TBool videoOk( iVideoConv->Initiated() || iVideoStreamId == KErrNotFound );
       
   723     
       
   724     // Loop packets, oldest first
       
   725     for ( TInt offset( iBuffer->PacketsCount( iSinkId ) - 1 );
       
   726         ( !audioOk || !videoOk ) && offset >= 0; offset-- )
       
   727         {
       
   728         MCRPacketSource::TCRPacketStreamId streamId( MCRPacketSource::EStreamIdCount );
       
   729         const TInt book( iBuffer->GetStream( iSinkId, offset, streamId ) );
       
   730         TPtr8 packet( NULL, 0 );
       
   731         
       
   732         switch ( streamId )
       
   733             {
       
   734             case MCRPacketSource::EAudioControlStream:
       
   735                 if ( !iAudioConv->Initiated() )
       
   736                     {
       
   737                     audioOk = ETrue;
       
   738                     iBuffer->PeekPacket( book, packet, offset );
       
   739                     iAudioConv->Init( packet );
       
   740                     LOG1( "CCRXpsSink::CheckBufferForControlStreamPackets(), Audio TS initiated, status: %d", 
       
   741                             iAudioConv->Initiated() )
       
   742                     }
       
   743                 break;
       
   744                 
       
   745             case MCRPacketSource::EVideoControlStream:
       
   746                 if ( !iVideoConv->Initiated() )
       
   747                     {
       
   748                     videoOk = ETrue;
       
   749                     iBuffer->PeekPacket( book, packet, offset );
       
   750                     iVideoConv->Init( packet );
       
   751                     LOG1( "CCRXpsSink::CheckBufferForControlStreamPackets(), Video TS initiated, status: %d", 
       
   752                             iVideoConv->Initiated() )
       
   753                     }
       
   754                 break;
       
   755                 
       
   756             case MCRPacketSource::ESubTitleControlStream:
       
   757                 if ( !iTitleConv->Initiated() )
       
   758                     {
       
   759                     iBuffer->PeekPacket( book, packet, offset );
       
   760                     iTitleConv->Init( packet );
       
   761                     LOG1( "CCRXpsSink::CheckBufferForControlStreamPackets(), Title TS initiated, status: %d", 
       
   762                             iTitleConv->Initiated() )
       
   763                     }
       
   764                 break;
       
   765             
       
   766             default:
       
   767                 break;
       
   768             }
       
   769         }
       
   770     
       
   771     return ( audioOk && videoOk );
       
   772     }
       
   773 
       
   774 // -----------------------------------------------------------------------------
       
   775 // CCRXpsSink::StartTimer
       
   776 // Starts packet flow timer.
       
   777 // -----------------------------------------------------------------------------
       
   778 //
       
   779 void CCRXpsSink::StartTimer( const TInt& aInterval )
       
   780     {
       
   781     StopTimer();
       
   782     TRAPD( err, iFlowTimer = CCRTimer::NewL( 
       
   783                              CActive::EPriorityLow, *this ) );
       
   784     if ( !err )
       
   785         {
       
   786         iFlowTimer->After( aInterval );
       
   787         }
       
   788     else
       
   789         {
       
   790         LOG1( "CCRXpsSink::StartTimer(), Flowtimer err: %d", err );
       
   791         iOwningSession.SinkStops( Id() );
       
   792         }
       
   793     }
       
   794     
       
   795 // -----------------------------------------------------------------------------
       
   796 // CCRXpsSink::StopTimer
       
   797 // Starts packet flow timer.
       
   798 // -----------------------------------------------------------------------------
       
   799 //
       
   800 void CCRXpsSink::StopTimer()
       
   801     {
       
   802     delete iFlowTimer; iFlowTimer = NULL;
       
   803     }
       
   804     
       
   805 #ifdef VIA_FEA_IPTV_USE_IPDC
       
   806 // -----------------------------------------------------------------------------
       
   807 // CCRXpsSink::FindFmtpL
       
   808 // Finds the fmtp string.
       
   809 // -----------------------------------------------------------------------------
       
   810 //
       
   811 HBufC8* CCRXpsSink::FindFmtpLC( const TDesC8& aSdpData )
       
   812     {
       
   813     LOG( "CCRXpsSink::FindFmtpLC() in" );
       
   814     _LIT8( KCRStr, "\r" );
       
   815     _LIT8( KLFStr, "\n" );
       
   816     _LIT8( KHxAVCfmtp, "a=hxavcfmtp:" );
       
   817     
       
   818     // Get the video fmtp string
       
   819     HBufC8* fmtp = NULL;
       
   820     TInt pos = aSdpData.Find( KHxAVCfmtp );
       
   821     if ( pos > KErrNotFound )
       
   822         {
       
   823         // Extract the right most from the fist char after KHxAVCfmtp
       
   824         TPtrC8 rightPtr( aSdpData.Mid( pos + KHxAVCfmtp().Length() ) );
       
   825         
       
   826         // We need the first line of rightPtr
       
   827         TInt posLFStr( rightPtr.Find( KLFStr ) );
       
   828         TInt posCRStr( rightPtr.Find( KCRStr ) );
       
   829         if ( posLFStr > 0 && posCRStr > 0 )
       
   830             {
       
   831             fmtp = rightPtr.Left( Min( posLFStr, posCRStr ) ).AllocLC();
       
   832             }
       
   833         else if ( posLFStr > 0 )
       
   834             {
       
   835             fmtp = rightPtr.Left( posLFStr ).AllocLC();
       
   836             }
       
   837         else if ( posCRStr > 0 )
       
   838             {
       
   839             fmtp = rightPtr.Left( posCRStr ).AllocLC();
       
   840             }
       
   841         else
       
   842         	{
       
   843         	fmtp = rightPtr.AllocLC();
       
   844             }
       
   845         }
       
   846     
       
   847     User::LeaveIfNull( fmtp );
       
   848 #if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
       
   849     HBufC* buf = HBufC::NewL( fmtp->Length() );
       
   850     TPtr ptr( buf->Des() ); ptr.Copy( *fmtp );
       
   851     LOG1( "CCRXpsSink::FindFmtpLC() out, Fmtp: %S", &ptr );
       
   852 #endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
       
   853     return fmtp;
       
   854     }
       
   855 
       
   856 #endif // VIA_FEA_IPTV_USE_IPDC
       
   857 
       
   858     //  End of File