|
1 /* |
|
2 * Copyright (c) 2002-2004 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: RTP Datasink |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 // INCLUDE FILES |
|
22 #include <mmf/common/mmfcontroller.h> |
|
23 |
|
24 #include "rtpheader.h" |
|
25 #include <srtpcryptocontext.h> |
|
26 #include <srtpstreamout.h> |
|
27 |
|
28 #include "mccrtpdatasink.h" |
|
29 #include "mmccevents.h" |
|
30 #include "mccinternaldef.h" |
|
31 #include "mccrtpdefs.h" |
|
32 #include "mmccinterfacedef.h" |
|
33 #include "mccrtpmediaclock.h" |
|
34 |
|
35 // MACROS |
|
36 |
|
37 // EXTERNAL DATA STRUCTURES |
|
38 |
|
39 // EXTERNAL FUNCTION PROTOTYPES |
|
40 |
|
41 // CONSTANTS |
|
42 |
|
43 // MACROS |
|
44 #define MCC_RTPSINK_ENDPOINT_ID MCC_ENDPOINT_ID( static_cast<MDataSink*>( this ) ) |
|
45 |
|
46 // LOCAL CONSTANTS AND MACROS |
|
47 |
|
48 // MODULE DATA STRUCTURES |
|
49 |
|
50 // LOCAL FUNCTION PROTOTYPES |
|
51 |
|
52 // FORWARD DECLARATIONS |
|
53 |
|
54 // ============================= LOCAL FUNCTIONS =============================== |
|
55 |
|
56 // ============================ MEMBER FUNCTIONS =============================== |
|
57 |
|
58 // ----------------------------------------------------------------------------- |
|
59 // CMccRtpDataSink::CMccRtpDataSink |
|
60 // C++ default constructor can NOT contain any code, that |
|
61 // might leave. |
|
62 // ----------------------------------------------------------------------------- |
|
63 // |
|
64 CMccRtpDataSink::CMccRtpDataSink() : |
|
65 CMccDataSink( KMccRtpSinkUid ), |
|
66 MMccRtpInterface(), iRtpStreamId( KNullId ) |
|
67 { |
|
68 } |
|
69 |
|
70 // ----------------------------------------------------------------------------- |
|
71 // CMccRtpDataSink::NewSinkL |
|
72 // Static constructor. |
|
73 // ----------------------------------------------------------------------------- |
|
74 // |
|
75 MDataSink* CMccRtpDataSink::NewSinkL( TUid /*aImplementationUid*/, |
|
76 const TDesC8& /*aInitData*/ ) |
|
77 { |
|
78 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::NewSinkL()" ) |
|
79 |
|
80 CMccRtpDataSink* self = new ( ELeave ) CMccRtpDataSink(); |
|
81 return static_cast<MDataSink*>( self ); |
|
82 } |
|
83 |
|
84 // ----------------------------------------------------------------------------- |
|
85 // CMccRtpDataSink::ConstructSinkL |
|
86 // class MDataSink inherited 2nd phase construction |
|
87 // ----------------------------------------------------------------------------- |
|
88 // |
|
89 void CMccRtpDataSink::ConstructSinkL( const TDesC8& aInitData ) |
|
90 { |
|
91 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::ConstructSinkL" ) |
|
92 |
|
93 SetStateL( ERtpStateConstructed ); |
|
94 |
|
95 TInt res = aInitData.Compare( KNullDesC8 ); |
|
96 if ( 0 != res ) |
|
97 { |
|
98 TRACE_RTP_SOURCE_PRINT( "CMccRtpDataSink::ConstructSinkL KErrArgument" ) |
|
99 |
|
100 User::Leave( KErrArgument ); |
|
101 } |
|
102 |
|
103 #ifdef FTD_ENABLED |
|
104 TInt err = iStreamStatsQueue.OpenGlobal( KMccStreamStats, EOwnerProcess ); |
|
105 if ( KErrNone != err ) |
|
106 { |
|
107 User::Leave( err ); |
|
108 } |
|
109 #endif |
|
110 } |
|
111 |
|
112 // ----------------------------------------------------------------------------- |
|
113 // CMccRtpDataSink::~CMccRtpDataSink |
|
114 // Destructor |
|
115 // ----------------------------------------------------------------------------- |
|
116 // |
|
117 CMccRtpDataSink::~CMccRtpDataSink() |
|
118 { |
|
119 TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::~CMccRtpDataSink 0x%x", this ) |
|
120 |
|
121 // We don't own this |
|
122 iEventHandler = NULL; |
|
123 |
|
124 CloseStreams(); |
|
125 |
|
126 iDataSource = NULL; |
|
127 iBufferToBeEmptied = NULL; |
|
128 |
|
129 iUsers.Close(); |
|
130 |
|
131 delete iSender; |
|
132 |
|
133 #ifdef FTD_ENABLED |
|
134 iStreamStatsQueue.Close(); |
|
135 #endif |
|
136 } |
|
137 |
|
138 |
|
139 // ----------------------------------------------------------------------------- |
|
140 // CMccRtpDataSink::SetCurrentUser |
|
141 // ----------------------------------------------------------------------------- |
|
142 // |
|
143 void CMccRtpDataSink::SetCurrentUser( MAsyncEventHandler* aEventHandler ) |
|
144 { |
|
145 iEventHandler = aEventHandler; |
|
146 } |
|
147 |
|
148 |
|
149 // ----------------------------------------------------------------------------- |
|
150 // CMccRtpDataSink::Mute |
|
151 // ----------------------------------------------------------------------------- |
|
152 // |
|
153 void CMccRtpDataSink::Mute( TBool aMuteOn, TUint8 aExceptionPt ) |
|
154 { |
|
155 TRACE_RTP_SINK_PRINT3( "CMccRtpDataSink::Mute, ENABLED: %d, PT: %u", |
|
156 aMuteOn, aExceptionPt ) |
|
157 |
|
158 iMuteOn = aMuteOn; |
|
159 iExceptionPt = aExceptionPt; |
|
160 } |
|
161 |
|
162 // ----------------------------------------------------------------------------- |
|
163 // CMccRtpDataSink::SinkThreadLogon |
|
164 // |
|
165 // Method to 'logon' the data sink to the same thread that sink will be consuming |
|
166 // data in. Thread specific initialisation is done here. |
|
167 // ----------------------------------------------------------------------------- |
|
168 // |
|
169 TInt CMccRtpDataSink::SinkThreadLogon( MAsyncEventHandler& aEventHandler ) |
|
170 { |
|
171 TRACE_RTP_SINK_PRINT ( "CMccRtpDataSink::SinkThreadLogon" ) |
|
172 |
|
173 if ( FindRtpUserEntryForCurrent( aEventHandler ) ) |
|
174 { |
|
175 TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SinkThreadLogon, ERR: %d", KErrAlreadyExists ) |
|
176 return KErrAlreadyExists; |
|
177 } |
|
178 |
|
179 TMccRtpUser user( &aEventHandler ); |
|
180 TInt err = iUsers.Append( user ); |
|
181 |
|
182 TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SinkThreadLogon, exit with err: %d", err ) |
|
183 |
|
184 return err; |
|
185 } |
|
186 |
|
187 // ----------------------------------------------------------------------------- |
|
188 // CMccRtpDataSink::SinkThreadLogoff |
|
189 // |
|
190 // Method to 'logoff' the data sink from the same thread that sink consumes |
|
191 // data in. Thread specific releasing of resources is done here. |
|
192 // ----------------------------------------------------------------------------- |
|
193 // |
|
194 void CMccRtpDataSink::SinkThreadLogoff() |
|
195 { |
|
196 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SinkThreadLogoff" ) |
|
197 |
|
198 RemoveCurrentRtpUser(); |
|
199 |
|
200 SetCurrentUser( NULL ); |
|
201 |
|
202 if ( 0 == iUsers.Count() ) |
|
203 { |
|
204 // SinkThreadLogoff may be called while not stopped, so don't |
|
205 // bother checking any states here. SinkThreadLogoff means that the |
|
206 // thread is going down, so we must cleanup here... |
|
207 |
|
208 StopKeepalive(); |
|
209 CloseStreams(); |
|
210 iRtpAPI = NULL; |
|
211 iRtpStreamId = KNullId; |
|
212 iUsers.Close(); |
|
213 |
|
214 delete iSender; |
|
215 iSender = NULL; |
|
216 } |
|
217 } |
|
218 |
|
219 // ----------------------------------------------------------------------------- |
|
220 // CMccRtpDataSink::SetSinkDataTypeCode |
|
221 // Sets the datatype code ( codec ) |
|
222 // ----------------------------------------------------------------------------- |
|
223 // |
|
224 TInt CMccRtpDataSink::SetSinkDataTypeCode( TFourCC aCodec, TMediaId aMedia ) |
|
225 { |
|
226 if ( KUidMediaTypeAudio == aMedia.iMediaType || |
|
227 KUidMediaTypeVideo == aMedia.iMediaType ) |
|
228 { |
|
229 TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SetSinkDataTypeCode, mediatype:%d", |
|
230 aMedia.iMediaType.iUid ) |
|
231 iMedia = aMedia; |
|
232 iCodecInfo.iFourCC = aCodec; |
|
233 return KErrNone; |
|
234 } |
|
235 else |
|
236 { |
|
237 return KErrNotSupported; |
|
238 } |
|
239 } |
|
240 |
|
241 // ----------------------------------------------------------------------------- |
|
242 // CMccRtpDataSink::SinkDataTypeCode |
|
243 // Returns the datatype code ( codec ) |
|
244 // ----------------------------------------------------------------------------- |
|
245 // |
|
246 TFourCC CMccRtpDataSink::SinkDataTypeCode( TMediaId aMediaId ) |
|
247 { |
|
248 if ( KUidMediaTypeAudio == aMediaId.iMediaType || |
|
249 KUidMediaTypeVideo == aMediaId.iMediaType ) |
|
250 { |
|
251 return iCodecInfo.iFourCC; |
|
252 } |
|
253 else |
|
254 { |
|
255 // Initializes to KMMFFourCCCodeNULL so the caller cannot see |
|
256 // if this sink really has some media type currently registered |
|
257 return TFourCC(); |
|
258 } |
|
259 } |
|
260 |
|
261 // ----------------------------------------------------------------------------- |
|
262 // CMccRtpDataSink::EmptyBufferL |
|
263 // NOT SUPPORTED. MDataSink pure virtual function must be implemented. |
|
264 // ----------------------------------------------------------------------------- |
|
265 // |
|
266 void CMccRtpDataSink::EmptyBufferL( CMMFBuffer* /*aBuffer*/, |
|
267 MDataSource* /*aSupplier*/, |
|
268 TMediaId /*aMediaId*/ ) |
|
269 { |
|
270 User::Leave( KErrNotSupported ); |
|
271 } |
|
272 |
|
273 // ----------------------------------------------------------------------------- |
|
274 // CMccRtpDataSink::EmptyBufferL |
|
275 // Overload to class MDataSink pure virtual function implementation. |
|
276 // Take RTP packet in the buffer and send it. |
|
277 // ----------------------------------------------------------------------------- |
|
278 // |
|
279 void CMccRtpDataSink::EmptyBufferL( CMMFBuffer* aBuffer, |
|
280 MDataSource* aSupplier, |
|
281 TMediaId /*aMediaId*/, |
|
282 TRtpSendHeader& aHeaderInfo ) |
|
283 { |
|
284 __ASSERT_ALWAYS( KNullId != iRtpStreamId, User::Leave( KErrNotReady ) ); |
|
285 this->CheckBufferSupportL( aBuffer ); |
|
286 User::LeaveIfNull( aSupplier ); |
|
287 |
|
288 if ( SendingAllowed( aHeaderInfo ) ) |
|
289 { |
|
290 __ASSERT_ALWAYS( iSender, User::Leave( KErrNotReady ) ); |
|
291 |
|
292 TRACE_RTP_SINK_PRINT3( |
|
293 "CMccRtpDataSink::EmptyBufferL, timestamp: %d, datalen: %d", |
|
294 aHeaderInfo.iTimestamp, aBuffer->BufferSize() ) |
|
295 |
|
296 iBufferToBeEmptied = static_cast<CMMFDataBuffer*>( aBuffer ); |
|
297 |
|
298 iSender->SendRtpPacketL( iRtpStreamId, |
|
299 aHeaderInfo, |
|
300 iBufferToBeEmptied->Data() ); |
|
301 ResetKeepaliveTimer(); |
|
302 } |
|
303 else |
|
304 { |
|
305 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::EmptyBufferL, PACKET DROPPED" ) |
|
306 } |
|
307 |
|
308 // Buffer is emptied, notify the caller so it can reuse the buffer. |
|
309 // We risk a dead lock if we don't do this if the supplier relies on this |
|
310 // callback. |
|
311 aSupplier->BufferEmptiedL( aBuffer ); |
|
312 |
|
313 #ifdef FTD_ENABLED |
|
314 TMccStreamStats stats; |
|
315 stats.iPacketsSent = ++iPacketsSent; |
|
316 stats.SetFieldUpdatedFlag( EPacketsSent ); |
|
317 iStreamStatsQueue.Send( stats ); |
|
318 #endif |
|
319 } |
|
320 |
|
321 // ----------------------------------------------------------------------------- |
|
322 // CMccRtpDataSink::BufferFilledL |
|
323 // NOT SUPPORTED. MDataSink pure virtual function must be implemented. |
|
324 // ----------------------------------------------------------------------------- |
|
325 // |
|
326 void CMccRtpDataSink::BufferFilledL( CMMFBuffer* /*aBuffer*/ ) |
|
327 { |
|
328 // DataSource calls synchronously CMccRtpDataSink->EmptyBuffer(), |
|
329 // so DataSource->FillBuffer, CMccRtpDataSink->BufferFilledL chain is not used at the moment |
|
330 User::Leave( KErrNotSupported ); |
|
331 } |
|
332 |
|
333 // ----------------------------------------------------------------------------- |
|
334 // CMccRtpDataSink::CanCreateSinkBuffer |
|
335 // NOT SUPPORTED. MDataSink pure virtual function must be implemented. |
|
336 // ----------------------------------------------------------------------------- |
|
337 // |
|
338 TBool CMccRtpDataSink::CanCreateSinkBuffer() |
|
339 { |
|
340 return EFalse; |
|
341 } |
|
342 |
|
343 // ----------------------------------------------------------------------------- |
|
344 // CMccRtpDataSink::CreateSinkBufferL |
|
345 // NOT SUPPORTED. MDataSink pure virtual function must be implemented. |
|
346 // ----------------------------------------------------------------------------- |
|
347 // |
|
348 CMMFBuffer* CMccRtpDataSink::CreateSinkBufferL( TMediaId /*aMediaId*/, |
|
349 TBool& /*aReference*/ ) |
|
350 { |
|
351 User::Leave( KErrNotSupported ); |
|
352 return NULL; |
|
353 } |
|
354 |
|
355 // ----------------------------------------------------------------------------- |
|
356 // CMccRtpDataSink::SinkPrimeL |
|
357 // Prime the sink. |
|
358 // ----------------------------------------------------------------------------- |
|
359 // |
|
360 void CMccRtpDataSink::SinkPrimeL() |
|
361 { |
|
362 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SinkPrimeL" ) |
|
363 |
|
364 SetStateL( ERtpStatePrimed ); |
|
365 |
|
366 // Start sending keep alive packets. Secure session has to wait until |
|
367 // secure stream is created |
|
368 if ( !iSecSession ) |
|
369 { |
|
370 StartKeepaliveL( *iRtpMediaClock ); |
|
371 } |
|
372 |
|
373 SendStreamEventToClient( KMccStreamPrepared ); |
|
374 } |
|
375 |
|
376 // ----------------------------------------------------------------------------- |
|
377 // CMccRtpDataSink::SinkPlayL |
|
378 // Start the playout operation. |
|
379 // ----------------------------------------------------------------------------- |
|
380 // |
|
381 void CMccRtpDataSink::SinkPlayL() |
|
382 { |
|
383 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SinkPlayL IN" ) |
|
384 if ( iSecureKeyExpired ) |
|
385 { |
|
386 TRACE_RTP_SINK_PRINT( "Leave becuase the secure key expired" ) |
|
387 User::Leave( KErrGeneral ); |
|
388 } |
|
389 TMccRtpUser* user = FindRtpUserEntryForCurrent( *iEventHandler ); |
|
390 __ASSERT_ALWAYS( user, User::Leave( KErrNotReady ) ); |
|
391 |
|
392 SetStateL( ERtpStatePlaying ); |
|
393 |
|
394 if ( user->iStartedOnce ) |
|
395 { |
|
396 SendStreamEventToClient( KMccStreamResumed ); |
|
397 } |
|
398 else |
|
399 { |
|
400 SendStreamEventToClient( KMccStreamStarted ); |
|
401 user->iStartedOnce = ETrue; |
|
402 } |
|
403 |
|
404 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SinkPlayL OUT" ) |
|
405 } |
|
406 |
|
407 // ----------------------------------------------------------------------------- |
|
408 // CMccRtpDataSink::SinkPauseL |
|
409 // Pauses the playout operation. |
|
410 // ----------------------------------------------------------------------------- |
|
411 // |
|
412 void CMccRtpDataSink::SinkPauseL() |
|
413 { |
|
414 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SinkPauseL" ) |
|
415 |
|
416 SetStateL( ERtpStatePaused ); |
|
417 |
|
418 |
|
419 iSender->Clear(); |
|
420 |
|
421 SendStreamEventToClient( KMccStreamPaused ); |
|
422 } |
|
423 |
|
424 // ----------------------------------------------------------------------------- |
|
425 // CMccRtpDataSink::SinkStopL |
|
426 // Stop the playout operation. |
|
427 // ----------------------------------------------------------------------------- |
|
428 // |
|
429 void CMccRtpDataSink::SinkStopL() |
|
430 { |
|
431 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SinkStopL" ) |
|
432 |
|
433 SetStateL( ERtpStateStopped ); |
|
434 |
|
435 StopKeepalive(); |
|
436 |
|
437 iSender->Clear(); |
|
438 |
|
439 SendStreamEventToClient( KMccStreamStopped ); |
|
440 } |
|
441 |
|
442 // ----------------------------------------------------------------------------- |
|
443 // CMccRtpDataSink::SendMediaSignallingL() |
|
444 // Sends media level signalling |
|
445 // ----------------------------------------------------------------------------- |
|
446 // |
|
447 void CMccRtpDataSink::SendMediaSignallingL( const TMccEvent& aEvent ) |
|
448 { |
|
449 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SendMediaSignallingL" ) |
|
450 |
|
451 __ASSERT_ALWAYS( aEvent.iEventCategory == KMccEventCategoryRtcp && |
|
452 aEvent.iEventType == KMccRtcpControl && |
|
453 iEnableRtcp, |
|
454 User::Leave( KErrNotSupported ) ); |
|
455 |
|
456 __ASSERT_ALWAYS( iRtpAPI, User::Leave( KErrNotReady ) ); |
|
457 |
|
458 const TMccRtcpEventData& rtcpEvent = |
|
459 (*reinterpret_cast<const TMccRtcpEventDataPackage*>( |
|
460 &aEvent.iEventData ))(); |
|
461 |
|
462 switch ( rtcpEvent.iRtcpPacketType ) |
|
463 { |
|
464 case KRtcpSdesPacket: |
|
465 { |
|
466 TPckgBuf<TRtpSdesParams> package; |
|
467 package.Copy( rtcpEvent.iRtcpPacketData ); |
|
468 iRtpAPI->SetLocalSdes( package() ); |
|
469 break; |
|
470 } |
|
471 case KRtcpByePacket: |
|
472 { |
|
473 __ASSERT_ALWAYS( KNullId != iRtpStreamId, User::Leave( KErrNotReady ) ); |
|
474 User::LeaveIfError( |
|
475 iRtpAPI->SendRtcpByePacket( iRtpStreamId, |
|
476 rtcpEvent.iRtcpPacketData ) ); |
|
477 break; |
|
478 } |
|
479 case KRtcpAppPacket: |
|
480 { |
|
481 __ASSERT_ALWAYS( KNullId != iRtpStreamId, User::Leave( KErrNotReady ) ); |
|
482 |
|
483 TPckgBuf<TRtcpApp> package; |
|
484 package.Copy( rtcpEvent.iRtcpPacketData ); |
|
485 |
|
486 User::LeaveIfError( |
|
487 iRtpAPI->SendRtcpAppPacket( iRtpStreamId, package() ) ); |
|
488 |
|
489 break; |
|
490 } |
|
491 case KRtcpSrPacket: |
|
492 { |
|
493 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SendMediaSignallingL, SR" ) |
|
494 |
|
495 __ASSERT_ALWAYS( KNullId != iRtpStreamId, User::Leave( KErrNotReady ) ); |
|
496 User::LeaveIfError( iRtpAPI->SendRtcpSrPacket( iRtpStreamId ) ); |
|
497 break; |
|
498 } |
|
499 case KRtcpAnyPacket: |
|
500 { |
|
501 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SendMediaSignallingL, FC" ) |
|
502 TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SendMediaSignallingL, sessionid:%d", |
|
503 iSessionID ) |
|
504 TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SendMediaSignallingL, datalen: %d", |
|
505 rtcpEvent.iRtcpPacketData.Length() ) |
|
506 |
|
507 __ASSERT_ALWAYS( iSender, User::Leave( KErrNotReady ) ); |
|
508 TBool useRTPSocket( EFalse ); |
|
509 iSender->SendDataL( iSessionID, |
|
510 useRTPSocket, |
|
511 rtcpEvent.iRtcpPacketData ); |
|
512 break; |
|
513 } |
|
514 default: |
|
515 { |
|
516 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SendMediaSignallingL, default" ) |
|
517 User::Leave( KErrArgument ); |
|
518 break; |
|
519 } |
|
520 } |
|
521 } |
|
522 |
|
523 // ----------------------------------------------------------------------------- |
|
524 // CMccRtpDataSink::DoCreateStreamL |
|
525 // Creates a transmit stream. |
|
526 // ----------------------------------------------------------------------------- |
|
527 // |
|
528 void CMccRtpDataSink::DoCreateStreamL() |
|
529 { |
|
530 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateStreamL IN" ) |
|
531 __ASSERT_ALWAYS( KNullId == iRtpStreamId, User::Leave( KErrAlreadyExists ) ); |
|
532 __ASSERT_ALWAYS( NULL != iRtpAPI, User::Leave( KErrNotReady ) ); |
|
533 |
|
534 if ( !iSender ) |
|
535 { |
|
536 // Can do marker based cleanup only with video stream |
|
537 TBool doMarkerBasedCleanup( iMedia.iMediaType == KUidMediaTypeVideo ); |
|
538 iSender = CMccRtpSender::NewL( |
|
539 *this, *iRtpAPI, iSessionID, doMarkerBasedCleanup ); |
|
540 } |
|
541 |
|
542 TTranStreamParams transParams; |
|
543 transParams.iPayloadType = iCodecInfo.iPayloadType; |
|
544 iRtpStreamId = |
|
545 iRtpAPI->CreateTransmitStreamL( iSessionID, transParams, iSSRC ); |
|
546 |
|
547 if ( KNullId == iRtpStreamId ) |
|
548 { |
|
549 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateStreamL KErrCouldNotConnect 1" ) |
|
550 |
|
551 User::Leave( KErrCouldNotConnect ); |
|
552 } |
|
553 |
|
554 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateStreamL SetSamplingRate 1" ) |
|
555 |
|
556 User::LeaveIfError( iRtpAPI->SetSamplingRate( |
|
557 iCodecInfo.iPayloadType, KDefSampleRate ) ); |
|
558 |
|
559 if ( KMccPayloadTypeMax != iCodecInfo.iRedundantPayload ) |
|
560 { |
|
561 User::LeaveIfError( iRtpAPI->SetSamplingRate( |
|
562 iCodecInfo.iRedundantPayload, KDefSampleRate ) ); |
|
563 } |
|
564 |
|
565 DoCreateSrtpStreamL(); |
|
566 |
|
567 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateStreamL OUT" ) |
|
568 } |
|
569 |
|
570 // ----------------------------------------------------------------------------- |
|
571 // CMccRtpDataSink::SendErrorOccured |
|
572 // Asynchronous sending error occured |
|
573 // ----------------------------------------------------------------------------- |
|
574 // |
|
575 void CMccRtpDataSink::SendErrorOccured( TInt aError ) |
|
576 { |
|
577 TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SendErrorOccured, err: %d", aError ) |
|
578 |
|
579 SendInternalRtpEventToAllClients( iUsers, |
|
580 KMccRtpSinkUid, |
|
581 EMccInternalRtpSinkError, |
|
582 KMccStreamError, |
|
583 MCC_RTPSINK_ENDPOINT_ID, |
|
584 aError ); |
|
585 |
|
586 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SendErrorOccured, exit" ) |
|
587 } |
|
588 |
|
589 // ----------------------------------------------------------------------------- |
|
590 // CMccRtpDataSink::DoCreateSrtpStreamL |
|
591 // ----------------------------------------------------------------------------- |
|
592 // |
|
593 void CMccRtpDataSink::DoCreateSrtpStreamL() |
|
594 { |
|
595 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateSrtpStreamL IN" ) |
|
596 if ( !iSrtpStream && iContext && iSecSession && KNullId != iRtpStreamId ) |
|
597 { |
|
598 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateSrtpStreamL, creating" ) |
|
599 iSrtpStream = CSRTPStreamOut::NewL( |
|
600 *iSecSession, static_cast<TUint>( iSSRC ), iContext, *this ); |
|
601 |
|
602 // Now it's possible to send keepalive |
|
603 StartKeepaliveL( *iRtpMediaClock ); |
|
604 } |
|
605 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::DoCreateSrtpStreamL OUT" ) |
|
606 } |
|
607 |
|
608 // --------------------------------------------------------------------------- |
|
609 // CMccRtpDataSink::SinkCustomCommand() |
|
610 // |
|
611 // --------------------------------------------------------------------------- |
|
612 // |
|
613 void CMccRtpDataSink::SinkCustomCommand( TMMFMessage& aMessage ) |
|
614 { |
|
615 TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::SinkCustomCommand - FUNCTION: %d", |
|
616 aMessage.Function() ) |
|
617 |
|
618 TInt result( KErrNone ); |
|
619 aMessage.Complete( result ); |
|
620 } |
|
621 |
|
622 // --------------------------------------------------------------------------- |
|
623 // CMccRtpDataSink::SendRTCPData() |
|
624 // Sends Non-RTCP data |
|
625 // --------------------------------------------------------------------------- |
|
626 // |
|
627 void CMccRtpDataSink::SendRTCPDataL( const TDesC8& aData ) |
|
628 { |
|
629 if ( iRtpAPI && iSender ) |
|
630 { |
|
631 TBool useRTPSocket( EFalse ); |
|
632 iSender->SendDataL( iSessionID, useRTPSocket, aData ); |
|
633 } |
|
634 else |
|
635 { |
|
636 User::Leave( KErrNotReady ); |
|
637 } |
|
638 } |
|
639 |
|
640 // ----------------------------------------------------------------------------- |
|
641 // CMccRtpDataSink::HandleBySsrc |
|
642 // ----------------------------------------------------------------------------- |
|
643 // |
|
644 TBool CMccRtpDataSink::HandleBySsrc( const TRtpSSRC& aSsrc ) |
|
645 { |
|
646 return ( iSSRC == aSsrc ); |
|
647 } |
|
648 |
|
649 // ----------------------------------------------------------------------------- |
|
650 // CMccRtpDataSink::RtpStreamId |
|
651 // ----------------------------------------------------------------------------- |
|
652 // |
|
653 TRtpId CMccRtpDataSink::RtpStreamId() |
|
654 { |
|
655 return iRtpStreamId; |
|
656 } |
|
657 |
|
658 // ----------------------------------------------------------------------------- |
|
659 // CMccRtpDataSink::IsSink |
|
660 // ----------------------------------------------------------------------------- |
|
661 // |
|
662 TBool CMccRtpDataSink::IsSink() const |
|
663 { |
|
664 return ETrue; |
|
665 } |
|
666 |
|
667 // ----------------------------------------------------------------------------- |
|
668 // CMccRtpDataSink::IsSending |
|
669 // ----------------------------------------------------------------------------- |
|
670 // |
|
671 TBool CMccRtpDataSink::IsSending() const |
|
672 { |
|
673 return ( ERtpStatePlaying == State() ); |
|
674 } |
|
675 |
|
676 // ----------------------------------------------------------------------------- |
|
677 // CMccRtpDataSink::SendStreamEventToClient() |
|
678 // ----------------------------------------------------------------------------- |
|
679 // |
|
680 void CMccRtpDataSink::SendStreamEventToClient( |
|
681 TMccEventType aEventType, |
|
682 TInt aError ) |
|
683 { |
|
684 TRACE_RTP_SOURCE_PRINT( "CMccRtpDataSink::SendStreamEventToClient" ) |
|
685 |
|
686 if ( iEventHandler ) |
|
687 { |
|
688 TMccEvent event( 0, |
|
689 0, |
|
690 0, |
|
691 MCC_ENDPOINT_ID( static_cast<MDataSink*>( this ) ), |
|
692 KMccEventCategoryStream, |
|
693 aEventType, |
|
694 aError, |
|
695 KNullDesC8 ); |
|
696 |
|
697 TMccInternalEvent internalEvent( KMccRtpSinkUid, |
|
698 EMccInternalEventNone, |
|
699 event ); |
|
700 |
|
701 iEventHandler->SendEventToClient( internalEvent ); |
|
702 } |
|
703 else |
|
704 { |
|
705 TRACE_RTP_SOURCE_PRINT( "CMccRtpDataSink::SendStreamEventToClient, \ |
|
706 iEventHandler=NULL" ) |
|
707 } |
|
708 } |
|
709 |
|
710 // --------------------------------------------------------------------------- |
|
711 // CMccRtpDataSink::FindRtpUserEntryForCurrent |
|
712 // --------------------------------------------------------------------------- |
|
713 // |
|
714 TMccRtpUser* CMccRtpDataSink::FindRtpUserEntryForCurrent( |
|
715 MAsyncEventHandler& aEventHandler ) |
|
716 { |
|
717 TMccRtpUser entry( &aEventHandler ); |
|
718 TIdentityRelation<TMccRtpUser> comparison( RtpUserMatch ); |
|
719 TInt index = iUsers.Find( entry, comparison ); |
|
720 if ( index != KErrNotFound ) |
|
721 { |
|
722 return &iUsers[ index ]; |
|
723 } |
|
724 return NULL; |
|
725 } |
|
726 |
|
727 // --------------------------------------------------------------------------- |
|
728 // CMccRtpDataSink::RemoveCurrentRtpUser |
|
729 // --------------------------------------------------------------------------- |
|
730 // |
|
731 void CMccRtpDataSink::RemoveCurrentRtpUser() |
|
732 { |
|
733 TMccRtpUser entry( iEventHandler ); |
|
734 TIdentityRelation<TMccRtpUser> comparison( RtpUserMatch ); |
|
735 TInt index = iUsers.Find( entry, comparison ); |
|
736 if ( index != KErrNotFound ) |
|
737 { |
|
738 iUsers.Remove( index ); |
|
739 } |
|
740 } |
|
741 |
|
742 // --------------------------------------------------------------------------- |
|
743 // CMccRtpDataSink::RtpUserMatch |
|
744 // --------------------------------------------------------------------------- |
|
745 // |
|
746 TBool CMccRtpDataSink::RtpUserMatch( |
|
747 const TMccRtpUser& aUser1, |
|
748 const TMccRtpUser& aUser2 ) |
|
749 { |
|
750 // First argument is always the search term |
|
751 |
|
752 TBool match( EFalse ); |
|
753 if ( aUser1.iEventHandler ) |
|
754 { |
|
755 match = ( aUser1.iEventHandler == aUser2.iEventHandler ); |
|
756 } |
|
757 return match; |
|
758 } |
|
759 |
|
760 // --------------------------------------------------------------------------- |
|
761 // CMccRtpDataSink::SendingAllowed |
|
762 // --------------------------------------------------------------------------- |
|
763 // |
|
764 TBool CMccRtpDataSink::SendingAllowed( |
|
765 const TRtpSendHeader& aHeaderInfo ) const |
|
766 { |
|
767 // If secure session, srtp stream has to exist |
|
768 TRACE_RTP_SINK_PRINT2( "CMccRtpDataSink::Sending allowed iSecureKeyExpired = ", |
|
769 iSecureKeyExpired ) |
|
770 |
|
771 TBool isPayloadMuted |
|
772 = iMuteOn ? aHeaderInfo.iPayloadType != iExceptionPt : EFalse; |
|
773 |
|
774 return ( ERtpStatePlaying == State() && |
|
775 ( !iSecSession || iSrtpStream ) && |
|
776 !iSecureKeyExpired && |
|
777 !isPayloadMuted ); |
|
778 } |
|
779 |
|
780 // --------------------------------------------------------------------------- |
|
781 // CMccRtpDataSink::SetMediaClock |
|
782 // --------------------------------------------------------------------------- |
|
783 // |
|
784 void CMccRtpDataSink::SetMediaClock( CMccRtpMediaClock& aRtpMediaClock ) |
|
785 { |
|
786 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SetMediaClock" ) |
|
787 |
|
788 if ( !iRtpMediaClock ) |
|
789 { |
|
790 iRtpMediaClock = &aRtpMediaClock; |
|
791 } |
|
792 else |
|
793 { |
|
794 TRACE_RTP_SINK_PRINT( "CMccRtpDataSink::SetMediaClock - Allready set!" ) |
|
795 } |
|
796 } |
|
797 |
|
798 // --------------------------------------------------------------------------- |
|
799 // FROM SRTP API |
|
800 // This function is called by SRTP Stream initiated with |
|
801 // MSRTPReKeyingObserver when a master key is stale and needs |
|
802 // to be refreshed. |
|
803 // --------------------------------------------------------------------------- |
|
804 // |
|
805 void CMccRtpDataSink::SRTPMasterKeyStaleEvent( const CSRTPStream& aStream ) |
|
806 { |
|
807 TRACE_RTP_INTERFACE_PRINT( "CMccRtpDataSink::SRTPMasterKeyStaleEvent" ) |
|
808 |
|
809 if ( iSrtpStream == &aStream ) |
|
810 { |
|
811 iSecureKeyExpired = ETrue; |
|
812 SendSecureRtpEventToClient( iEventHandler, |
|
813 KMccRtpSinkUid, |
|
814 EMccInternalEventNone, |
|
815 KMccMasterKeyStaled, |
|
816 MCC_RTPSINK_ENDPOINT_ID ); |
|
817 } |
|
818 else |
|
819 { |
|
820 TRACE_RTP_INTERFACE_PRINT( "CMccRtpDataSink::SRTPMasterKeyStaleEvent - Wrong stream" ) |
|
821 } |
|
822 } |
|
823 |
|
824 // --------------------------------------------------------------------------- |
|
825 // FROM SRTP API |
|
826 // This function is called by SRTP Stream initiated with |
|
827 // CSRTPSession when a master key is stale and |
|
828 // needs to be refreshed. |
|
829 // --------------------------------------------------------------------------- |
|
830 void CMccRtpDataSink::SRTPMasterKeyStaleEvent(const CSRTPSession& aSession ) |
|
831 { |
|
832 TRACE_RTP_INTERFACE_PRINT( "CMccRtpStream::SRTPMasterKeyStaleEvent" ) |
|
833 |
|
834 if ( iSecSession == &aSession ) |
|
835 { |
|
836 iSecureKeyExpired = ETrue; |
|
837 SendSecureRtpEventToClient( iEventHandler, |
|
838 KMccRtpSinkUid, |
|
839 EMccInternalEventNone, |
|
840 KMccMasterKeyStaled, |
|
841 MCC_RTPSINK_ENDPOINT_ID ); |
|
842 } |
|
843 else |
|
844 { |
|
845 TRACE_RTP_INTERFACE_PRINT( "MccRtpStream::SRTPMasterKeyStaleEvent - Wrong session" ) |
|
846 } |
|
847 } |
|
848 |
|
849 // ========================== OTHER EXPORTED FUNCTIONS ========================= |
|
850 |
|
851 // End of File |
|
852 |