multimediacommsengine/mmcesrv/mmcemediamanager/src/mcevideosdpcodec.cpp
changeset 0 1bce908db942
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/multimediacommsengine/mmcesrv/mmcemediamanager/src/mcevideosdpcodec.cpp	Tue Feb 02 01:04:58 2010 +0200
@@ -0,0 +1,609 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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:    
+*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <e32base.h>
+#include <e32std.h>
+#include <e32def.h>
+#include <stringpool.h>
+#include <sdpdocument.h>
+#include <sdpcodecstringconstants.h>
+#include <sdpcodecstringpool.h>
+#include <sdpmediafield.h>
+#include <sdpattributefield.h>
+#include <sdprtpmapvalue.h>
+#include <sdpfmtattributefield.h>
+#include <sdporiginfield.h>
+
+#include "mcemediadefs.h"
+#include "mcevideosdpcodec.h"
+#include "mcevideostream.h"
+#include "mcecomsession.h"
+#include "mcecomvideostream.h"
+#include "mcecomvideocodec.h"
+#include "mceh263codec.h"
+#include "mcecomfactory.h"
+#include "mcecomrtpsource.h"
+#include "mcecomrtpsink.h"
+#include "mcecomcamerasource.h"
+#include "mcecomdisplaysink.h"
+#include "mcemmlogs.h"
+#include "mcesip.h"
+
+
+
+const TInt KFrameSizeLength = KMceSdpNumericAttributeLength * 3;
+
+    
+// ================= MEMBER FUNCTIONS =======================
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::NewL
+// -----------------------------------------------------------------------------
+//
+CMceVideoSdpCodec* CMceVideoSdpCodec::NewL()
+    {
+    RStringF video = MCE_SDP_STRING_VIDEOL();
+        
+    CMceVideoSdpCodec* self = new (ELeave) CMceVideoSdpCodec( video );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::CMceVideoSdpCodec
+// -----------------------------------------------------------------------------
+//
+CMceVideoSdpCodec::CMceVideoSdpCodec( RStringF aMedia )
+    : CMceMediaSdpCodec( aMedia )
+    {
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::ConstructL
+// -----------------------------------------------------------------------------
+//    
+void CMceVideoSdpCodec::ConstructL()
+    {
+    CMceMediaSdpCodec::ConstructL();
+    
+    iFrameSizeAttr = iStringPool.OpenFStringL( KMceVideoFrameSizeAttribute );
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::~CMceVideoSdpCodec
+// -----------------------------------------------------------------------------
+//
+CMceVideoSdpCodec::~CMceVideoSdpCodec()
+    {
+    iFrameSizeAttr.Close();
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::Encodes
+// -----------------------------------------------------------------------------
+//
+TBool CMceVideoSdpCodec::Encodes( const CMceComMediaStream& aStream ) const
+    {
+    return aStream.iStreamType != CMceComMediaStream::ELocalStream &&
+           aStream.iType == KMceVideo;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::CodecsL
+// -----------------------------------------------------------------------------
+//
+const RPointerArray<CMceComCodec>& CMceVideoSdpCodec::CodecsL( CMceComMediaStream& aStream ) const
+    {
+    __ASSERT_ALWAYS( aStream.iType == KMceVideo, User::Leave( KErrArgument ) );
+    MCE_DEFINE_VIDEO( stream, aStream );
+
+	return reinterpret_cast< const RPointerArray< CMceComCodec >& >( stream.Codecs() );
+    }
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::EncodeRtpmapAttributeLC
+// -----------------------------------------------------------------------------
+//
+CSdpFmtAttributeField* CMceVideoSdpCodec::EncodeRtpmapAttributeLC( CMceComCodec& aCodec ) const
+    {
+    MCEMM_DEBUG("CMceVideoSdpCodec::EncodeRtpmapAttributeLC(), Entry ");
+    
+    MCE_DEFINE_VIDEO_CODEC( codec, aCodec );
+    CSdpFmtAttributeField* rtpmapAttribute = NULL;
+    
+    TUint payloadType = codec.iPayloadType;
+    // Get the encoding name
+    TPtrC8 codecName = codec.iSdpName; 
+    TUint clockRate = codec.iClockRate;      
+        
+    // create rtpmap field for current codec
+    rtpmapAttribute = EncodeRtpMapFieldsL( payloadType, 
+                                           codecName, 
+                                           clockRate,
+                                           KMceSdpOptionalEncodingParam );
+    
+    
+    CleanupStack::PushL( rtpmapAttribute );
+    
+    MCEMM_DEBUG_SVALUE("encoded rtpmap", rtpmapAttribute->Value() );
+    
+    MCEMM_DEBUG("CMceVideoSdpCodec::EncodeRtpmapAttributeLC(), Exit ");
+    return rtpmapAttribute;
+    
+    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::EncodeMediaAttributesL
+// -----------------------------------------------------------------------------
+//
+void CMceVideoSdpCodec::EncodeMediaAttributesL( CMceComCodec& aCodec, 
+                                                CSdpMediaField& aMediaLine, 
+                                                CSdpFmtAttributeField& aRtpmap ) const
+    {
+    MCEMM_DEBUG("CMceVideoSdpCodec::EncodeMediaAttributesL(), Entry ");
+    MCE_DEFINE_VIDEO_CODEC( codec, aCodec );
+    
+    EncodeFrameRateAttributeL( codec, aMediaLine, aRtpmap );
+    EncodeFrameSizeAttributeL( codec, aMediaLine, aRtpmap );
+        
+    MCEMM_DEBUG("CMceVideoSdpCodec::EncodeMediaAttributesL(), Exit ");
+    }
+    
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::DecodeMediaAttributesL  
+// -----------------------------------------------------------------------------
+//
+
+void CMceVideoSdpCodec::DecodeMediaAttributesL( 
+                                    CSdpMediaField& aMediaLine,
+                                    CMceComCodec& aCodec,
+                                    CSdpFmtAttributeField& /*aRtpmap*/ ) const
+
+                                                
+    {
+    MCEMM_DEBUG("CMceVideoSdpCodec::DecodeMediaAttributesL(), Entry ");
+    MCE_DEFINE_VIDEO_CODEC( codec, aCodec );
+        
+    RPointerArray<CSdpAttributeField>& attrfields = aMediaLine.AttributeFields();
+    
+    for ( TInt index = 0; index < attrfields.Count(); index++ )
+        {
+        CSdpAttributeField* attrfield = attrfields[ index ];
+        RStringF attribute = attrfield->Attribute();
+        
+        if ( attribute == SDP_STRING( SdpCodecStringConstants::EAttributeFramerate ) )
+            {
+            const TDesC8& framerate = attrfield->Value();
+            TReal frameRateVal = ConvertDesToRealL( framerate );
+            MCEMM_DEBUG_SVALUE("decoded framerate", framerate );
+            
+            // Do not update frame rate for receive stream, but is anyway good
+            // to know at media side what framerate sender is about to use.
+            TReal& updateFrameRate = codec.Stream()->SendStream() ? 
+                    codec.iFrameRate : codec.iReceiveFrameRate;
+            
+            updateFrameRate = frameRateVal;
+            }
+        else if ( codec.Stream()->SendStream() && attribute == iFrameSizeAttr )
+            {
+            const TDesC8& framesize = attrfield->Value();
+            
+            TInt ind1 = framesize.Locate( KMceSipBlank );
+            TInt ind2 = framesize.Locate( KMceSipDash );
+            TInt widthStartPos( ind1 + 1 );
+            TInt heightStartPos( ind2 + 1 );  
+
+            if ( ind1 != KErrNotFound && 
+                 ind2 != KErrNotFound && 
+                 widthStartPos < ind2 && 
+                 heightStartPos < framesize.Length() &&
+                 ConvertDesToUintL( framesize.Mid( 0, ind1 ) ) == 
+                    codec.iPayloadType )
+                {
+                codec.iResolutionWidth = 
+                    ConvertDesToIntL( 
+                        framesize.Mid( widthStartPos, ind2 - widthStartPos ) );
+                
+                codec.iResolutionHeight = 
+                    ConvertDesToIntL( framesize.Mid( heightStartPos ) );
+                
+                MCEMM_DEBUG_SVALUE("decoded framesize", framesize );
+            
+                }
+            }
+        else
+            {
+            // NOP
+            }
+        }
+        
+    MCEMM_DEBUG("CMceVideoSdpCodec::DecodeMediaAttributesL(), Exit ");    
+    
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::DecodeSessionMediaAttributesL
+// -----------------------------------------------------------------------------
+//
+void CMceVideoSdpCodec::DecodeSessionMediaAttributesL( CMceComMediaStream& aStream, 
+                                                       CSdpDocument& aSdpDocument ) const
+    {   
+    MCEMM_DEBUG("CMceVideoSdpCodec::DecodeSessionMediaAttributesL(), Entry ");
+    MCE_DEFINE_VIDEO( stream, aStream );
+    
+    RPointerArray<CSdpAttributeField>& attrfields = 
+                                            aSdpDocument.AttributeFields();
+
+    const RPointerArray<CMceComVideoCodec>& codecs = stream.Codecs();
+    // look for the framerate attribute, go through all
+    // attribute fields and apply to all codecs in the stream if found
+    for ( TInt index = 0; index < attrfields.Count(); index++ )
+        {
+        CSdpAttributeField* attrfield = attrfields[ index ];
+        RStringF attribute = attrfield->Attribute();
+        if ( attribute == SDP_STRING( SdpCodecStringConstants::EAttributeFramerate ) )
+            {
+            TReal frameRate = ConvertDesToRealL( attrfield->Value() );
+            MCEMM_DEBUG_SVALUE("decoded framerate", attrfield->Value() );
+            for ( TInt j = 0; j < codecs.Count(); j++ )
+                {
+                TReal& updateFrameRate = stream.SendStream() ? 
+                    codecs[ j ]->iFrameRate : codecs[ j ]->iReceiveFrameRate;
+                updateFrameRate = frameRate;
+                }
+            }
+        }
+        
+    MCEMM_DEBUG("CMceVideoSdpCodec::ParseSessionFrameRateAttributeL(), Exit ");
+    
+    }
+    
+    
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::EncodeFrameRateAttributeL
+// -----------------------------------------------------------------------------
+//
+void CMceVideoSdpCodec::EncodeFrameRateAttributeL( 
+    CMceComVideoCodec& aCodec,
+    CSdpMediaField& aMedia,
+    CSdpFmtAttributeField& aFmtpline ) const
+    {   
+    MCEMM_DEBUG("CMceVideoSdpCodec::EncodeFrameRateAttributeL(), Entry ");
+    
+    RStringF attributeFrameRate = 
+        SDP_STRING( SdpCodecStringConstants::EAttributeFramerate );
+   
+    HBufC8* frameRate = ConvertTRealToDesLC( aCodec.iFrameRate );
+
+    MCEMM_DEBUG_SVALUE("encoded framerate", *frameRate );
+    
+    CSdpAttributeField* frameRateLine = 
+        CSdpAttributeField::NewL( attributeFrameRate, *frameRate );
+    CleanupStack::PopAndDestroy( frameRate );
+    CleanupStack::PushL( frameRateLine ); 
+    aMedia.AttributeFields().AppendL( frameRateLine );
+    CleanupStack::Pop( frameRateLine ); 
+    
+    
+    // This creates dependency between framerate and payload type
+    frameRateLine->AssignTo( aFmtpline );
+
+    MCEMM_DEBUG("CMceVideoSdpCodec::EncodeFrameRateAttributeL(), Exit ");
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::EncodeFrameSizeAttributeL
+// -----------------------------------------------------------------------------
+//
+void CMceVideoSdpCodec::EncodeFrameSizeAttributeL( 
+    CMceComVideoCodec& aCodec,
+    CSdpMediaField& aMedia,
+    CSdpFmtAttributeField& aFmtpline ) const
+    {   
+    MCEMM_DEBUG("CMceVideoSdpCodec::EncodeFrameSizeAttributeL(), Entry ");
+
+    HBufC8* frameSize = 
+        HBufC8::NewLC( KMceVideoFrameSizeFormat().Length() + 
+                       KFrameSizeLength );
+    
+    TPtr8 ptrFrameSize( frameSize->Des() );
+    ptrFrameSize.AppendFormat( KMceVideoFrameSizeFormat, 
+                               aCodec.iPayloadType, 
+                               aCodec.iResolutionWidth, 
+                               aCodec.iResolutionHeight );
+                                    
+    MCEMM_DEBUG_SVALUE("encoded framesize", ptrFrameSize );
+    
+    CSdpAttributeField* frameSizeLine = 
+        CSdpAttributeField::NewL( iFrameSizeAttr, *frameSize );
+    CleanupStack::PopAndDestroy( frameSize );
+    CleanupStack::PushL( frameSizeLine ); 
+    aMedia.AttributeFields().AppendL( frameSizeLine );
+    CleanupStack::Pop( frameSizeLine ); 
+
+    frameSizeLine->AssignTo( aFmtpline );
+
+    MCEMM_DEBUG("CMceVideoSdpCodec::EncodeFrameSizeAttributeL(), Exit ");
+    }
+    
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::CreateStreamLC
+// -----------------------------------------------------------------------------
+//
+CMceComMediaStream* CMceVideoSdpCodec::CreateStreamLC( TInt aType ) const
+    {
+    MCEMM_DEBUG("CMceVideoSdpCodec::CreateStreamLC(), Entry ");
+    CMceComVideoStream* videostream = NULL;
+                
+    if( aType == SdpCodecStringConstants::EAttributeSendonly )
+        {
+        // downlink
+        MCEMM_DEBUG( "create downlink" );
+        videostream = CreateDownlinkStreamL();
+        }
+    else if( aType == SdpCodecStringConstants::EAttributeRecvonly )        
+        {
+        // uplink 
+        MCEMM_DEBUG( "create uplink" );
+        videostream = CreateUplinkStreamL();
+        
+        }
+    else
+        {
+        // sendrcv 
+        // create two way stream
+        // create downlink
+        MCEMM_DEBUG( "create two-way stream");
+        videostream = CreateDownlinkStreamL();
+        CleanupStack::PushL( videostream );
+        // create bounded uplink
+        CMceComVideoStream *boundUplink = CreateUplinkStreamL();
+        CleanupStack::PushL( boundUplink );
+        videostream->BindL( boundUplink );
+        CleanupStack::Pop( boundUplink ); 
+        CleanupStack::Pop( videostream );
+        }
+    
+    CleanupStack::PushL( videostream );
+    
+    
+    MCEMM_DEBUG("CMceVideoSdpCodec::CreateStreamLC(), Exit ");
+    return videostream;
+    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::UpdateStreamL
+// -----------------------------------------------------------------------------
+//
+void CMceVideoSdpCodec::UpdateStreamL( CMceComMediaStream& aStream, TInt aDirection ) const
+    {
+    
+    MCEMM_DEBUG("CMceVideoSdpCodec::UpdateStreamL(), Entry ");
+    MCE_DEFINE_VIDEO( stream, aStream );
+
+    CMceComVideoStream* videostream = NULL;
+    TInt streamType = stream.SdpStreamType();
+
+    if ( aDirection != SdpCodecStringConstants::EAttributeInactive )
+        {
+        switch( streamType )
+            {
+            case SdpCodecStringConstants::EAttributeRecvonly:
+                {
+                //if direction is changed
+                if ( aDirection != SdpCodecStringConstants::EAttributeSendonly )
+                    {
+                    MCEMM_DEBUG("update from recvonly to send");
+                    MCEMM_DEBUG("create uplink");
+                    videostream = CreateUplinkStreamL();
+                    }
+                break;
+                }
+            case SdpCodecStringConstants::EAttributeSendonly:
+                {
+                //if direction is changed
+                if ( aDirection != SdpCodecStringConstants::EAttributeRecvonly )
+                    {
+                    MCEMM_DEBUG("update from sendonly to recv");
+                    MCEMM_DEBUG("create downlink");
+                    videostream = CreateDownlinkStreamL();
+                    }
+                break;
+                }
+            case SdpCodecStringConstants::EAttributeSendrecv:
+            default:
+                {
+                break;
+                }
+            }
+        }
+        
+    if ( videostream )
+        {
+        CleanupStack::PushL( videostream );
+
+        MCEMM_DEBUG("cloning codecs");
+        
+        for( TInt index = 0; index < stream.CodecCount(); index++ )
+            {
+            CMceComVideoCodec* codec = 
+                static_cast<CMceComVideoCodec*>( stream.CodecL( index )->CloneL() );
+            CleanupStack::PushL( codec );
+            MCEMM_DEBUG_SVALUE("cloned codec", codec->iSdpName );
+            videostream->AddCodecL( codec );
+            CleanupStack::Pop( codec );
+            }
+
+        stream.BindL( videostream );
+        
+        videostream->InitializeL( *aStream.Session() );
+        
+        MCEMM_DEBUG("binded stream created");
+        CleanupStack::Pop( videostream ); 
+
+        
+        }
+    
+    MCEMM_DEBUG("CMceVideoSdpCodec::UpdateStreamL(), Exit ");
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::CreateCodecLC
+// -----------------------------------------------------------------------------
+//
+CMceComCodec* CMceVideoSdpCodec::CreateCodecLC( CSdpFmtAttributeField& aRtpmap ) const
+    {
+    MCEMM_DEBUG("CMceVideoSdpCodec::CreateCodecLC(), Entry ");
+    
+    CMceComVideoCodec* codec = NULL;
+    
+    const TDesC8& payloadType = aRtpmap.Format();
+    const TDesC8& attributeValue = aRtpmap.Value();
+    TSdpRtpmapValue rtpmapValue = TSdpRtpmapValue::DecodeL( attributeValue );
+
+    TPtrC8 codecName = rtpmapValue.iEncName;
+    TPtrC8 clockRate = rtpmapValue.iClockrate;
+    
+    TUint uintValPT = ConvertDesToUintL( payloadType );
+    TUint uintValCR = ConvertDesToUintL( clockRate );
+    
+    if ( uintValPT > KMceMaxPTValue )
+        {
+		MCEMM_DEBUG_DVALUE("CMceVideoSdpCodec::CreateCodecLC(), invalid payloadtype value ", uintValPT )
+		User::Leave( KErrNotSupported );        	
+        }
+    if ( IsSupported( codecName ) )
+        {
+        TMceComVideoCodecFactory factory;
+        codec = factory.CreateLC( codecName );
+        codec->iClockRate = uintValCR;
+        codec->iPayloadType = uintValPT;
+        MCEMM_DEBUG_SVALUE("created codec", codecName );
+        MCEMM_DEBUG_DVALUE("clock rate", uintValCR  )
+        MCEMM_DEBUG_DVALUE("payload", uintValPT  )
+        }
+    else
+        {
+        MCEMM_DEBUG_SVALUE("not supported codec", codecName );
+        }
+        
+    MCEMM_DEBUG("CMceVideoSdpCodec::CreateCodecLC(), Exit ");
+    
+    return codec;
+    
+    }
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::CreateCodecLC
+// -----------------------------------------------------------------------------
+//
+CMceComCodec* CMceVideoSdpCodec::CreateCodecLC( TUint aPayload, 
+                                                CSdpMediaField& /*aMediaLine*/ ) const
+    {
+    MCEMM_DEBUG("CMceVideoSdpCodec::CreateCodecLC( payload ), Entry ");
+    
+    TMceComVideoCodecFactory factory;
+    CMceComVideoCodec* codec = NULL;
+    
+    codec = factory.CreateCodecLC( aPayload );
+    if ( codec && !IsSupported( codec->iSdpName ) )
+        {
+        CleanupStack::PopAndDestroy( codec );
+        codec = NULL;
+        }
+
+    MCEMM_DEBUG("CMceVideoSdpCodec::CreateCodecLC( payload ), Exit ");
+    
+    return codec;
+    }
+
+    
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::CreateUplinkStreamL
+// -----------------------------------------------------------------------------
+//
+CMceComVideoStream* CMceVideoSdpCodec::CreateUplinkStreamL() const
+    {
+    MCEMM_DEBUG("CMceVideoSdpCodec::CreateUplinkStreamL(), Entry ");
+    
+    CMceComVideoStream* videoStream = CMceComVideoStream::NewL();
+    CleanupStack::PushL( videoStream );
+    // uplink           
+    CMceComCameraSource* cameraSource = CMceComCameraSource::NewL();
+    CleanupStack::PushL( cameraSource );
+    cameraSource->InitializeL( 
+                    static_cast<CMceComVideoStream&> ( *videoStream ) );
+    videoStream->SetSourceL( cameraSource );
+    CleanupStack::Pop( cameraSource );
+    CMceComRtpSink* rtpSink = CMceComRtpSink::NewL();
+    CleanupStack::PushL( rtpSink );
+    rtpSink->InitializeL( static_cast<CMceComVideoStream&> ( *videoStream ) );
+    videoStream->AddSinkL( rtpSink );
+    CleanupStack::Pop( rtpSink ); 
+    CleanupStack::Pop( videoStream );
+    
+    MCEMM_DEBUG("CMceVideoSdpCodec::CreateUplinkStreamL(), Exit ");
+    
+    return videoStream;
+    }
+
+// -----------------------------------------------------------------------------
+// CMceVideoSdpCodec::CreateDownlinkStreamL
+// -----------------------------------------------------------------------------
+//
+CMceComVideoStream* CMceVideoSdpCodec::CreateDownlinkStreamL() const
+    {
+    MCEMM_DEBUG("CMceVideoSdpCodec::CreateDownlinkStreamL(), Entry ");
+
+    CMceComVideoStream* videoStream = CMceComVideoStream::NewL();
+    CleanupStack::PushL( videoStream ); 
+    // downlink         
+    CMceComRtpSource* rtpSource = CMceComRtpSource::NewL();
+    CleanupStack::PushL( rtpSource );
+    rtpSource->InitializeL( static_cast<CMceComVideoStream&> ( *videoStream ) );
+    videoStream->SetSourceL( rtpSource );
+    CleanupStack::Pop( rtpSource );
+    CMceComDisplaySink* display = CMceComDisplaySink::NewL();
+    CleanupStack::PushL( display );
+    display->InitializeL( static_cast<CMceComVideoStream&> ( *videoStream ) );
+    videoStream->AddSinkL( display );
+    CleanupStack::Pop( display ); 
+    CleanupStack::Pop( videoStream );
+    
+    MCEMM_DEBUG("CMceVideoSdpCodec::CreateDownlinkStreamL(), Exit ");
+    
+    return videoStream;
+    }
+ 
+