|
1 /* |
|
2 * Copyright (c) 2006 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 "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: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 // USER INCLUDES |
|
21 |
|
22 #include "musengreceivesession.h" |
|
23 #include "musengsessionobserver.h" |
|
24 #include "musengreceivesessionobserver.h" |
|
25 #include "musengmceutils.h" |
|
26 #include "musenglogger.h" |
|
27 #include "mussettings.h" |
|
28 #include "mussipprofilehandler.h" |
|
29 |
|
30 // SYSTEM INCLUDES |
|
31 #include <mcemanager.h> |
|
32 #include <mceinsession.h> |
|
33 #include <mcestreambundle.h> |
|
34 #include <mceaudiostream.h> |
|
35 #include <mcevideostream.h> |
|
36 #include <mcemediasource.h> |
|
37 #include <mcertpsource.h> |
|
38 #include <mcedisplaysink.h> |
|
39 #include <mcespeakersink.h> |
|
40 #include <mceaudiocodec.h> |
|
41 #include <mceavccodec.h> |
|
42 |
|
43 #include <utf.h> |
|
44 |
|
45 |
|
46 const TUint8 KMusEngRtpKeepAliveTimer = 5; // this should be 30 sec, this a temporary fix |
|
47 const TUint8 KMusEngKeepAlivePayloadTypeVideoH263 = 96; |
|
48 const TUint8 KMusEngKeepAlivePayloadTypeAudio = 97; |
|
49 const TUint8 KMusEngKeepAlivePayloadTypeVideoAvc = 98; |
|
50 |
|
51 const TInt KMusEngJitterBufferLength = 51; //Must be bigger than treshold |
|
52 // Using following value increases treshold buffer to 1 second from |
|
53 // default 100 ms |
|
54 const TInt KMusEngJitterBufferTreshold = 50; |
|
55 const TInt KMusEngTresholdToSecondsFactor = 20; |
|
56 const TInt KMusEngOneSecondInMilliSeconds = 1000; |
|
57 // Use inactivity timer value that is a little bigger than treshold in seconds |
|
58 const TUint KMusEngInactivityTimer = KMusEngTresholdToSecondsFactor * |
|
59 KMusEngJitterBufferTreshold + |
|
60 KMusEngOneSecondInMilliSeconds; |
|
61 |
|
62 _LIT8( KMusEngSwisIdentifier, "Require: precondition" ); |
|
63 _LIT8( KMusEngAssertedIdentity, "P-Asserted-Identity" ); |
|
64 _LIT8( KMusEngBiggerSign, ">" ); |
|
65 |
|
66 const TInt KMusEngSipReasonCodeBusyHere = 486; |
|
67 _LIT8( KMusEngSipReasonPhraseBusy, "Busy" ); |
|
68 |
|
69 // ----------------------------------------------------------------------------- |
|
70 // |
|
71 // ----------------------------------------------------------------------------- |
|
72 // |
|
73 CMusEngReceiveSession::~CMusEngReceiveSession() |
|
74 { |
|
75 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::~CMusEngReceiveSession()" ) |
|
76 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::~CMusEngReceiveSession()" ) |
|
77 } |
|
78 |
|
79 |
|
80 // ----------------------------------------------------------------------------- |
|
81 // |
|
82 // ----------------------------------------------------------------------------- |
|
83 // |
|
84 EXPORT_C CMusEngReceiveSession* CMusEngReceiveSession::NewL( |
|
85 const TRect& aRect, |
|
86 MMusEngSessionObserver& aSessionObserver, |
|
87 MMusEngReceiveSessionObserver& aReceiveSessionObserver ) |
|
88 { |
|
89 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::NewL(...)" ) |
|
90 |
|
91 CMusEngReceiveSession* self = new( ELeave ) CMusEngReceiveSession( |
|
92 aSessionObserver, |
|
93 aReceiveSessionObserver, |
|
94 aRect ); |
|
95 CleanupStack::PushL( self ); |
|
96 self->ConstructL(); |
|
97 CleanupStack::Pop( self ); |
|
98 |
|
99 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::NewL(...)" ) |
|
100 return self; |
|
101 } |
|
102 |
|
103 |
|
104 // ----------------------------------------------------------------------------- |
|
105 // |
|
106 // ----------------------------------------------------------------------------- |
|
107 // |
|
108 EXPORT_C void CMusEngReceiveSession::AcceptInvitationL( |
|
109 const TBool& aAccept ) |
|
110 { |
|
111 MUS_LOG1( "mus: [ENGINE] -> CMusEngReceiveSession::\ |
|
112 AcceptInvitationL( %d )", aAccept ) |
|
113 |
|
114 __ASSERT_ALWAYS( iSession && iSession->State() == CMceSession::EProceeding, |
|
115 User::Leave( KErrNotReady ) ); |
|
116 |
|
117 // Accept or reject |
|
118 if ( aAccept ) |
|
119 { |
|
120 InSession()->AcceptL(); |
|
121 } |
|
122 else |
|
123 { |
|
124 if ( iOperatorVariant ) |
|
125 { |
|
126 // In operator variant, session is rejected with 486 instead of 603. |
|
127 // Also the reason phrase is supposed to be "Busy". |
|
128 InSession()->RejectL( KMusEngSipReasonPhraseBusy(), |
|
129 KMusEngSipReasonCodeBusyHere ); |
|
130 } |
|
131 else |
|
132 { |
|
133 InSession()->RejectL(); |
|
134 } |
|
135 } |
|
136 |
|
137 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::\ |
|
138 AcceptInvitationL(...)" ) |
|
139 } |
|
140 |
|
141 |
|
142 // ----------------------------------------------------------------------------- |
|
143 // When reserving resources is ready, this function reports observer about |
|
144 // incoming session and signals this also to other end terminal ( 180 ringing ). |
|
145 // ----------------------------------------------------------------------------- |
|
146 // |
|
147 void CMusEngReceiveSession::HandleSessionStateChanged( |
|
148 CMceSession& aSession, |
|
149 TInt aStatusCode, |
|
150 const TDesC8& aReasonPhrase ) |
|
151 { |
|
152 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::\ |
|
153 HandleSessionStateChanged()" ) |
|
154 |
|
155 MUS_ENG_LOG_SESSION_STATE_AND_STATUS( aSession, aStatusCode, aReasonPhrase ) |
|
156 |
|
157 if ( iSession && iSession == &aSession && |
|
158 aSession.State() == CMceSession::EProceeding ) |
|
159 { |
|
160 // Indicates that resource reservation is ready, user can be notified |
|
161 // if we do not have to wait for PRACK |
|
162 |
|
163 if ( !iRingLCalled ) |
|
164 { |
|
165 // Notify other end terminal |
|
166 TRAP_IGNORE( InSession()->RingL() ) |
|
167 iRingLCalled = ETrue; |
|
168 |
|
169 // Notify user |
|
170 TBuf16<KMaxUriLength> originator; |
|
171 CnvUtfConverter::ConvertToUnicodeFromUtf8( originator, |
|
172 iSession->Originator() ); |
|
173 |
|
174 TBuf16<KMaxUriLength> identity; |
|
175 CnvUtfConverter::ConvertToUnicodeFromUtf8( identity, |
|
176 iIdentity ); |
|
177 iReceiveSessionObserver.IncomingSession( originator, identity ); |
|
178 } |
|
179 else |
|
180 { |
|
181 MUS_LOG( "mus: [ENGINE] User and remote end already notified." ) |
|
182 } |
|
183 |
|
184 } |
|
185 else |
|
186 { |
|
187 // Forward all other session state changes to base class |
|
188 CMusEngMceSession::HandleSessionStateChanged( aSession, |
|
189 aStatusCode, |
|
190 aReasonPhrase ); |
|
191 } |
|
192 |
|
193 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::\ |
|
194 HandleSessionStateChanged()" ) |
|
195 } |
|
196 |
|
197 |
|
198 // ----------------------------------------------------------------------------- |
|
199 // Sets keepalive timer for video and calls base class variant of this function |
|
200 // ----------------------------------------------------------------------------- |
|
201 // |
|
202 void CMusEngReceiveSession::AdjustVideoCodecL( CMceVideoCodec& aVideoCodec ) |
|
203 { |
|
204 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::AdjustVideoCodecL()" ) |
|
205 |
|
206 CMusEngMceSession::AdjustVideoCodecL( aVideoCodec ); |
|
207 |
|
208 aVideoCodec.SetKeepAliveTimerL( KMusEngRtpKeepAliveTimer ); |
|
209 if ( aVideoCodec.SdpName() == KMceSDPNameH263() || |
|
210 aVideoCodec.SdpName() == KMceSDPNameH2632000() ) |
|
211 { |
|
212 aVideoCodec.SetKeepAlivePayloadTypeL( KMusEngKeepAlivePayloadTypeVideoH263 ); |
|
213 } |
|
214 else if ( aVideoCodec.SdpName() == KMceSDPNameH264() ) |
|
215 { |
|
216 aVideoCodec.SetKeepAlivePayloadTypeL( KMusEngKeepAlivePayloadTypeVideoAvc ); |
|
217 } |
|
218 else |
|
219 { |
|
220 // NOP |
|
221 } |
|
222 |
|
223 aVideoCodec.SetKeepAliveDataL( KNullDesC8() ); |
|
224 |
|
225 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::AdjustVideoCodecL()" ) |
|
226 } |
|
227 |
|
228 |
|
229 // ----------------------------------------------------------------------------- |
|
230 // Sets keepalive timer for audio and calls base class variant of this function |
|
231 // ----------------------------------------------------------------------------- |
|
232 // |
|
233 void CMusEngReceiveSession::AdjustAudioCodecL( CMceAudioCodec& aAudioCodec ) |
|
234 { |
|
235 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::AdjustAudioCodecL()" ) |
|
236 |
|
237 CMusEngMceSession::AdjustAudioCodecL( aAudioCodec ); |
|
238 |
|
239 aAudioCodec.SetKeepAliveTimerL( KMusEngRtpKeepAliveTimer ); |
|
240 aAudioCodec.SetKeepAlivePayloadTypeL( KMusEngKeepAlivePayloadTypeAudio ); |
|
241 aAudioCodec.SetKeepAliveDataL( KNullDesC8() ); |
|
242 |
|
243 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::AdjustAudioCodecL()" ) |
|
244 } |
|
245 |
|
246 |
|
247 // ----------------------------------------------------------------------------- |
|
248 // |
|
249 // ----------------------------------------------------------------------------- |
|
250 // |
|
251 void CMusEngReceiveSession::DoCodecSelectionL( CMceVideoStream& aVideoStream ) |
|
252 { |
|
253 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::DoCodecSelectionL()" ) |
|
254 |
|
255 const RPointerArray<CMceVideoCodec>& codecs = aVideoStream.Codecs(); |
|
256 |
|
257 const CMceVideoCodec* avcSingleNal = NULL; |
|
258 const CMceVideoCodec* avcNonInterleaved = NULL; |
|
259 |
|
260 for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex ) |
|
261 { |
|
262 if ( codecs[codecIndex]->SdpName() == KMceSDPNameH264() && |
|
263 !MultimediaSharingSettings::IsAvcDisabled() ) |
|
264 { |
|
265 if ( codecs[codecIndex]->CodecMode() == KMceAvcModeSingleNal ) |
|
266 { |
|
267 // Store a pointer to the Single NAL codec with best bitrate |
|
268 if ( !avcSingleNal || |
|
269 ( avcSingleNal && codecs[codecIndex]->MaxBitRate() > |
|
270 avcSingleNal->MaxBitRate() ) ) |
|
271 { |
|
272 avcSingleNal = codecs[codecIndex]; |
|
273 } |
|
274 } |
|
275 else if ( codecs[codecIndex]->CodecMode() == |
|
276 KMceAvcModeNonInterleaved ) |
|
277 { |
|
278 // Store a pointer to the Non-Interleaved codec with best bitrate |
|
279 if ( !avcNonInterleaved || |
|
280 ( avcNonInterleaved && codecs[codecIndex]->MaxBitRate() > |
|
281 avcNonInterleaved->MaxBitRate() ) ) |
|
282 { |
|
283 avcNonInterleaved = codecs[codecIndex]; |
|
284 } |
|
285 } |
|
286 else |
|
287 { |
|
288 // NOP, we do not care about interleaved AVC |
|
289 } |
|
290 } |
|
291 } |
|
292 |
|
293 const CMceVideoCodec* selectedCodec = NULL; |
|
294 |
|
295 if ( avcNonInterleaved ) |
|
296 { |
|
297 selectedCodec = avcNonInterleaved; |
|
298 } |
|
299 else |
|
300 { |
|
301 selectedCodec = avcSingleNal; |
|
302 } |
|
303 |
|
304 if ( selectedCodec ) |
|
305 { |
|
306 // Remove all other codecs |
|
307 for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex ) |
|
308 { |
|
309 if ( codecs[codecIndex] != selectedCodec ) |
|
310 { |
|
311 aVideoStream.RemoveCodecL( *codecs[codecIndex] ); |
|
312 // Since succesfull removal of a codec has decreased the amount |
|
313 // of codecs in array by one, we have to reset the index |
|
314 codecIndex = 0; |
|
315 } |
|
316 } |
|
317 } |
|
318 else |
|
319 { |
|
320 // Let the base class do H.263 selection |
|
321 CMusEngMceSession::DoCodecSelectionL( aVideoStream ); |
|
322 } |
|
323 |
|
324 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::DoCodecSelectionL()" ) |
|
325 } |
|
326 |
|
327 |
|
328 // ----------------------------------------------------------------------------- |
|
329 // If incoming session does not have valid structure and cannot be reconstructed |
|
330 // as such, session is rejected automatically. |
|
331 // ----------------------------------------------------------------------------- |
|
332 // |
|
333 void CMusEngReceiveSession::IncomingSession( |
|
334 CMceInSession* aSession, |
|
335 TMceTransactionDataContainer* aContainer ) |
|
336 { |
|
337 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::IncomingSession(...)" ) |
|
338 |
|
339 if ( !aContainer || |
|
340 ( iSession && |
|
341 iSession->State() != CMceSession::ETerminated ) ) |
|
342 { |
|
343 // We already have one session ongoing, or do not have container. |
|
344 // Reject new session. |
|
345 Reject( *aSession ); |
|
346 delete aSession; |
|
347 aSession = NULL; |
|
348 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::IncomingSession( \ |
|
349 session already exists. New session rejected and deleted. )" ) |
|
350 return; |
|
351 } |
|
352 |
|
353 iReceiveSessionObserver.IncomingSessionPreNotification(); |
|
354 |
|
355 delete iSession; // possibly existing terminated session |
|
356 iSession = aSession; |
|
357 |
|
358 if ( iOperatorVariant ) |
|
359 { |
|
360 ParseAssertedIdentity( aContainer ); |
|
361 } |
|
362 |
|
363 // Reset variable defined for preparing for multiple state changes to |
|
364 // EProceeding. This might happen if we set 100rel to be required. |
|
365 iRingLCalled = EFalse; |
|
366 |
|
367 // If preparing fails, session setup with VS2.2 will fail later |
|
368 TRAP_IGNORE( PrepareToRequire100RelL( aContainer ) ) |
|
369 |
|
370 TRAPD( error, CompleteSessionStructureL() ); |
|
371 |
|
372 if ( error != KErrNone ) |
|
373 { |
|
374 Reject( *InSession() ); |
|
375 } |
|
376 |
|
377 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::IncomingSession()" ) |
|
378 } |
|
379 |
|
380 |
|
381 // ----------------------------------------------------------------------------- |
|
382 // |
|
383 // ----------------------------------------------------------------------------- |
|
384 // |
|
385 void CMusEngReceiveSession::IncomingUpdate( |
|
386 CMceSession& aOrigSession, |
|
387 CMceInSession* aUpdatedSession, |
|
388 TMceTransactionDataContainer* aContainer ) |
|
389 { |
|
390 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::IncomingUpdate(...)" ) |
|
391 |
|
392 if ( iSession && |
|
393 iSession == &aOrigSession ) |
|
394 { |
|
395 // Old session is useless from now on |
|
396 delete iSession; |
|
397 iSession = aUpdatedSession; |
|
398 |
|
399 TRAPD( error, CompleteSessionStructureL() ); |
|
400 |
|
401 if ( error != KErrNone ) |
|
402 { |
|
403 MUS_LOG( "mus: [ENGINE] Cannot handle update, reject" ) |
|
404 Reject( *aUpdatedSession ); |
|
405 } |
|
406 } |
|
407 else |
|
408 { |
|
409 // Cannot handle, forward to a base class |
|
410 CMusEngMceSession::IncomingUpdate( aOrigSession, |
|
411 aUpdatedSession, |
|
412 aContainer ); |
|
413 } |
|
414 |
|
415 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::IncomingUpdate(...)" ) |
|
416 } |
|
417 |
|
418 |
|
419 // ----------------------------------------------------------------------------- |
|
420 // |
|
421 // ----------------------------------------------------------------------------- |
|
422 // |
|
423 void CMusEngReceiveSession::StreamStateChanged( CMceMediaStream& aStream ) |
|
424 { |
|
425 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::StreamStateChanged()" ) |
|
426 |
|
427 MUS_ENG_LOG_STREAM_STATE( aStream ) |
|
428 |
|
429 if ( !iSession ) |
|
430 { |
|
431 return; |
|
432 } |
|
433 |
|
434 if ( aStream.Type() == KMceVideo && |
|
435 aStream.Source() && |
|
436 aStream.Source()->Type() == KMceRTPSource ) |
|
437 { |
|
438 |
|
439 if ( aStream.State() == CMceMediaStream::EBuffering ) |
|
440 { |
|
441 iReceiveSessionObserver.StreamBuffering(); |
|
442 } |
|
443 else if ( aStream.State() == CMceMediaStream::EStreaming ) |
|
444 { |
|
445 CMceRtpSource* rtpSource = |
|
446 static_cast<CMceRtpSource*>( aStream.Source() ); |
|
447 TRAPD( err , |
|
448 rtpSource->EnableInactivityTimerL( KMusEngInactivityTimer ) ); |
|
449 if ( err != KErrNone ) |
|
450 { |
|
451 MUS_LOG1("mus: [ENGINE] EnableInactivityTimerL Fails %d",err) |
|
452 iSessionObserver.SessionFailed(); |
|
453 } |
|
454 else |
|
455 { |
|
456 iSessionObserver.StreamStreaming(); |
|
457 } |
|
458 } |
|
459 else |
|
460 { |
|
461 // Cannot handle, forward to CMusEngMceSession |
|
462 CMusEngMceSession::StreamStateChanged( aStream ); |
|
463 } |
|
464 |
|
465 } |
|
466 else |
|
467 { |
|
468 // Cannot handle, forward to CMusEngMceSession |
|
469 CMusEngMceSession::StreamStateChanged( aStream ); |
|
470 } |
|
471 |
|
472 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::StreamStateChanged()" ) |
|
473 } |
|
474 |
|
475 |
|
476 // ----------------------------------------------------------------------------- |
|
477 // |
|
478 // ----------------------------------------------------------------------------- |
|
479 // |
|
480 CMusEngReceiveSession::CMusEngReceiveSession( |
|
481 MMusEngSessionObserver& aSessionObserver, |
|
482 MMusEngReceiveSessionObserver& aReceiveSessionObserver, |
|
483 const TRect& aRect ) |
|
484 : CMusEngMceSession( aRect, aSessionObserver ), |
|
485 iReceiveSessionObserver( aReceiveSessionObserver ) |
|
486 { |
|
487 } |
|
488 |
|
489 |
|
490 // ----------------------------------------------------------------------------- |
|
491 // |
|
492 // ----------------------------------------------------------------------------- |
|
493 // |
|
494 void CMusEngReceiveSession::ConstructL() |
|
495 { |
|
496 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::ConstructL()" ) |
|
497 |
|
498 CMusEngMceSession::ConstructL(); |
|
499 |
|
500 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::ConstructL()" ) |
|
501 } |
|
502 |
|
503 |
|
504 // ----------------------------------------------------------------------------- |
|
505 // |
|
506 // ----------------------------------------------------------------------------- |
|
507 // |
|
508 CMceInSession* CMusEngReceiveSession::InSession() |
|
509 { |
|
510 return static_cast<CMceInSession*>(iSession); |
|
511 } |
|
512 |
|
513 |
|
514 // ----------------------------------------------------------------------------- |
|
515 // Check if incoming session is originated from VideoSharing 2.2 client, |
|
516 // which sends PRACK for 180 Ringing whether it is required or not. In |
|
517 // order to let MCE handle the PRACK correctly, force 180 Ringing to be |
|
518 // sent reliably. |
|
519 // ----------------------------------------------------------------------------- |
|
520 // |
|
521 void CMusEngReceiveSession::PrepareToRequire100RelL( |
|
522 TMceTransactionDataContainer* aContainer) |
|
523 { |
|
524 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::PrepareToRequire100RelL()" ) |
|
525 |
|
526 __ASSERT_ALWAYS( aContainer, User::Leave( KErrArgument ) ); |
|
527 |
|
528 CDesC8Array* headers = aContainer->GetHeaders(); |
|
529 CleanupStack::PushL( headers ); |
|
530 |
|
531 if ( headers ) |
|
532 { |
|
533 for ( TInt i = 0; i < headers->Count(); ++i ) |
|
534 { |
|
535 if ( headers->MdcaPoint(i).FindF( KMusEngSwisIdentifier() ) != |
|
536 KErrNotFound ) |
|
537 { |
|
538 iSession->SetModifierL( KMce100Rel, KMce100RelRequired ); |
|
539 MUS_LOG( "mus: [ENGINE] Forced to require 100rel" ) |
|
540 } |
|
541 } |
|
542 |
|
543 } |
|
544 |
|
545 CleanupStack::PopAndDestroy( headers ); |
|
546 |
|
547 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::PrepareToRequire100RelL()" ) |
|
548 } |
|
549 |
|
550 |
|
551 // ----------------------------------------------------------------------------- |
|
552 // Check that incoming session contains only incoming video and audio |
|
553 // streams. All the other streams will be removed. If there is no |
|
554 // display sinks and speakers, they will be created. |
|
555 // ----------------------------------------------------------------------------- |
|
556 // |
|
557 void CMusEngReceiveSession::CompleteSessionStructureL() |
|
558 { |
|
559 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::CompleteSessionStructureL()" ) |
|
560 |
|
561 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
562 |
|
563 // Force bandwidth line usage in sdp as it is mandatory |
|
564 // at MT side based on GSMA VS specification IR.74. Bandwidth is set to |
|
565 // session or to media level based on sender's way of usage. If other end |
|
566 // is not using bandwidth attribute at all, media level is preferred. |
|
567 SetSessionSdpLinesL( *iSession, ETrue ); |
|
568 |
|
569 CMceStreamBundle* localBundle = |
|
570 CMceStreamBundle::NewLC( CMceStreamBundle::ELS ); |
|
571 |
|
572 const RPointerArray<CMceMediaStream>& streams = iSession->Streams(); |
|
573 |
|
574 CMceMediaStream* videoInStream = NULL; |
|
575 |
|
576 for( TInt i = 0; i < streams.Count(); ++i ) |
|
577 { |
|
578 if ( MusEngMceUtils::IsVideoInStream( *streams[i] ) && |
|
579 !videoInStream ) |
|
580 { |
|
581 videoInStream = streams[i]; |
|
582 |
|
583 // Disable possible opposite stream to indicate that sendrecv is |
|
584 // not allowed. |
|
585 if ( streams[i]->BoundStream() ) |
|
586 { |
|
587 MusEngMceUtils::DisableStreamL( streams[i]->BoundStreamL() ); |
|
588 } |
|
589 } |
|
590 else if ( streams[i]->BoundStream() && |
|
591 MusEngMceUtils::IsVideoInStream( streams[i]->BoundStreamL() ) && |
|
592 !videoInStream ) |
|
593 { |
|
594 videoInStream = &streams[i]->BoundStreamL(); |
|
595 |
|
596 // Disable opposite stream to indicate that sendrecv is not allowed. |
|
597 MusEngMceUtils::DisableStreamL( *streams[i] ); |
|
598 } |
|
599 else if ( MusEngMceUtils::IsAudioInStream( *streams[i] ) && |
|
600 !iOperatorVariant ) |
|
601 { |
|
602 MusEngMceUtils::AddSpeakerL( *streams[i] ); |
|
603 |
|
604 localBundle->AddStreamL( *streams[i] ); |
|
605 |
|
606 // Disable possible opposite stream to indicate that sendrecv is |
|
607 // not allowed. |
|
608 if ( streams[i]->BoundStream() ) |
|
609 { |
|
610 MusEngMceUtils::DisableStreamL( streams[i]->BoundStreamL() ); |
|
611 } |
|
612 } |
|
613 else if ( streams[i]->BoundStream() && |
|
614 MusEngMceUtils::IsAudioInStream( streams[i]->BoundStreamL() ) && |
|
615 !iOperatorVariant ) |
|
616 { |
|
617 MusEngMceUtils::AddSpeakerL( streams[i]->BoundStreamL() ); |
|
618 |
|
619 localBundle->AddStreamL( streams[i]->BoundStreamL() ); |
|
620 |
|
621 // Disable opposite stream to indicate that sendrecv is not allowed. |
|
622 MusEngMceUtils::DisableStreamL( *streams[i] ); |
|
623 } |
|
624 else |
|
625 { |
|
626 // We remove stream because either it |
|
627 // 1. Is not and does not contain incoming video or audio, or |
|
628 // 2. We already have one incoming video stream or |
|
629 // 3. Stream is audio and we run operator variant where audio is |
|
630 // not allowed. |
|
631 iSession->RemoveStreamL( *streams[i] ); |
|
632 |
|
633 // Since succesfull removal of a stream has decreased the amount |
|
634 // of streams in array by one, we have to modify the index |
|
635 --i; |
|
636 } |
|
637 } |
|
638 |
|
639 if ( videoInStream ) |
|
640 { |
|
641 SetMediaSdpLinesL( *videoInStream, ETrue ); |
|
642 |
|
643 // Complete stream |
|
644 MusEngMceUtils::AddDisplayL( *videoInStream, *iManager, Rect() ); |
|
645 |
|
646 static_cast<CMceRtpSource*>(videoInStream->Source())->UpdateL( |
|
647 KMusEngJitterBufferLength, |
|
648 KMusEngJitterBufferTreshold ); |
|
649 |
|
650 localBundle->AddStreamL( *videoInStream ); |
|
651 } |
|
652 else |
|
653 { |
|
654 User::Leave( KErrCorrupt ); |
|
655 } |
|
656 |
|
657 // Next line is to cause a leave if there were no incoming video streams |
|
658 MusEngMceUtils::GetVideoInStreamL( *iSession ); |
|
659 |
|
660 // Destroy bundle if it is not needed or transfer ownership |
|
661 if ( localBundle->Streams().Count() > 1 ) |
|
662 { |
|
663 iSession->AddBundleL( localBundle ); |
|
664 CleanupStack::Pop( localBundle ); |
|
665 } |
|
666 else |
|
667 { |
|
668 CleanupStack::PopAndDestroy( localBundle ); |
|
669 } |
|
670 |
|
671 AdjustStreamsAndCodecsL(); |
|
672 |
|
673 iSession->UpdateL(); |
|
674 |
|
675 // Now session state is right to adjust volume |
|
676 SetSpeakerVolumeL( VolumeL() ); |
|
677 |
|
678 iSipProfileHandler->CreateProfileL( iSession->Profile() ); |
|
679 |
|
680 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::CompleteSessionStructureL()" ) |
|
681 } |
|
682 |
|
683 |
|
684 // ----------------------------------------------------------------------------- |
|
685 // Parse P-Asserted-Identity Header |
|
686 // ----------------------------------------------------------------------------- |
|
687 // |
|
688 void CMusEngReceiveSession::ParseAssertedIdentity( |
|
689 TMceTransactionDataContainer* aContainer ) |
|
690 { |
|
691 MUS_LOG( "mus: [ENGINE] -> CMusEngReceiveSession::AssertedIdentity()" ) |
|
692 |
|
693 iIdentity.Zero(); |
|
694 |
|
695 if ( !aContainer ) |
|
696 { |
|
697 MUS_LOG( "mus: [ENGINE] Data container is NULL" ) |
|
698 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::AssertedIdentity()" ) |
|
699 return; |
|
700 } |
|
701 |
|
702 CDesC8Array* headers = aContainer->GetHeaders(); |
|
703 |
|
704 if ( !headers ) |
|
705 { |
|
706 MUS_LOG( "mus: [ENGINE] No headers" ) |
|
707 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::AssertedIdentity()" ) |
|
708 return; |
|
709 } |
|
710 |
|
711 TBool found = EFalse; |
|
712 TInt length = 0; |
|
713 for( TInt i = 0; i < headers->Count() && !found; ++i ) |
|
714 { |
|
715 TPtrC8 header = (*headers)[i]; |
|
716 if ( header.FindF( KMusEngAssertedIdentity ) != KErrNotFound ) |
|
717 { |
|
718 TInt pos = 0; |
|
719 // check for sip url, continue if found because maybe tel url exists |
|
720 if ( ( pos = header.FindF( KMusEngSipPrefix ) ) != KErrNotFound ) |
|
721 { |
|
722 TInt atPos = header.FindF( KMusEngAtSign ); |
|
723 length = atPos - pos - KMusEngSipPrefix().Length(); |
|
724 if ( length > 0 && length <= KMaxUriLength ) |
|
725 { |
|
726 iIdentity.Copy( |
|
727 header.Mid( pos + KMusEngSipPrefix().Length(), length ) ); |
|
728 } |
|
729 } |
|
730 // check for tel url, exit if found |
|
731 else if ( ( pos = header.FindF( KMusEngTelPrefix ) ) != KErrNotFound ) |
|
732 { |
|
733 length = header.Length() - pos - KMusEngTelPrefix().Length(); |
|
734 if ( length > 0 && length <= KMaxUriLength ) |
|
735 { |
|
736 iIdentity.Copy( header.Right( length ) ); |
|
737 } |
|
738 found = ETrue; |
|
739 } |
|
740 } |
|
741 } |
|
742 |
|
743 // remove ending '>' if exists and whitespaces |
|
744 if ( iIdentity.Length() > 0 ) |
|
745 { |
|
746 iIdentity.Trim(); |
|
747 if ( iIdentity.Find( KMusEngBiggerSign ) == iIdentity.Length() - 1 ) |
|
748 { |
|
749 iIdentity = iIdentity.Left( iIdentity.Length() - 1 ); |
|
750 iIdentity.Trim(); |
|
751 } |
|
752 } |
|
753 |
|
754 delete headers; |
|
755 MUS_LOG( "mus: [ENGINE] <- CMusEngReceiveSession::AssertedIdentity()" ) |
|
756 } |