--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dvrengine/CommonRecordingEngine/DvrSdpParser/src/CDvrSdpParser.cpp Thu Dec 17 09:14:38 2009 +0200
@@ -0,0 +1,1063 @@
+/*
+* 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: Parses SDP file.*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <ipvideo/CDvrSdpParser.h>
+#include <in_sock.h>
+#include "videoserviceutilsLogger.h"
+
+// CONSTANTS
+_LIT8( KKeyIpv4Addr, "c=IN IP4 " );
+_LIT8( KKeyIpv6Addr, "c=IN IP6 " );
+_LIT8( KKeyAttribute, "a=" );
+_LIT8( KKeyMedia, "m=" );
+_LIT8( KKeyMediaAudio, "m=audio " );
+_LIT8( KKeyMediaVideo, "m=video " );
+_LIT8( KKeyMediaTitle, "m=title " );
+_LIT8( KKeyDataStream, "m=data " );
+_LIT8( KKeyClockRate, "a=rtpmap:" );
+_LIT8( KKeyControl, "a=control:" );
+//_LIT8( KKeyStreamId, "a=control:streamid=" );
+_LIT8( KRealMediaIndicator, "/x-pn-real" );
+_LIT8( KKeyBandWidth, "b=AS:" );
+_LIT8( KCRSDPRtspUriBegin, "rtsp://" );
+_LIT8( KSPStr, " ");
+_LIT8( KCRStr, "\r");
+_LIT8( KLFStr, "\n");
+_LIT8( KCRLFStr, "\r\n");
+_LIT8( KSLStr, "/" );
+_LIT8( KSdpLiveStream, "a=LiveStream:integer;1");
+_LIT8( KSdpRangeHeaderLiveStream, "a=range:npt=now-" );
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CDvrSdpParser* CDvrSdpParser::NewL()
+ {
+ CDvrSdpParser* self = CDvrSdpParser::NewLC();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::NewLC
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CDvrSdpParser* CDvrSdpParser::NewLC()
+ {
+ CDvrSdpParser* self = new( ELeave ) CDvrSdpParser();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::CDvrSdpParser
+// C++ default constructor can NOT contain any code, that might leave.
+// -----------------------------------------------------------------------------
+//
+CDvrSdpParser::CDvrSdpParser()
+ : iAudioPort( KErrNotFound ),
+ iVideoPort( KErrNotFound ),
+ iTitlePort( KErrNotFound ),
+ iAudioBitrate( KErrNotFound ),
+ iVideoBitrate( KErrNotFound ),
+ iAudioStreamId( KErrNotFound ),
+ iVideoStreamId( KErrNotFound ),
+ iVideoTimerGranularity( KMaxTUint32 ),
+ iAudioTimerGranularity( KMaxTUint32 )
+ {
+ // None
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CDvrSdpParser::ConstructL()
+ {
+ LOG( "CDvrSdpParser::ConstructL()" );
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::~CDvrSdpParser
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CDvrSdpParser::~CDvrSdpParser()
+ {
+ LOG( "CDvrSdpParser::~CDvrSdpParser()" );
+ delete iBaseUrl; iBaseUrl = NULL;
+ DeleteVariables();
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::TryParseL
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CDvrSdpParser::TryParseL( const TDesC8& aSdp, const TDesC8& aBaseUrl )
+ {
+#if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
+ HBufC* baseLog = HBufC::NewLC( aBaseUrl.Length() );
+ TPtr ptr = baseLog->Des();
+ ptr.Copy( aBaseUrl );
+ LOG2( "CDvrSdpParser::TryParseL(), aSdp length: %d, aBaseUrl: %S",
+ aSdp.Length(), &ptr );
+ CleanupStack::PopAndDestroy( baseLog );
+#endif
+
+ if ( aBaseUrl.Length() )
+ {
+ delete iBaseUrl; iBaseUrl = NULL;
+ iBaseUrl = aBaseUrl.AllocL();
+ }
+
+ TryParseL( aSdp );
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::TryParseL
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CDvrSdpParser::TryParseL( const TDesC8& aSdp )
+ {
+ LOG1( "CDvrSdpParser::TryParseL(), aSdp length: %d", aSdp.Length() );
+
+ // Find medias
+ FindMediasL( aSdp );
+
+ // Append found medias to the array
+ for ( TInt i( 0 ); i < iMediaBuf.Count(); i++ )
+ {
+ TInt port( KErrNotFound );
+ TPtrC8 ptr( iMediaBuf[i] );
+
+ // Audio media info found ?
+ port = GetIntL( ptr, KKeyMediaAudio );
+ if ( port != KErrNotFound )
+ {
+ iAudioPort = port;
+ LOG1( "CDvrSdpParser::TryParseL(), iAudioPort: %d", iAudioPort );
+ UpdateMediaInfoL( ptr, iAudioIpAddr );
+ // Stream id (Helix takes medias in appearance order)
+ iAudioStreamId = i;
+ // Audio clock rate
+ iAudioTimerGranularity = GetClockRateL( ptr );
+ iAudioBitrate = GetIntL( ptr, KKeyBandWidth );
+ // Audio attributes
+ FindAttributesL( ptr, iAudioAttributes );
+ // Audio control
+ GetControlL( ptr, iAudioControlAddr );
+ // Find media id 97 from a=rtpmap:97 MP4A-LATM/32000/2
+ iMediaIdentifierAudio = GetIntL( ptr, KKeyClockRate );
+ }
+ else
+ {
+ // Video media info found ?
+ port = GetIntL( ptr, KKeyMediaVideo );
+ if ( port != KErrNotFound )
+ {
+ iVideoPort = port;
+ LOG1( "CDvrSdpParser::TryParseL(), iVideoPort: %d", iVideoPort );
+ UpdateMediaInfoL( ptr, iVideoIpAddr );
+ // Stream id (Helix takes medias in appearance order)
+ iVideoStreamId = i;
+ // Video clock rate
+ iVideoTimerGranularity = GetClockRateL( ptr );
+ iVideoBitrate = GetIntL( ptr, KKeyBandWidth );
+ // Video attributes
+ FindAttributesL( ptr, iVideoAttributes );
+ // Video control
+ GetControlL( ptr, iVideoControlAddr );
+ // Find media id 96 from a=rtpmap:96 H264/90000 line
+ iMediaIdentifierVideo = GetIntL( ptr, KKeyClockRate );
+ }
+ else
+ {
+ port = GetIntL( ptr, KKeyMediaTitle );
+ if ( port != KErrNotFound )
+ {
+ iTitlePort = port;
+ LOG1( "CDvrSdpParser::TryParseL(), iTitlePort: %d", iTitlePort );
+ }
+ }
+ }
+ }
+
+ iMediaBuf.Reset();
+ delete iBaseUrl; iBaseUrl = NULL;
+ delete iCommonIp; iCommonIp = NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::NewLineL
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CDvrSdpParser::NewLineL(
+ const TInt aStreamId,
+ const TDesC8& aLine )
+ {
+ User::LeaveIfNull( iSdp );
+ const TInt newLen( iSdp->Length() + aLine.Length() + KCRLFStr().Length() );
+ LOG2( "CDvrSdpParser::NewLineL(), aStreamId: %d, New sdp length: %d",
+ aStreamId, newLen );
+ switch( aStreamId )
+ {
+ case KErrNotFound: // Common
+ {
+ // Alloc more room
+ iSdp = iSdp->ReAllocL( newLen );
+ TPtr8 ptr( iSdp->Des() );
+
+ // Find first attribute for new line point
+ const TInt insertPoint( ptr.Find( KKeyAttribute ) );
+ User::LeaveIfError( insertPoint );
+ ptr.Insert( insertPoint, KCRLFStr );
+ ptr.Insert( insertPoint, aLine );
+ }
+ break;
+
+ case 0: // Audio (usually)
+ case 1: // Video (usually)
+ {
+ iSdp = iSdp->ReAllocL( newLen );
+ InserNewLineL( aStreamId, aLine );
+ }
+ break;
+
+ default:
+ User::Leave( KErrCompletion );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::GetSdp
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CDvrSdpParser::GetSdp( TPtrC8& aSdp )
+ {
+ if ( iSdp )
+ {
+ aSdp.Set( iSdp->Des() );
+ return KErrNone;
+ }
+
+ return KErrNotFound;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::SupportedContent
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CDvrSdpParser::TDvrPacketProvidings CDvrSdpParser::SupportedContent( void )
+ {
+ TDvrPacketProvidings retval( EDvrNoProgramAtAll );
+
+ if ( iAudioPort > KErrNotFound && iVideoPort > KErrNotFound )
+ {
+ retval = EDvrBothAudioAndVideo;
+ }
+ else if ( iAudioPort > KErrNotFound && iVideoPort <= KErrNotFound )
+ {
+ retval = EDvrAudioOnly;
+ }
+ else if ( iVideoPort > KErrNotFound && iAudioPort <= KErrNotFound )
+ {
+ retval = EDvrVideoOnly;
+ }
+ else
+ {
+ LOG( "CDvrSdpParser::SupportedContent(), No media !" );
+ }
+
+ return retval;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::SessionAttributes
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C RArray<TPtrC8>& CDvrSdpParser::SessionAttributes( void )
+ {
+ return iSessionAttributes;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::AudioAttributes
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C RArray<TPtrC8>& CDvrSdpParser::AudioAttributes( void )
+ {
+ return iAudioAttributes;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::VideoAttributes
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C RArray<TPtrC8>& CDvrSdpParser::VideoAttributes( void )
+ {
+ return iVideoAttributes;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::DataStreams
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C RArray<TPtrC8>& CDvrSdpParser::DataStreams( void )
+ {
+ return iDataStreams;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::IsIpv4Sdp
+// Checks if Ipv4 address in use.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CDvrSdpParser::IsIpv4Sdp( void )
+ {
+ return iIsIpv4;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::IsMultiCastSdp
+// Checks if c= line did specify a multicast addr
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CDvrSdpParser::IsMultiCastSdp( void )
+ {
+ return iIsMulticast;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::AudioControlAddr
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 CDvrSdpParser::AudioControlAddr( void )
+ {
+ return ( iAudioControlAddr )? TPtrC8( *iAudioControlAddr ):
+ TPtrC8( KNullDesC8 );
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::VideoControlAddr
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 CDvrSdpParser::VideoControlAddr( void )
+ {
+ return ( iVideoControlAddr )? TPtrC8( *iVideoControlAddr ):
+ TPtrC8( KNullDesC8 );
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::AudioIpAddr
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 CDvrSdpParser::AudioIpAddr( void )
+ {
+ return ( iAudioIpAddr )? TPtrC8( *iAudioIpAddr ): TPtrC8( KNullDesC8 );
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::VideoIpAddr
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TPtrC8 CDvrSdpParser::VideoIpAddr( void )
+ {
+ return ( iVideoIpAddr )? TPtrC8( *iVideoIpAddr ): TPtrC8( KNullDesC8 );
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::AudioPort
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CDvrSdpParser::AudioPort( void )
+ {
+ return iAudioPort;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::VideoPort
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CDvrSdpParser::VideoPort( void )
+ {
+ return iVideoPort;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::AudioBitrate
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CDvrSdpParser::AudioBitrate( void )
+ {
+ return iAudioBitrate;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::VideoBitrate
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CDvrSdpParser::VideoBitrate( void )
+ {
+ return iVideoBitrate;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::AudioStreamId
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CDvrSdpParser::AudioStreamId( void )
+ {
+ return iAudioStreamId;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::VideoStreamId
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CDvrSdpParser::VideoStreamId( void )
+ {
+ return iVideoStreamId;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::VideoTimerGranularity
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TUint32 CDvrSdpParser::VideoTimerGranularity( void )
+ {
+ return iVideoTimerGranularity;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::AudioTimerGranularity
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TUint32 CDvrSdpParser::AudioTimerGranularity( void )
+ {
+ return iAudioTimerGranularity;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::IsRealMediaContent
+// Check for realmedia content.
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CDvrSdpParser::IsRealMediaContent( void )
+ {
+ if ( iSdp && iSdp->Des().Find( KRealMediaIndicator ) != KErrNotFound )
+ {
+ LOG( "CDvrSdpParser::IsRealMediaContent(), Yes" );
+ return ETrue;
+ }
+
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::MediaIdentifierAudio
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CDvrSdpParser::MediaIdentifierAudio( void )
+ {
+ return iMediaIdentifierAudio ;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::MediaIdentifierVideo
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CDvrSdpParser::MediaIdentifierVideo( void )
+ {
+ return iMediaIdentifierVideo ;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::IsLiveStream
+//
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CDvrSdpParser::IsLiveStream( void )
+ {
+ TBool isLiveStream = EFalse;
+ if ( iSdp &&
+ ( iSdp->Des().Find( KSdpLiveStream ) != KErrNotFound ||
+ iSdp->Des().Find( KSdpRangeHeaderLiveStream ) != KErrNotFound ) )
+ {
+ LOG( "CDvrSdpParser::IsLiveStream(), Yes" );
+ isLiveStream = ETrue;
+ }
+
+ return isLiveStream;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::FindMediasL
+//
+// -----------------------------------------------------------------------------
+//
+void CDvrSdpParser::FindMediasL( const TDesC8& aSdp )
+ {
+ LOG1( "CDvrSdpParser::FindMediasL(), aSdp length: %d", aSdp.Length() );
+
+ // Find medias from SDP
+ DeleteVariables();
+ iSdp = aSdp.AllocL();
+ RArray<SMediaPoint> points;
+ CleanupClosePushL( points );
+ FindMediaPointsL( points );
+ MakeMediaBuffersL( points );
+ FindSessionAttributesL( points );
+ CleanupStack::PopAndDestroy( &points );
+ FindDataStreamsL( iSdp->Des(), iDataStreams );
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::FindMediaPointsL
+// Find points of all medias.
+// -----------------------------------------------------------------------------
+//
+void CDvrSdpParser::FindMediaPointsL( RArray<SMediaPoint>& aPoints )
+ {
+ TInt lastPoint( 0 );
+ User::LeaveIfNull( iSdp );
+ TPtrC8 ptr( iSdp->Des() );
+ TInt start( MediaSectionStart( ptr ) );
+
+ // Loop all media sections
+ while ( start > KErrNotFound && lastPoint < iSdp->Length() )
+ {
+ // Find whole media section, up to next media or EOF
+ start += lastPoint;
+ TInt len( MediaSectionStart( ptr.Mid( start + KKeyMedia().Length() ) ) );
+ len = ( len > KErrNotFound )? len + KKeyMedia().Length() - 1:
+ ptr.Length() - start - 1;
+ // New media point
+ SMediaPoint point;
+ point.iStart = start;
+ point.iLength = len;
+ lastPoint = ( start + len );
+ User::LeaveIfError( aPoints.Append( point ) );
+ LOG3( "CDvrSdpParser::FindMediaPointsL(), start: %d, len: %d, lastPoint: %d",
+ start, len, lastPoint );
+ // Next section
+ start = MediaSectionStart( ptr.Mid( lastPoint ) );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::MediaSectionStart
+//
+// -----------------------------------------------------------------------------
+//
+TInt CDvrSdpParser::MediaSectionStart( const TDesC8& aPtr )
+ {
+ TInt start( aPtr.Find( KKeyMedia ) );
+ while ( start > KErrNotFound )
+ {
+ // Verify that not data stream keyword? ( i.e not 'm=data' )
+ const TInt keywordlen( KKeyDataStream().Length() );
+ TPtrC8 ptr( aPtr.Mid( start, keywordlen ) );
+ if ( ptr.Find( KKeyDataStream ) == KErrNotFound )
+ {
+ // Audio, video or subtitle
+ return start;
+ }
+
+ start += keywordlen;
+ const TInt next( aPtr.Mid( start ).Find( KKeyMedia ) );
+ start = ( next > KErrNotFound )? start + next: KErrNotFound;
+ }
+
+ return start;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::MakeMediaBuffersL
+// Make media buffers
+// -----------------------------------------------------------------------------
+//
+void CDvrSdpParser::MakeMediaBuffersL( RArray<SMediaPoint>& aPoints )
+ {
+ User::LeaveIfNull( iSdp );
+ for ( TInt i( 0 ); i < aPoints.Count(); i++ )
+ {
+ TPtrC8 media( iSdp->Des().Mid( aPoints[i].iStart, aPoints[i].iLength ) );
+ User::LeaveIfError( iMediaBuf.Append( media ) );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::FindSessionAttributesL
+// Find session attributes (common section before any media)
+// -----------------------------------------------------------------------------
+//
+void CDvrSdpParser::FindSessionAttributesL( RArray<SMediaPoint>& aPoints )
+ {
+ User::LeaveIfNull( iSdp );
+ if ( aPoints.Count() )
+ {
+ TPtrC8 common( iSdp->Des().Left( aPoints[0].iStart ) );
+ FindAttributesL( common, iSessionAttributes );
+
+ // IP in common section
+ delete iCommonIp; iCommonIp = NULL;
+ iCommonIp = GetIpAddrL( common );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::InserNewLineL
+//
+// -----------------------------------------------------------------------------
+//
+void CDvrSdpParser::InserNewLineL(
+ TInt aStreamId,
+ const TDesC8& aLine )
+ {
+ RArray<SMediaPoint> points;
+ CleanupClosePushL( points );
+ FindMediaPointsL( points );
+
+ // Add new line to first after media description
+ if ( aStreamId >= 0 && aStreamId < points.Count() )
+ {
+ User::LeaveIfNull( iSdp );
+ TPtr8 ptr( iSdp->Des() );
+ TInt insertPoint( GetLen( ptr.Mid( points[aStreamId].iStart,
+ points[aStreamId].iLength ), ETrue ) );
+ User::LeaveIfError( insertPoint );
+ ptr.Insert( insertPoint, aLine );
+ ptr.Insert( insertPoint, KCRLFStr );
+ }
+ else
+ {
+ User::Leave( KErrCompletion );
+ }
+
+ CleanupStack::PopAndDestroy( &points );
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::UpdateMediaInfoL
+//
+// -----------------------------------------------------------------------------
+//
+void CDvrSdpParser::UpdateMediaInfoL(
+ const TDesC8& aMediaPtr,
+ HBufC8*& aAddress )
+ {
+ // Search for IP address (Ipv6/Ipv4)
+ aAddress = GetIpAddrL( aMediaPtr );
+ if ( !aAddress && iCommonIp )
+ {
+ aAddress = iCommonIp->AllocL();
+ }
+ User::LeaveIfNull( aAddress );
+ TPtr8 ptr( aAddress->Des() );
+
+ // IP Address
+ if ( iIsIpv4 )
+ {
+ LOG( "CDvrSdpParser::UpdateMediaInfoL(), Removing v4 subnet mask" );
+ // Remove possible subnet mask (e.g. c=IN IP4 225.0.1.15/64)
+ const TInt maskPos( aAddress->Find( KSLStr ) );
+ if ( maskPos != KErrNotFound )
+ {
+ ptr.SetLength( maskPos );
+ }
+ }
+
+#if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
+ TName buf; buf.Copy( ptr );
+ LOG1( "CDvrSdpParser::UpdateMediaInfoL(), aAddress: %S", &buf );
+#endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
+
+ /* Stream Id
+ const TInt streamId( GetIntL( aMediaPtr, KKeyStreamId ) );
+ LOG1( "CDvrSdpParser::UpdateMediaInfoL(), Stream Id: %d", streamId );
+ return streamId;
+ */
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::GetIpAddrL
+//
+// -----------------------------------------------------------------------------
+//
+HBufC8* CDvrSdpParser::GetIpAddrL( const TDesC8& aPtr )
+ {
+ iIsIpv4 = EFalse;
+ HBufC8* ipAddr = GetStringL( aPtr, KKeyIpv6Addr );
+ if ( !ipAddr )
+ {
+ ipAddr = GetStringL( aPtr, KKeyIpv4Addr );
+ if ( ipAddr )
+ {
+ iIsIpv4 = ETrue;
+ }
+ }
+
+ // Verify multicast
+ if ( ipAddr )
+ {
+ TPtrC8 addr( ipAddr->Des() );
+ if ( addr.Length() <= KMaxName )
+ {
+ CheckForMulticast( addr );
+ }
+ else
+ {
+ LOG1( "Ipaddress length too long: %d, leaving....", addr.Length() );
+ delete ipAddr; ipAddr = NULL;
+ User::Leave( KErrOverflow );
+ }
+ }
+
+ return ipAddr;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::GetClockRateL
+//
+// -----------------------------------------------------------------------------
+//
+TUint CDvrSdpParser::GetClockRateL( const TDesC8& aPtr )
+ {
+ // Find clock rate keyword
+ TInt start( FindStart( aPtr, KKeyClockRate ) );
+ User::LeaveIfError( start );
+
+ // Len up to first slash ( i.e: rtpmap:97 MP4A-LATM/32000/2 )
+ TInt slash( aPtr.Mid( start ).Find( KSLStr ) );
+ User::LeaveIfError( slash );
+ start += ( slash + KSLStr().Length() );
+ TInt len( GetLen( aPtr, start ) );
+
+ // Len up to second slash ( i.e: rtpmap:97 MP4A-LATM/32000/2 )
+ slash = aPtr.Mid( start, len ).Find( KSLStr );
+ len = ( slash != KErrNotFound )? slash: len;
+ return StrToUint( aPtr.Mid( start, len ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::GetControlL()
+// Checks if a=control line specifies a control for media.
+// -----------------------------------------------------------------------------
+//
+void CDvrSdpParser::GetControlL( const TDesC8& aMediaPtr, HBufC8*& aControlAddr )
+ {
+ delete aControlAddr; aControlAddr = NULL;
+ HBufC8* control = GetStringL( aMediaPtr, KKeyControl );
+ if ( control )
+ {
+ CleanupStack::PushL( control );
+ if ( control->Des().FindC( KCRSDPRtspUriBegin ) == KErrNotFound )
+ {
+ // relative url
+ if ( iBaseUrl )
+ {
+ aControlAddr = HBufC8::NewL( iBaseUrl->Des().Length() +
+ control->Des().Length() +
+ KSLStr().Length() );
+ aControlAddr->Des().Append ( iBaseUrl->Des() );
+ aControlAddr->Des().Append ( KSLStr ) ;
+ aControlAddr->Des().Append ( control->Des() );
+ }
+ }
+ else
+ {
+ // absolute url
+ aControlAddr = control->Des().AllocL();
+ }
+
+ CleanupStack::PopAndDestroy( control );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::CheckForMulticast()
+// Checks if c= line specifies a multicast addr
+// -----------------------------------------------------------------------------
+//
+void CDvrSdpParser::CheckForMulticast( const TDesC8& aLine )
+ {
+ TInetAddr controladdr;
+ TName addr( KNullDesC );
+ addr.Copy( aLine );
+ TInt err( controladdr.Input( addr ) );
+ if ( err != KErrNone )
+ {
+ LOG1( "CDvrSdpParser: invalid control address in SDP connection line '%S'", &addr );
+ }
+ else
+ {
+ // just do check for multicast, actual address is taken from SETUP response
+ iIsMulticast = controladdr.IsMulticast();
+
+#if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
+ /* Commented out, for some reason can crash with RTP playback in debug.
+ if ( iIsMulticast )
+ {
+ LOG1( "CDvrSdpParser: detected MULTICAST (%S) control address in SDP", &addr );
+ }
+ else
+ {
+ LOG1( "CDvrSdpParser: detected unicast (%S) control address in SDP", &addr );
+ }
+ */
+#endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::FindAttributesL
+//
+// -----------------------------------------------------------------------------
+//
+void CDvrSdpParser::FindAttributesL(
+ const TDesC8& aSdpSection,
+ RArray<TPtrC8>& aAttributeList )
+ {
+ TInt last( 0 );
+ TInt start( KErrNotFound );
+ do
+ {
+ // Rest of the SDP section
+ TPtrC8 rest( aSdpSection.Mid( last ) );
+ start = rest.Find( KKeyAttribute );
+ if ( start > KErrNotFound )
+ {
+ last += start;
+ TInt len( GetLen( rest, start, ETrue ) );
+ if ( len > 0 )
+ {
+ // Add other than control attribute
+ if ( rest.Mid( start, len ).Find( KKeyControl ) == KErrNotFound )
+ {
+ TPtrC8 ptr( rest.Mid( start, len ) );
+ User::LeaveIfError( aAttributeList.Append( ptr ) );
+ }
+
+ last += len;
+ }
+ }
+ }
+ while( start > KErrNotFound );
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::FindDataStreamsL
+//
+// -----------------------------------------------------------------------------
+//
+void CDvrSdpParser::FindDataStreamsL(
+ const TDesC8& aSdpSection,
+ RArray<TPtrC8>& aStreamsList )
+ {
+ TInt last( 0 );
+ TInt start( KErrNotFound );
+ do
+ {
+ // Rest of the SDP block
+ TPtrC8 rest( aSdpSection.Mid( last ) );
+ start = rest.Find( KKeyDataStream );
+ if ( start > KErrNotFound )
+ {
+ last += start;
+ TInt len( GetLen( rest, start, ETrue ) );
+ if ( len > 0 )
+ {
+ TPtrC8 ptr( rest.Mid( start, len ) );
+ User::LeaveIfError( aStreamsList.Append( ptr ) );
+ last += len;
+ }
+ }
+ }
+ while( start > KErrNotFound );
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::GetIntL
+//
+// -----------------------------------------------------------------------------
+//
+TInt CDvrSdpParser::GetIntL( const TDesC8& aPtr, const TDesC8& aKeyword )
+ {
+ TInt ret( KErrNotFound );
+ HBufC8* buf = GetStringL( aPtr, aKeyword );
+ if ( buf )
+ {
+ ret = StrToUint( buf->Des() );
+ delete buf;
+ }
+
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::GetStringL
+//
+// -----------------------------------------------------------------------------
+//
+HBufC8* CDvrSdpParser::GetStringL( const TDesC8& aPtr, const TDesC8& aKeyword )
+ {
+ const TInt start( FindStart( aPtr, aKeyword ) );
+ const TInt len( GetLen( aPtr, start ) );
+
+ HBufC8* buf = NULL;
+ if ( start > KErrNotFound && len > 0 && ( start + len ) <= aPtr.Length() )
+ {
+ buf = aPtr.Mid( start, len ).AllocL();
+ }
+
+ return buf;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::FindStart
+//
+// -----------------------------------------------------------------------------
+//
+TInt CDvrSdpParser::FindStart( const TDesC8& aPtr, const TDesC8& aKeyword )
+ {
+ TInt start( aPtr.Find( aKeyword ) );
+
+ if ( start > KErrNotFound )
+ {
+ start += aKeyword.Length();
+ }
+
+ return start;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::GetLen
+//
+// -----------------------------------------------------------------------------
+//
+TInt CDvrSdpParser::GetLen(
+ const TDesC8& aPtr,
+ const TInt aStart,
+ const TBool aIgnoreSpace )
+ {
+ if ( aStart > KErrNotFound && aStart < aPtr.Length() )
+ {
+ // Find next LF, CR or CRLF combination
+ TInt len1( MinNonError( aPtr.Mid( aStart ).Find( KLFStr ),
+ aPtr.Mid( aStart ).Find( KCRStr ) ) );
+ // Find space
+ TInt len2( ( aIgnoreSpace )? KErrNotFound:
+ aPtr.Mid( aStart ).Find( KSPStr ) );
+
+ if ( len1 == KErrNotFound && len2 == KErrNotFound )
+ {
+ // Rest of the buffer
+ return ( aPtr.Length() - aStart );
+ }
+ else
+ {
+ // CRLF or space
+ return MinNonError( len1, len2 );
+ }
+ }
+
+ return KErrNotFound;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::MinNonError
+//
+// -----------------------------------------------------------------------------
+//
+TInt CDvrSdpParser::MinNonError( const TInt aValue1, const TInt aValue2 )
+ {
+ if ( aValue1 > KErrNotFound && aValue2 > KErrNotFound )
+ {
+ return Min( aValue1, aValue2 );
+ }
+
+ return ( ( aValue1 > KErrNotFound )? aValue1:
+ ( aValue2 > KErrNotFound )? aValue2: KErrNotFound );
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::StrToUint
+// Convert string to integer.
+// -----------------------------------------------------------------------------
+//
+TUint CDvrSdpParser::StrToUint( const TDesC8& aString )
+ {
+ TLex8 templex;
+ templex.Assign( aString );
+ TUint ret( KMaxTUint );
+ templex.Val( ret );
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CDvrSdpParser::DeleteVariables
+//
+// -----------------------------------------------------------------------------
+//
+void CDvrSdpParser::DeleteVariables( void )
+ {
+ delete iSdp; iSdp = NULL;
+ delete iCommonIp; iCommonIp = NULL;
+ iMediaBuf.Reset();
+ iSessionAttributes.Reset();
+ iAudioAttributes.Reset();
+ iVideoAttributes.Reset();
+ iDataStreams.Reset();
+ delete iAudioControlAddr; iAudioControlAddr = NULL;
+ delete iVideoControlAddr; iVideoControlAddr = NULL;
+ delete iAudioIpAddr; iAudioIpAddr = NULL;
+ delete iVideoIpAddr; iVideoIpAddr = NULL;
+ }
+
+// End of File