diff -r 826cea16efd9 -r 13a33d82ad98 dvrengine/CommonRecordingEngine/DvrSdpParser/src/CDvrSdpParser.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dvrengine/CommonRecordingEngine/DvrSdpParser/src/CDvrSdpParser.cpp Wed Sep 01 12:20:37 2010 +0100 @@ -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 +#include +#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& CDvrSdpParser::SessionAttributes( void ) + { + return iSessionAttributes; + } + +// ----------------------------------------------------------------------------- +// CDvrSdpParser::AudioAttributes +// +// ----------------------------------------------------------------------------- +// +EXPORT_C RArray& CDvrSdpParser::AudioAttributes( void ) + { + return iAudioAttributes; + } + +// ----------------------------------------------------------------------------- +// CDvrSdpParser::VideoAttributes +// +// ----------------------------------------------------------------------------- +// +EXPORT_C RArray& CDvrSdpParser::VideoAttributes( void ) + { + return iVideoAttributes; + } + +// ----------------------------------------------------------------------------- +// CDvrSdpParser::DataStreams +// +// ----------------------------------------------------------------------------- +// +EXPORT_C RArray& 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 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& 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& 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& 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 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& 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& 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