dvrengine/CommonRecordingEngine/src/CCRRtpTcpStreamer.cpp
branchRCL_3
changeset 23 13a33d82ad98
parent 0 822a42b6c3f1
equal deleted inserted replaced
22:826cea16efd9 23:13a33d82ad98
       
     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:    RTP/TCP streamer for RTSP source.*
       
    15 */
       
    16 
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "CCRRtpTcpStreamer.h"
       
    22 #include "CCRRtpTcpObserver.h"
       
    23 #include "CCRRtpTcpStream.h"
       
    24 #include "CRRTSPCommon.h"
       
    25 #include <es_sock.h>
       
    26 #include "videoserviceutilsLogger.h"
       
    27 
       
    28 // CONSTANTS
       
    29 const TInt KCRRtpTcpHeaderLength( 4 );
       
    30 const TInt KCRRtpTcpStartMark( 0x24 );
       
    31 
       
    32 // ============================ MEMBER FUNCTIONS ===============================
       
    33 
       
    34 // -----------------------------------------------------------------------------
       
    35 // CCRRtpTcpStreamer::NewL
       
    36 // -----------------------------------------------------------------------------
       
    37 CCRRtpTcpStreamer* CCRRtpTcpStreamer::NewL( MCRRtpTcpObserver& aObserver )
       
    38     {
       
    39     CCRRtpTcpStreamer* self = new( ELeave ) CCRRtpTcpStreamer( aObserver );
       
    40     CleanupStack::PushL( self );
       
    41     self->ConstructL();
       
    42     CleanupStack::Pop( self );
       
    43     return self;
       
    44     }
       
    45 
       
    46 // -----------------------------------------------------------------------------
       
    47 // CCRRtpTcpStreamer::CCRRtpTcpStreamer
       
    48 // -----------------------------------------------------------------------------
       
    49 //
       
    50 CCRRtpTcpStreamer::CCRRtpTcpStreamer( MCRRtpTcpObserver& aObserver )
       
    51   : iObserver( aObserver ),
       
    52     iMoreExpected( KErrNotFound ),
       
    53     iIpData( NULL )
       
    54     {
       
    55     // None
       
    56     }
       
    57 
       
    58 // -----------------------------------------------------------------------------
       
    59 // CCRRtpTcpStreamer::ConstructL
       
    60 // -----------------------------------------------------------------------------
       
    61 //
       
    62 void CCRRtpTcpStreamer::ConstructL()
       
    63     {
       
    64     // Construct streams
       
    65     for ( TInt i( 0 ); i < KCRRtpTcpStreamCount; i++ )
       
    66         {
       
    67         iStreams[i] = CCRRtpTcpStream::NewL( iObserver );
       
    68         }
       
    69     }
       
    70 
       
    71 // -----------------------------------------------------------------------------
       
    72 // CCRRtpTcpStreamer::~CCRRtpTcpStreamer
       
    73 // -----------------------------------------------------------------------------
       
    74 CCRRtpTcpStreamer::~CCRRtpTcpStreamer()
       
    75     {
       
    76     // Buffers
       
    77     if ( iIpData )
       
    78         {
       
    79         delete iIpData; iIpData = NULL;
       
    80         }
       
    81     if ( iRtspData )
       
    82         {
       
    83         delete iRtspData; iRtspData = NULL;
       
    84         }
       
    85 
       
    86     // Delete streams
       
    87     for ( TInt i( 0 ); i < KCRRtpTcpStreamCount; i++ )
       
    88         {
       
    89         if ( iStreams[i] )
       
    90             {
       
    91             delete iStreams[i]; iStreams[i] = NULL;
       
    92             }
       
    93         }
       
    94     }
       
    95 
       
    96 // -----------------------------------------------------------------------------
       
    97 // CCRRtpTcpStreamer::DataAvailable
       
    98 // -----------------------------------------------------------------------------
       
    99 //
       
   100 void CCRRtpTcpStreamer::DataAvailable(
       
   101     const TDesC8& aIpData,
       
   102     const TBool& aInterleaved )
       
   103     {
       
   104     TPtrC8 data( aIpData );
       
   105     if ( iMoreExpected > KErrNotFound && iIpData != NULL )
       
   106         {
       
   107         // More data expected
       
   108         if ( HandleMoreExpected( data ) )
       
   109             {
       
   110             return; // Need more
       
   111             }
       
   112         }
       
   113 
       
   114     // Can't be existing IP data at this point
       
   115     delete iIpData; iIpData = NULL;
       
   116     iMoreExpected = KErrNotFound;
       
   117     
       
   118     // Find out next packet
       
   119     do
       
   120         {
       
   121         // Search for $ (0x24) sign
       
   122         TBool tcp( EFalse );
       
   123         for ( TInt i( 0 ); aInterleaved && tcp == EFalse &&
       
   124             i < data.Length() && i < KCRRtpTcpHeaderLength; i++ )
       
   125             {
       
   126             if ( data[i] == KCRRtpTcpStartMark )
       
   127                 {
       
   128                 tcp = ETrue;
       
   129                 data.Set( data.Mid( i ) );
       
   130                 
       
   131                 // Received less than full interleved header (4 bytes)
       
   132                 if ( data.Length() < KCRRtpTcpHeaderLength )
       
   133                     {
       
   134                     iMoreExpected = KCRRtpTcpHeaderLength - data.Length();
       
   135                     iIpData = data.Alloc();
       
   136                     LOG1( "CCRRtpTcpStreamer::DataAvailable(), No interleave header, len: %d", data.Length() );
       
   137                     return; // Need more
       
   138                     }
       
   139                 }
       
   140             }
       
   141         
       
   142         if ( tcp )
       
   143             {
       
   144             // TCP packet
       
   145             if ( HandleTcpPacket( data ) )
       
   146                 {
       
   147                 return; // Need more
       
   148                 }
       
   149             }
       
   150         else
       
   151             {
       
   152             // RTSP response
       
   153             if ( HandleRtspResponse( data, aInterleaved ) )
       
   154                 {
       
   155                 return; // Need more
       
   156                 }
       
   157         
       
   158             delete iRtspData; iRtspData = NULL;
       
   159             }
       
   160         }
       
   161         while ( data.Length() > 0 );
       
   162     }
       
   163 
       
   164 // -----------------------------------------------------------------------------
       
   165 // CCRRtpTcpStreamer::HandleMoreExpected
       
   166 // -----------------------------------------------------------------------------
       
   167 //
       
   168 TBool CCRRtpTcpStreamer::HandleMoreExpected( TPtrC8& aData )
       
   169     {
       
   170     TInt len( aData.Length() );
       
   171     int used( len );
       
   172     if ( len >= iMoreExpected || iMoreExpected == KMaxTInt )
       
   173         {
       
   174         if ( iMoreExpected >= KCRRtpTcpHeaderLength ||
       
   175              iIpData->Des()[0] != KCRRtpTcpStartMark ||
       
   176              iIpData->Length() >= KCRRtpTcpHeaderLength )
       
   177             {
       
   178             // KMaxTInt is indication of unknow length in RTSP response
       
   179             if ( iMoreExpected < KMaxTInt )
       
   180                 {
       
   181                 used = iMoreExpected;
       
   182                 iMoreExpected = KErrNotFound;
       
   183                 }
       
   184             else
       
   185                 {
       
   186                 // Combine datas and try find out RTSP response
       
   187                 delete iRtspData; iRtspData = NULL;
       
   188                 iRtspData = HBufC8::New( iIpData->Length() + len );
       
   189                 TPtr8 ptr( iRtspData->Des() );
       
   190                 ptr.Copy( iIpData->Des() );
       
   191                 ptr.Append( aData );
       
   192                 aData.Set( iRtspData->Des() );
       
   193                 return EFalse; // Continue
       
   194                 }
       
   195             }
       
   196         else
       
   197             {
       
   198             // Fill interleave header
       
   199             iIpData = iIpData->ReAlloc( iIpData->Length() + iMoreExpected );
       
   200             TPtr8 ptr( iIpData->Des() );
       
   201             ptr.Append( aData.Mid( 0, iMoreExpected ) );
       
   202             aData.Set( aData.Mid( iMoreExpected ) );
       
   203             len = aData.Length();
       
   204             used = len;
       
   205             // Find real wanted packet length 
       
   206             iMoreExpected = ( TInt )BigEndian::Get16( ptr.Ptr() + 2 );
       
   207             if ( len == 0 )
       
   208                 {
       
   209                 return ETrue; // Need more
       
   210                 }
       
   211             if ( len >= iMoreExpected )
       
   212                 {
       
   213                 used = iMoreExpected;
       
   214                 iMoreExpected = KErrNotFound;
       
   215                 }
       
   216             }
       
   217         }
       
   218 
       
   219     // Add new data to iIpData
       
   220     iIpData = iIpData->ReAlloc( iIpData->Length() + used );
       
   221     TPtr8 ptr( iIpData->Des() );
       
   222     ptr.Append( aData.Mid( 0, used ) );
       
   223     aData.Set( aData.Mid( used ) );
       
   224     if ( iMoreExpected == KErrNotFound )
       
   225         {
       
   226         ForwardPacket( ptr );
       
   227         if ( used == len )
       
   228             {
       
   229             delete iIpData; iIpData = NULL;
       
   230             return ETrue; // All handled
       
   231             }
       
   232         }
       
   233     else
       
   234         {
       
   235         iMoreExpected -= used;
       
   236         return ETrue; // Need more
       
   237         }
       
   238         
       
   239     return EFalse; // Continue
       
   240     }
       
   241     
       
   242 // -----------------------------------------------------------------------------
       
   243 // CCRRtpTcpStreamer::HandleTcpPacket
       
   244 // -----------------------------------------------------------------------------
       
   245 //
       
   246 TBool CCRRtpTcpStreamer::HandleTcpPacket( TPtrC8& aData )
       
   247     {
       
   248     const TInt length( KCRRtpTcpHeaderLength + 
       
   249         ( TInt )BigEndian::Get16( aData.Ptr() + 2 ) );
       
   250     if ( aData.Length() >= length )
       
   251         {
       
   252         MakePacket( aData, length );
       
   253         }
       
   254     else
       
   255         {
       
   256         // Need more data
       
   257         iMoreExpected = length - aData.Length();
       
   258         iIpData = aData.Alloc();
       
   259         return ETrue; // Need more
       
   260         }
       
   261     
       
   262     return EFalse; // Continue
       
   263     }
       
   264     
       
   265 // -----------------------------------------------------------------------------
       
   266 // CCRRtpTcpStreamer::HandleRtspResponse
       
   267 // -----------------------------------------------------------------------------
       
   268 //
       
   269 TBool CCRRtpTcpStreamer::HandleRtspResponse(
       
   270     TPtrC8& aData,
       
   271     const TBool& aInterleaved )
       
   272     {
       
   273     TInt point( aData.FindC( KCRRTSPReplyHeader ) );
       
   274     if ( point > KErrNotFound )
       
   275         {
       
   276         aData.Set( aData.Mid( point ) );
       
   277         
       
   278         // Search for double CRLF combination
       
   279         TInt crlf2( aData.FindC( KCR2NewLines ) );
       
   280 		if ( crlf2 > KErrNotFound )
       
   281 		    {
       
   282 		    crlf2 += KCR2NewLines().Length();
       
   283 		    }
       
   284 
       
   285         // Content length
       
   286         point = aData.FindC( KCRRTSPContentLength() );
       
   287         if ( point > KErrNotFound && crlf2 > KErrNotFound )
       
   288             {
       
   289             point += KCRRTSPContentLength().Length();
       
   290             TInt contentLen( KErrNotFound );
       
   291             TLex8 contentLenLex( aData.Mid( point, 5 ) );
       
   292             if ( contentLenLex.Val( contentLen ) < KErrNone )
       
   293                 {
       
   294                 LOG1( "CCRRtpTcpStreamer::HandleRtspResponse(), Content length parse failed, Dumped %d bytes !", aData.Length() );
       
   295                 return ETrue;
       
   296                 }
       
   297             
       
   298             LOG1( "CCRRtspCommon::HandleRtspResponse(), contentLen %d", contentLen );
       
   299             // Verify that enought data in IP packet
       
   300             if ( aData.Length() >= ( crlf2 + contentLen ) )
       
   301                 {
       
   302                 MakePacket( aData, crlf2 + contentLen );
       
   303                 }
       
   304             else
       
   305                 {
       
   306                 // Need more
       
   307                 iIpData = aData.Alloc();
       
   308                 iMoreExpected = crlf2 + contentLen - aData.Length();
       
   309                 return ETrue;
       
   310                 }
       
   311             }
       
   312         else
       
   313             {
       
   314             // Content length not defined, RTSP command should end to double CRLF
       
   315             if ( crlf2 > KErrNotFound )
       
   316                 {
       
   317                 MakePacket( aData, crlf2 );
       
   318                 }
       
   319             else
       
   320                 {
       
   321                 LOG( "CCRRtpTcpStreamer::HandleRtspResponse(), No double CRLF.." );
       
   322                 
       
   323                 // Look for single CRLF
       
   324                 point = aData.FindC( KCRNewLine );
       
   325                 if ( point > KErrNotFound )
       
   326                     {
       
   327                     // If not interleaved, all data belongs to RTSP response
       
   328                     if ( !aInterleaved )
       
   329                         {
       
   330                         if ( aData.Mid( aData.Length() - KCR2NewLines().Length() ).
       
   331                             FindF( KCRNewLine ) > KErrNotFound )
       
   332                             {
       
   333                             ForwardPacket( aData );
       
   334                             return ETrue;
       
   335                             }
       
   336                         
       
   337                         // Not complete but total length unknown
       
   338                         LOG( "CCRRtpTcpStreamer::HandleRtspResponse(), Need more without known length.." );
       
   339                         iIpData = aData.Alloc();
       
   340                         iMoreExpected = KMaxTInt;
       
   341                         return ETrue;
       
   342                         }
       
   343 
       
   344                     // Only one CRLF after RTSP response, find last
       
   345                     point += KCRNewLine().Length();
       
   346                     for ( TInt i( point ); i < aData.Length(); )
       
   347                         {
       
   348                         TInt next( aData.Mid( point ).FindC( KCRNewLine ) );
       
   349                         if ( next > KErrNotFound )
       
   350                             {
       
   351                             point += ( next + KCRNewLine().Length() );
       
   352                             i = point;
       
   353                             }
       
   354                         else
       
   355                             {
       
   356                             i = aData.Length();
       
   357                             }
       
   358                         }
       
   359 
       
   360                     LOG1( "CCRRtpTcpStreamer::HandleRtspResponse(), Last CRLF at index: %d", point );
       
   361                     MakePacket( aData, point );
       
   362                     }
       
   363                 else
       
   364                     {
       
   365                     // Not any CRLF, can not be RTSP response
       
   366                     LOG1( "CCRRtpTcpStreamer::HandleRtspResponse(), No CRLF, Dumped %d bytes !", aData.Length() );
       
   367                     return ETrue;
       
   368                     }
       
   369                 }
       
   370             }
       
   371         }
       
   372     else
       
   373         {
       
   374         LOG1( "CCRRtpTcpStreamer::HandleRtspResponse(), Not RTSP message, Dumped %d bytes !", aData.Length() );
       
   375         return ETrue;
       
   376         }
       
   377     
       
   378     return EFalse;
       
   379     }
       
   380     
       
   381 // -----------------------------------------------------------------------------
       
   382 // CCRRtpTcpStreamer::MakePacket
       
   383 // -----------------------------------------------------------------------------
       
   384 //
       
   385 void CCRRtpTcpStreamer::MakePacket( TPtrC8& aData, const TInt aLength )
       
   386     {
       
   387     ForwardPacket( aData.Mid( 0, aLength ) );
       
   388     aData.Set( aData.Mid( aLength ) );
       
   389     }
       
   390     
       
   391 // -----------------------------------------------------------------------------
       
   392 // CCRRtpTcpStreamer::ForwardPacket
       
   393 // -----------------------------------------------------------------------------
       
   394 //
       
   395 void CCRRtpTcpStreamer::ForwardPacket( const TDesC8& aPacket )
       
   396     {
       
   397     if ( aPacket[0] == KCRRtpTcpStartMark )
       
   398         {
       
   399         // 1. Forward (actually return or signal reception of) packet to user
       
   400         const TInt channel( ( TInt )aPacket[1] );
       
   401         iObserver.RtpTcpPacketAvailable(
       
   402             channel, aPacket.Mid( KCRRtpTcpHeaderLength ) );
       
   403 
       
   404         // 2. Map channel to internal stream, ignore non audio or video
       
   405         const TInt streamId( channel / 2 );
       
   406         if ( streamId >= 0 && streamId < KCRRtpTcpStreamCount )
       
   407             {
       
   408             iStreams[streamId]->PacketAvailable( channel );
       
   409             }
       
   410         }
       
   411     else
       
   412         {
       
   413         // RTSP
       
   414         iObserver.RtspMsgAvailable( aPacket );
       
   415         }
       
   416     }
       
   417 
       
   418 //  End of File