1 /* |
|
2 * Copyright (c) 2007 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 the License "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: Parses SDP file.* |
|
15 */ |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 // INCLUDE FILES |
|
21 #include <ipvideo/CDvrSdpParser.h> |
|
22 #include <in_sock.h> |
|
23 #include "videoserviceutilsLogger.h" |
|
24 |
|
25 // CONSTANTS |
|
26 _LIT8( KKeyIpv4Addr, "c=IN IP4 " ); |
|
27 _LIT8( KKeyIpv6Addr, "c=IN IP6 " ); |
|
28 _LIT8( KKeyAttribute, "a=" ); |
|
29 _LIT8( KKeyMedia, "m=" ); |
|
30 _LIT8( KKeyMediaAudio, "m=audio " ); |
|
31 _LIT8( KKeyMediaVideo, "m=video " ); |
|
32 _LIT8( KKeyMediaTitle, "m=title " ); |
|
33 _LIT8( KKeyDataStream, "m=data " ); |
|
34 _LIT8( KKeyClockRate, "a=rtpmap:" ); |
|
35 _LIT8( KKeyControl, "a=control:" ); |
|
36 //_LIT8( KKeyStreamId, "a=control:streamid=" ); |
|
37 _LIT8( KRealMediaIndicator, "/x-pn-real" ); |
|
38 _LIT8( KKeyBandWidth, "b=AS:" ); |
|
39 _LIT8( KCRSDPRtspUriBegin, "rtsp://" ); |
|
40 _LIT8( KSPStr, " "); |
|
41 _LIT8( KCRStr, "\r"); |
|
42 _LIT8( KLFStr, "\n"); |
|
43 _LIT8( KCRLFStr, "\r\n"); |
|
44 _LIT8( KSLStr, "/" ); |
|
45 _LIT8( KSdpLiveStream, "a=LiveStream:integer;1"); |
|
46 _LIT8( KSdpRangeHeaderLiveStream, "a=range:npt=now-" ); |
|
47 |
|
48 // ============================ MEMBER FUNCTIONS =============================== |
|
49 |
|
50 // ----------------------------------------------------------------------------- |
|
51 // CDvrSdpParser::NewL |
|
52 // Two-phased constructor. |
|
53 // ----------------------------------------------------------------------------- |
|
54 // |
|
55 EXPORT_C CDvrSdpParser* CDvrSdpParser::NewL() |
|
56 { |
|
57 CDvrSdpParser* self = CDvrSdpParser::NewLC(); |
|
58 CleanupStack::Pop( self ); |
|
59 return self; |
|
60 } |
|
61 |
|
62 // ----------------------------------------------------------------------------- |
|
63 // CDvrSdpParser::NewLC |
|
64 // Two-phased constructor. |
|
65 // ----------------------------------------------------------------------------- |
|
66 // |
|
67 EXPORT_C CDvrSdpParser* CDvrSdpParser::NewLC() |
|
68 { |
|
69 CDvrSdpParser* self = new( ELeave ) CDvrSdpParser(); |
|
70 CleanupStack::PushL( self ); |
|
71 self->ConstructL(); |
|
72 return self; |
|
73 } |
|
74 |
|
75 // ----------------------------------------------------------------------------- |
|
76 // CDvrSdpParser::CDvrSdpParser |
|
77 // C++ default constructor can NOT contain any code, that might leave. |
|
78 // ----------------------------------------------------------------------------- |
|
79 // |
|
80 CDvrSdpParser::CDvrSdpParser() |
|
81 : iAudioPort( KErrNotFound ), |
|
82 iVideoPort( KErrNotFound ), |
|
83 iTitlePort( KErrNotFound ), |
|
84 iAudioBitrate( KErrNotFound ), |
|
85 iVideoBitrate( KErrNotFound ), |
|
86 iAudioStreamId( KErrNotFound ), |
|
87 iVideoStreamId( KErrNotFound ), |
|
88 iVideoTimerGranularity( KMaxTUint32 ), |
|
89 iAudioTimerGranularity( KMaxTUint32 ) |
|
90 { |
|
91 // None |
|
92 } |
|
93 |
|
94 // ----------------------------------------------------------------------------- |
|
95 // CDvrSdpParser::ConstructL |
|
96 // Symbian 2nd phase constructor can leave. |
|
97 // ----------------------------------------------------------------------------- |
|
98 // |
|
99 void CDvrSdpParser::ConstructL() |
|
100 { |
|
101 LOG( "CDvrSdpParser::ConstructL()" ); |
|
102 } |
|
103 |
|
104 // ----------------------------------------------------------------------------- |
|
105 // CDvrSdpParser::~CDvrSdpParser |
|
106 // Destructor. |
|
107 // ----------------------------------------------------------------------------- |
|
108 // |
|
109 EXPORT_C CDvrSdpParser::~CDvrSdpParser() |
|
110 { |
|
111 LOG( "CDvrSdpParser::~CDvrSdpParser()" ); |
|
112 delete iBaseUrl; iBaseUrl = NULL; |
|
113 DeleteVariables(); |
|
114 } |
|
115 |
|
116 // ----------------------------------------------------------------------------- |
|
117 // CDvrSdpParser::TryParseL |
|
118 // |
|
119 // ----------------------------------------------------------------------------- |
|
120 // |
|
121 EXPORT_C void CDvrSdpParser::TryParseL( const TDesC8& aSdp, const TDesC8& aBaseUrl ) |
|
122 { |
|
123 #if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE ) |
|
124 HBufC* baseLog = HBufC::NewLC( aBaseUrl.Length() ); |
|
125 TPtr ptr = baseLog->Des(); |
|
126 ptr.Copy( aBaseUrl ); |
|
127 LOG2( "CDvrSdpParser::TryParseL(), aSdp length: %d, aBaseUrl: %S", |
|
128 aSdp.Length(), &ptr ); |
|
129 CleanupStack::PopAndDestroy( baseLog ); |
|
130 #endif |
|
131 |
|
132 if ( aBaseUrl.Length() ) |
|
133 { |
|
134 delete iBaseUrl; iBaseUrl = NULL; |
|
135 iBaseUrl = aBaseUrl.AllocL(); |
|
136 } |
|
137 |
|
138 TryParseL( aSdp ); |
|
139 } |
|
140 |
|
141 // ----------------------------------------------------------------------------- |
|
142 // CDvrSdpParser::TryParseL |
|
143 // |
|
144 // ----------------------------------------------------------------------------- |
|
145 // |
|
146 EXPORT_C void CDvrSdpParser::TryParseL( const TDesC8& aSdp ) |
|
147 { |
|
148 LOG1( "CDvrSdpParser::TryParseL(), aSdp length: %d", aSdp.Length() ); |
|
149 |
|
150 // Find medias |
|
151 FindMediasL( aSdp ); |
|
152 |
|
153 // Append found medias to the array |
|
154 for ( TInt i( 0 ); i < iMediaBuf.Count(); i++ ) |
|
155 { |
|
156 TInt port( KErrNotFound ); |
|
157 TPtrC8 ptr( iMediaBuf[i] ); |
|
158 |
|
159 // Audio media info found ? |
|
160 port = GetIntL( ptr, KKeyMediaAudio ); |
|
161 if ( port != KErrNotFound ) |
|
162 { |
|
163 iAudioPort = port; |
|
164 LOG1( "CDvrSdpParser::TryParseL(), iAudioPort: %d", iAudioPort ); |
|
165 UpdateMediaInfoL( ptr, iAudioIpAddr ); |
|
166 // Stream id (Helix takes medias in appearance order) |
|
167 iAudioStreamId = i; |
|
168 // Audio clock rate |
|
169 iAudioTimerGranularity = GetClockRateL( ptr ); |
|
170 iAudioBitrate = GetIntL( ptr, KKeyBandWidth ); |
|
171 // Audio attributes |
|
172 FindAttributesL( ptr, iAudioAttributes ); |
|
173 // Audio control |
|
174 GetControlL( ptr, iAudioControlAddr ); |
|
175 // Find media id 97 from a=rtpmap:97 MP4A-LATM/32000/2 |
|
176 iMediaIdentifierAudio = GetIntL( ptr, KKeyClockRate ); |
|
177 } |
|
178 else |
|
179 { |
|
180 // Video media info found ? |
|
181 port = GetIntL( ptr, KKeyMediaVideo ); |
|
182 if ( port != KErrNotFound ) |
|
183 { |
|
184 iVideoPort = port; |
|
185 LOG1( "CDvrSdpParser::TryParseL(), iVideoPort: %d", iVideoPort ); |
|
186 UpdateMediaInfoL( ptr, iVideoIpAddr ); |
|
187 // Stream id (Helix takes medias in appearance order) |
|
188 iVideoStreamId = i; |
|
189 // Video clock rate |
|
190 iVideoTimerGranularity = GetClockRateL( ptr ); |
|
191 iVideoBitrate = GetIntL( ptr, KKeyBandWidth ); |
|
192 // Video attributes |
|
193 FindAttributesL( ptr, iVideoAttributes ); |
|
194 // Video control |
|
195 GetControlL( ptr, iVideoControlAddr ); |
|
196 // Find media id 96 from a=rtpmap:96 H264/90000 line |
|
197 iMediaIdentifierVideo = GetIntL( ptr, KKeyClockRate ); |
|
198 } |
|
199 else |
|
200 { |
|
201 port = GetIntL( ptr, KKeyMediaTitle ); |
|
202 if ( port != KErrNotFound ) |
|
203 { |
|
204 iTitlePort = port; |
|
205 LOG1( "CDvrSdpParser::TryParseL(), iTitlePort: %d", iTitlePort ); |
|
206 } |
|
207 } |
|
208 } |
|
209 } |
|
210 |
|
211 iMediaBuf.Reset(); |
|
212 delete iBaseUrl; iBaseUrl = NULL; |
|
213 delete iCommonIp; iCommonIp = NULL; |
|
214 } |
|
215 |
|
216 // ----------------------------------------------------------------------------- |
|
217 // CDvrSdpParser::NewLineL |
|
218 // |
|
219 // ----------------------------------------------------------------------------- |
|
220 // |
|
221 EXPORT_C void CDvrSdpParser::NewLineL( |
|
222 const TInt aStreamId, |
|
223 const TDesC8& aLine ) |
|
224 { |
|
225 User::LeaveIfNull( iSdp ); |
|
226 const TInt newLen( iSdp->Length() + aLine.Length() + KCRLFStr().Length() ); |
|
227 LOG2( "CDvrSdpParser::NewLineL(), aStreamId: %d, New sdp length: %d", |
|
228 aStreamId, newLen ); |
|
229 switch( aStreamId ) |
|
230 { |
|
231 case KErrNotFound: // Common |
|
232 { |
|
233 // Alloc more room |
|
234 iSdp = iSdp->ReAllocL( newLen ); |
|
235 TPtr8 ptr( iSdp->Des() ); |
|
236 |
|
237 // Find first attribute for new line point |
|
238 const TInt insertPoint( ptr.Find( KKeyAttribute ) ); |
|
239 User::LeaveIfError( insertPoint ); |
|
240 ptr.Insert( insertPoint, KCRLFStr ); |
|
241 ptr.Insert( insertPoint, aLine ); |
|
242 } |
|
243 break; |
|
244 |
|
245 case 0: // Audio (usually) |
|
246 case 1: // Video (usually) |
|
247 { |
|
248 iSdp = iSdp->ReAllocL( newLen ); |
|
249 InserNewLineL( aStreamId, aLine ); |
|
250 } |
|
251 break; |
|
252 |
|
253 default: |
|
254 User::Leave( KErrCompletion ); |
|
255 } |
|
256 } |
|
257 |
|
258 // ----------------------------------------------------------------------------- |
|
259 // CDvrSdpParser::GetSdp |
|
260 // |
|
261 // ----------------------------------------------------------------------------- |
|
262 // |
|
263 EXPORT_C TInt CDvrSdpParser::GetSdp( TPtrC8& aSdp ) |
|
264 { |
|
265 if ( iSdp ) |
|
266 { |
|
267 aSdp.Set( iSdp->Des() ); |
|
268 return KErrNone; |
|
269 } |
|
270 |
|
271 return KErrNotFound; |
|
272 } |
|
273 |
|
274 // ----------------------------------------------------------------------------- |
|
275 // CDvrSdpParser::SupportedContent |
|
276 // ----------------------------------------------------------------------------- |
|
277 // |
|
278 EXPORT_C CDvrSdpParser::TDvrPacketProvidings CDvrSdpParser::SupportedContent( void ) |
|
279 { |
|
280 TDvrPacketProvidings retval( EDvrNoProgramAtAll ); |
|
281 |
|
282 if ( iAudioPort > KErrNotFound && iVideoPort > KErrNotFound ) |
|
283 { |
|
284 retval = EDvrBothAudioAndVideo; |
|
285 } |
|
286 else if ( iAudioPort > KErrNotFound && iVideoPort <= KErrNotFound ) |
|
287 { |
|
288 retval = EDvrAudioOnly; |
|
289 } |
|
290 else if ( iVideoPort > KErrNotFound && iAudioPort <= KErrNotFound ) |
|
291 { |
|
292 retval = EDvrVideoOnly; |
|
293 } |
|
294 else |
|
295 { |
|
296 LOG( "CDvrSdpParser::SupportedContent(), No media !" ); |
|
297 } |
|
298 |
|
299 return retval; |
|
300 } |
|
301 |
|
302 // ----------------------------------------------------------------------------- |
|
303 // CDvrSdpParser::SessionAttributes |
|
304 // |
|
305 // ----------------------------------------------------------------------------- |
|
306 // |
|
307 EXPORT_C RArray<TPtrC8>& CDvrSdpParser::SessionAttributes( void ) |
|
308 { |
|
309 return iSessionAttributes; |
|
310 } |
|
311 |
|
312 // ----------------------------------------------------------------------------- |
|
313 // CDvrSdpParser::AudioAttributes |
|
314 // |
|
315 // ----------------------------------------------------------------------------- |
|
316 // |
|
317 EXPORT_C RArray<TPtrC8>& CDvrSdpParser::AudioAttributes( void ) |
|
318 { |
|
319 return iAudioAttributes; |
|
320 } |
|
321 |
|
322 // ----------------------------------------------------------------------------- |
|
323 // CDvrSdpParser::VideoAttributes |
|
324 // |
|
325 // ----------------------------------------------------------------------------- |
|
326 // |
|
327 EXPORT_C RArray<TPtrC8>& CDvrSdpParser::VideoAttributes( void ) |
|
328 { |
|
329 return iVideoAttributes; |
|
330 } |
|
331 |
|
332 // ----------------------------------------------------------------------------- |
|
333 // CDvrSdpParser::DataStreams |
|
334 // |
|
335 // ----------------------------------------------------------------------------- |
|
336 // |
|
337 EXPORT_C RArray<TPtrC8>& CDvrSdpParser::DataStreams( void ) |
|
338 { |
|
339 return iDataStreams; |
|
340 } |
|
341 |
|
342 // ----------------------------------------------------------------------------- |
|
343 // CDvrSdpParser::IsIpv4Sdp |
|
344 // Checks if Ipv4 address in use. |
|
345 // ----------------------------------------------------------------------------- |
|
346 // |
|
347 EXPORT_C TBool CDvrSdpParser::IsIpv4Sdp( void ) |
|
348 { |
|
349 return iIsIpv4; |
|
350 } |
|
351 |
|
352 // ----------------------------------------------------------------------------- |
|
353 // CDvrSdpParser::IsMultiCastSdp |
|
354 // Checks if c= line did specify a multicast addr |
|
355 // ----------------------------------------------------------------------------- |
|
356 // |
|
357 EXPORT_C TBool CDvrSdpParser::IsMultiCastSdp( void ) |
|
358 { |
|
359 return iIsMulticast; |
|
360 } |
|
361 |
|
362 // ----------------------------------------------------------------------------- |
|
363 // CDvrSdpParser::AudioControlAddr |
|
364 // |
|
365 // ----------------------------------------------------------------------------- |
|
366 // |
|
367 EXPORT_C TPtrC8 CDvrSdpParser::AudioControlAddr( void ) |
|
368 { |
|
369 return ( iAudioControlAddr )? TPtrC8( *iAudioControlAddr ): |
|
370 TPtrC8( KNullDesC8 ); |
|
371 } |
|
372 |
|
373 // ----------------------------------------------------------------------------- |
|
374 // CDvrSdpParser::VideoControlAddr |
|
375 // |
|
376 // ----------------------------------------------------------------------------- |
|
377 // |
|
378 EXPORT_C TPtrC8 CDvrSdpParser::VideoControlAddr( void ) |
|
379 { |
|
380 return ( iVideoControlAddr )? TPtrC8( *iVideoControlAddr ): |
|
381 TPtrC8( KNullDesC8 ); |
|
382 } |
|
383 |
|
384 // ----------------------------------------------------------------------------- |
|
385 // CDvrSdpParser::AudioIpAddr |
|
386 // |
|
387 // ----------------------------------------------------------------------------- |
|
388 // |
|
389 EXPORT_C TPtrC8 CDvrSdpParser::AudioIpAddr( void ) |
|
390 { |
|
391 return ( iAudioIpAddr )? TPtrC8( *iAudioIpAddr ): TPtrC8( KNullDesC8 ); |
|
392 } |
|
393 |
|
394 // ----------------------------------------------------------------------------- |
|
395 // CDvrSdpParser::VideoIpAddr |
|
396 // |
|
397 // ----------------------------------------------------------------------------- |
|
398 // |
|
399 EXPORT_C TPtrC8 CDvrSdpParser::VideoIpAddr( void ) |
|
400 { |
|
401 return ( iVideoIpAddr )? TPtrC8( *iVideoIpAddr ): TPtrC8( KNullDesC8 ); |
|
402 } |
|
403 |
|
404 // ----------------------------------------------------------------------------- |
|
405 // CDvrSdpParser::AudioPort |
|
406 // |
|
407 // ----------------------------------------------------------------------------- |
|
408 // |
|
409 EXPORT_C TInt CDvrSdpParser::AudioPort( void ) |
|
410 { |
|
411 return iAudioPort; |
|
412 } |
|
413 |
|
414 // ----------------------------------------------------------------------------- |
|
415 // CDvrSdpParser::VideoPort |
|
416 // |
|
417 // ----------------------------------------------------------------------------- |
|
418 // |
|
419 EXPORT_C TInt CDvrSdpParser::VideoPort( void ) |
|
420 { |
|
421 return iVideoPort; |
|
422 } |
|
423 |
|
424 // ----------------------------------------------------------------------------- |
|
425 // CDvrSdpParser::AudioBitrate |
|
426 // |
|
427 // ----------------------------------------------------------------------------- |
|
428 // |
|
429 EXPORT_C TInt CDvrSdpParser::AudioBitrate( void ) |
|
430 { |
|
431 return iAudioBitrate; |
|
432 } |
|
433 |
|
434 // ----------------------------------------------------------------------------- |
|
435 // CDvrSdpParser::VideoBitrate |
|
436 // |
|
437 // ----------------------------------------------------------------------------- |
|
438 // |
|
439 EXPORT_C TInt CDvrSdpParser::VideoBitrate( void ) |
|
440 { |
|
441 return iVideoBitrate; |
|
442 } |
|
443 |
|
444 // ----------------------------------------------------------------------------- |
|
445 // CDvrSdpParser::AudioStreamId |
|
446 // |
|
447 // ----------------------------------------------------------------------------- |
|
448 // |
|
449 EXPORT_C TInt CDvrSdpParser::AudioStreamId( void ) |
|
450 { |
|
451 return iAudioStreamId; |
|
452 } |
|
453 |
|
454 // ----------------------------------------------------------------------------- |
|
455 // CDvrSdpParser::VideoStreamId |
|
456 // |
|
457 // ----------------------------------------------------------------------------- |
|
458 // |
|
459 EXPORT_C TInt CDvrSdpParser::VideoStreamId( void ) |
|
460 { |
|
461 return iVideoStreamId; |
|
462 } |
|
463 |
|
464 // ----------------------------------------------------------------------------- |
|
465 // CDvrSdpParser::VideoTimerGranularity |
|
466 // |
|
467 // ----------------------------------------------------------------------------- |
|
468 // |
|
469 EXPORT_C TUint32 CDvrSdpParser::VideoTimerGranularity( void ) |
|
470 { |
|
471 return iVideoTimerGranularity; |
|
472 } |
|
473 |
|
474 // ----------------------------------------------------------------------------- |
|
475 // CDvrSdpParser::AudioTimerGranularity |
|
476 // |
|
477 // ----------------------------------------------------------------------------- |
|
478 // |
|
479 EXPORT_C TUint32 CDvrSdpParser::AudioTimerGranularity( void ) |
|
480 { |
|
481 return iAudioTimerGranularity; |
|
482 } |
|
483 |
|
484 // ----------------------------------------------------------------------------- |
|
485 // CDvrSdpParser::IsRealMediaContent |
|
486 // Check for realmedia content. |
|
487 // ----------------------------------------------------------------------------- |
|
488 // |
|
489 EXPORT_C TBool CDvrSdpParser::IsRealMediaContent( void ) |
|
490 { |
|
491 if ( iSdp && iSdp->Des().Find( KRealMediaIndicator ) != KErrNotFound ) |
|
492 { |
|
493 LOG( "CDvrSdpParser::IsRealMediaContent(), Yes" ); |
|
494 return ETrue; |
|
495 } |
|
496 |
|
497 return EFalse; |
|
498 } |
|
499 |
|
500 // ----------------------------------------------------------------------------- |
|
501 // CDvrSdpParser::MediaIdentifierAudio |
|
502 // |
|
503 // ----------------------------------------------------------------------------- |
|
504 // |
|
505 EXPORT_C TInt CDvrSdpParser::MediaIdentifierAudio( void ) |
|
506 { |
|
507 return iMediaIdentifierAudio ; |
|
508 } |
|
509 |
|
510 // ----------------------------------------------------------------------------- |
|
511 // CDvrSdpParser::MediaIdentifierVideo |
|
512 // |
|
513 // ----------------------------------------------------------------------------- |
|
514 // |
|
515 EXPORT_C TInt CDvrSdpParser::MediaIdentifierVideo( void ) |
|
516 { |
|
517 return iMediaIdentifierVideo ; |
|
518 } |
|
519 |
|
520 // ----------------------------------------------------------------------------- |
|
521 // CDvrSdpParser::IsLiveStream |
|
522 // |
|
523 // ----------------------------------------------------------------------------- |
|
524 // |
|
525 EXPORT_C TBool CDvrSdpParser::IsLiveStream( void ) |
|
526 { |
|
527 TBool isLiveStream = EFalse; |
|
528 if ( iSdp && |
|
529 ( iSdp->Des().Find( KSdpLiveStream ) != KErrNotFound || |
|
530 iSdp->Des().Find( KSdpRangeHeaderLiveStream ) != KErrNotFound ) ) |
|
531 { |
|
532 LOG( "CDvrSdpParser::IsLiveStream(), Yes" ); |
|
533 isLiveStream = ETrue; |
|
534 } |
|
535 |
|
536 return isLiveStream; |
|
537 } |
|
538 |
|
539 // ----------------------------------------------------------------------------- |
|
540 // CDvrSdpParser::FindMediasL |
|
541 // |
|
542 // ----------------------------------------------------------------------------- |
|
543 // |
|
544 void CDvrSdpParser::FindMediasL( const TDesC8& aSdp ) |
|
545 { |
|
546 LOG1( "CDvrSdpParser::FindMediasL(), aSdp length: %d", aSdp.Length() ); |
|
547 |
|
548 // Find medias from SDP |
|
549 DeleteVariables(); |
|
550 iSdp = aSdp.AllocL(); |
|
551 RArray<SMediaPoint> points; |
|
552 CleanupClosePushL( points ); |
|
553 FindMediaPointsL( points ); |
|
554 MakeMediaBuffersL( points ); |
|
555 FindSessionAttributesL( points ); |
|
556 CleanupStack::PopAndDestroy( &points ); |
|
557 FindDataStreamsL( iSdp->Des(), iDataStreams ); |
|
558 } |
|
559 |
|
560 // ----------------------------------------------------------------------------- |
|
561 // CDvrSdpParser::FindMediaPointsL |
|
562 // Find points of all medias. |
|
563 // ----------------------------------------------------------------------------- |
|
564 // |
|
565 void CDvrSdpParser::FindMediaPointsL( RArray<SMediaPoint>& aPoints ) |
|
566 { |
|
567 TInt lastPoint( 0 ); |
|
568 User::LeaveIfNull( iSdp ); |
|
569 TPtrC8 ptr( iSdp->Des() ); |
|
570 TInt start( MediaSectionStart( ptr ) ); |
|
571 |
|
572 // Loop all media sections |
|
573 while ( start > KErrNotFound && lastPoint < iSdp->Length() ) |
|
574 { |
|
575 // Find whole media section, up to next media or EOF |
|
576 start += lastPoint; |
|
577 TInt len( MediaSectionStart( ptr.Mid( start + KKeyMedia().Length() ) ) ); |
|
578 len = ( len > KErrNotFound )? len + KKeyMedia().Length() - 1: |
|
579 ptr.Length() - start - 1; |
|
580 // New media point |
|
581 SMediaPoint point; |
|
582 point.iStart = start; |
|
583 point.iLength = len; |
|
584 lastPoint = ( start + len ); |
|
585 User::LeaveIfError( aPoints.Append( point ) ); |
|
586 LOG3( "CDvrSdpParser::FindMediaPointsL(), start: %d, len: %d, lastPoint: %d", |
|
587 start, len, lastPoint ); |
|
588 // Next section |
|
589 start = MediaSectionStart( ptr.Mid( lastPoint ) ); |
|
590 } |
|
591 } |
|
592 |
|
593 // ----------------------------------------------------------------------------- |
|
594 // CDvrSdpParser::MediaSectionStart |
|
595 // |
|
596 // ----------------------------------------------------------------------------- |
|
597 // |
|
598 TInt CDvrSdpParser::MediaSectionStart( const TDesC8& aPtr ) |
|
599 { |
|
600 TInt start( aPtr.Find( KKeyMedia ) ); |
|
601 while ( start > KErrNotFound ) |
|
602 { |
|
603 // Verify that not data stream keyword? ( i.e not 'm=data' ) |
|
604 const TInt keywordlen( KKeyDataStream().Length() ); |
|
605 TPtrC8 ptr( aPtr.Mid( start, keywordlen ) ); |
|
606 if ( ptr.Find( KKeyDataStream ) == KErrNotFound ) |
|
607 { |
|
608 // Audio, video or subtitle |
|
609 return start; |
|
610 } |
|
611 |
|
612 start += keywordlen; |
|
613 const TInt next( aPtr.Mid( start ).Find( KKeyMedia ) ); |
|
614 start = ( next > KErrNotFound )? start + next: KErrNotFound; |
|
615 } |
|
616 |
|
617 return start; |
|
618 } |
|
619 |
|
620 // ----------------------------------------------------------------------------- |
|
621 // CDvrSdpParser::MakeMediaBuffersL |
|
622 // Make media buffers |
|
623 // ----------------------------------------------------------------------------- |
|
624 // |
|
625 void CDvrSdpParser::MakeMediaBuffersL( RArray<SMediaPoint>& aPoints ) |
|
626 { |
|
627 User::LeaveIfNull( iSdp ); |
|
628 for ( TInt i( 0 ); i < aPoints.Count(); i++ ) |
|
629 { |
|
630 TPtrC8 media( iSdp->Des().Mid( aPoints[i].iStart, aPoints[i].iLength ) ); |
|
631 User::LeaveIfError( iMediaBuf.Append( media ) ); |
|
632 } |
|
633 } |
|
634 |
|
635 // ----------------------------------------------------------------------------- |
|
636 // CDvrSdpParser::FindSessionAttributesL |
|
637 // Find session attributes (common section before any media) |
|
638 // ----------------------------------------------------------------------------- |
|
639 // |
|
640 void CDvrSdpParser::FindSessionAttributesL( RArray<SMediaPoint>& aPoints ) |
|
641 { |
|
642 User::LeaveIfNull( iSdp ); |
|
643 if ( aPoints.Count() ) |
|
644 { |
|
645 TPtrC8 common( iSdp->Des().Left( aPoints[0].iStart ) ); |
|
646 FindAttributesL( common, iSessionAttributes ); |
|
647 |
|
648 // IP in common section |
|
649 delete iCommonIp; iCommonIp = NULL; |
|
650 iCommonIp = GetIpAddrL( common ); |
|
651 } |
|
652 } |
|
653 |
|
654 // ----------------------------------------------------------------------------- |
|
655 // CDvrSdpParser::InserNewLineL |
|
656 // |
|
657 // ----------------------------------------------------------------------------- |
|
658 // |
|
659 void CDvrSdpParser::InserNewLineL( |
|
660 TInt aStreamId, |
|
661 const TDesC8& aLine ) |
|
662 { |
|
663 RArray<SMediaPoint> points; |
|
664 CleanupClosePushL( points ); |
|
665 FindMediaPointsL( points ); |
|
666 |
|
667 // Add new line to first after media description |
|
668 if ( aStreamId >= 0 && aStreamId < points.Count() ) |
|
669 { |
|
670 User::LeaveIfNull( iSdp ); |
|
671 TPtr8 ptr( iSdp->Des() ); |
|
672 TInt insertPoint( GetLen( ptr.Mid( points[aStreamId].iStart, |
|
673 points[aStreamId].iLength ), ETrue ) ); |
|
674 User::LeaveIfError( insertPoint ); |
|
675 ptr.Insert( insertPoint, aLine ); |
|
676 ptr.Insert( insertPoint, KCRLFStr ); |
|
677 } |
|
678 else |
|
679 { |
|
680 User::Leave( KErrCompletion ); |
|
681 } |
|
682 |
|
683 CleanupStack::PopAndDestroy( &points ); |
|
684 } |
|
685 |
|
686 // ----------------------------------------------------------------------------- |
|
687 // CDvrSdpParser::UpdateMediaInfoL |
|
688 // |
|
689 // ----------------------------------------------------------------------------- |
|
690 // |
|
691 void CDvrSdpParser::UpdateMediaInfoL( |
|
692 const TDesC8& aMediaPtr, |
|
693 HBufC8*& aAddress ) |
|
694 { |
|
695 // Search for IP address (Ipv6/Ipv4) |
|
696 aAddress = GetIpAddrL( aMediaPtr ); |
|
697 if ( !aAddress && iCommonIp ) |
|
698 { |
|
699 aAddress = iCommonIp->AllocL(); |
|
700 } |
|
701 User::LeaveIfNull( aAddress ); |
|
702 TPtr8 ptr( aAddress->Des() ); |
|
703 |
|
704 // IP Address |
|
705 if ( iIsIpv4 ) |
|
706 { |
|
707 LOG( "CDvrSdpParser::UpdateMediaInfoL(), Removing v4 subnet mask" ); |
|
708 // Remove possible subnet mask (e.g. c=IN IP4 225.0.1.15/64) |
|
709 const TInt maskPos( aAddress->Find( KSLStr ) ); |
|
710 if ( maskPos != KErrNotFound ) |
|
711 { |
|
712 ptr.SetLength( maskPos ); |
|
713 } |
|
714 } |
|
715 |
|
716 #if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE ) |
|
717 TName buf; buf.Copy( ptr ); |
|
718 LOG1( "CDvrSdpParser::UpdateMediaInfoL(), aAddress: %S", &buf ); |
|
719 #endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE |
|
720 |
|
721 /* Stream Id |
|
722 const TInt streamId( GetIntL( aMediaPtr, KKeyStreamId ) ); |
|
723 LOG1( "CDvrSdpParser::UpdateMediaInfoL(), Stream Id: %d", streamId ); |
|
724 return streamId; |
|
725 */ |
|
726 } |
|
727 |
|
728 // ----------------------------------------------------------------------------- |
|
729 // CDvrSdpParser::GetIpAddrL |
|
730 // |
|
731 // ----------------------------------------------------------------------------- |
|
732 // |
|
733 HBufC8* CDvrSdpParser::GetIpAddrL( const TDesC8& aPtr ) |
|
734 { |
|
735 iIsIpv4 = EFalse; |
|
736 HBufC8* ipAddr = GetStringL( aPtr, KKeyIpv6Addr ); |
|
737 if ( !ipAddr ) |
|
738 { |
|
739 ipAddr = GetStringL( aPtr, KKeyIpv4Addr ); |
|
740 if ( ipAddr ) |
|
741 { |
|
742 iIsIpv4 = ETrue; |
|
743 } |
|
744 } |
|
745 |
|
746 // Verify multicast |
|
747 if ( ipAddr ) |
|
748 { |
|
749 TPtrC8 addr( ipAddr->Des() ); |
|
750 if ( addr.Length() <= KMaxName ) |
|
751 { |
|
752 CheckForMulticast( addr ); |
|
753 } |
|
754 else |
|
755 { |
|
756 LOG1( "Ipaddress length too long: %d, leaving....", addr.Length() ); |
|
757 delete ipAddr; ipAddr = NULL; |
|
758 User::Leave( KErrOverflow ); |
|
759 } |
|
760 } |
|
761 |
|
762 return ipAddr; |
|
763 } |
|
764 |
|
765 // ----------------------------------------------------------------------------- |
|
766 // CDvrSdpParser::GetClockRateL |
|
767 // |
|
768 // ----------------------------------------------------------------------------- |
|
769 // |
|
770 TUint CDvrSdpParser::GetClockRateL( const TDesC8& aPtr ) |
|
771 { |
|
772 // Find clock rate keyword |
|
773 TInt start( FindStart( aPtr, KKeyClockRate ) ); |
|
774 User::LeaveIfError( start ); |
|
775 |
|
776 // Len up to first slash ( i.e: rtpmap:97 MP4A-LATM/32000/2 ) |
|
777 TInt slash( aPtr.Mid( start ).Find( KSLStr ) ); |
|
778 User::LeaveIfError( slash ); |
|
779 start += ( slash + KSLStr().Length() ); |
|
780 TInt len( GetLen( aPtr, start ) ); |
|
781 |
|
782 // Len up to second slash ( i.e: rtpmap:97 MP4A-LATM/32000/2 ) |
|
783 slash = aPtr.Mid( start, len ).Find( KSLStr ); |
|
784 len = ( slash != KErrNotFound )? slash: len; |
|
785 return StrToUint( aPtr.Mid( start, len ) ); |
|
786 } |
|
787 |
|
788 // ----------------------------------------------------------------------------- |
|
789 // CDvrSdpParser::GetControlL() |
|
790 // Checks if a=control line specifies a control for media. |
|
791 // ----------------------------------------------------------------------------- |
|
792 // |
|
793 void CDvrSdpParser::GetControlL( const TDesC8& aMediaPtr, HBufC8*& aControlAddr ) |
|
794 { |
|
795 delete aControlAddr; aControlAddr = NULL; |
|
796 HBufC8* control = GetStringL( aMediaPtr, KKeyControl ); |
|
797 if ( control ) |
|
798 { |
|
799 CleanupStack::PushL( control ); |
|
800 if ( control->Des().FindC( KCRSDPRtspUriBegin ) == KErrNotFound ) |
|
801 { |
|
802 // relative url |
|
803 if ( iBaseUrl ) |
|
804 { |
|
805 aControlAddr = HBufC8::NewL( iBaseUrl->Des().Length() + |
|
806 control->Des().Length() + |
|
807 KSLStr().Length() ); |
|
808 aControlAddr->Des().Append ( iBaseUrl->Des() ); |
|
809 aControlAddr->Des().Append ( KSLStr ) ; |
|
810 aControlAddr->Des().Append ( control->Des() ); |
|
811 } |
|
812 } |
|
813 else |
|
814 { |
|
815 // absolute url |
|
816 aControlAddr = control->Des().AllocL(); |
|
817 } |
|
818 |
|
819 CleanupStack::PopAndDestroy( control ); |
|
820 } |
|
821 } |
|
822 |
|
823 // ----------------------------------------------------------------------------- |
|
824 // CDvrSdpParser::CheckForMulticast() |
|
825 // Checks if c= line specifies a multicast addr |
|
826 // ----------------------------------------------------------------------------- |
|
827 // |
|
828 void CDvrSdpParser::CheckForMulticast( const TDesC8& aLine ) |
|
829 { |
|
830 TInetAddr controladdr; |
|
831 TName addr( KNullDesC ); |
|
832 addr.Copy( aLine ); |
|
833 TInt err( controladdr.Input( addr ) ); |
|
834 if ( err != KErrNone ) |
|
835 { |
|
836 LOG1( "CDvrSdpParser: invalid control address in SDP connection line '%S'", &addr ); |
|
837 } |
|
838 else |
|
839 { |
|
840 // just do check for multicast, actual address is taken from SETUP response |
|
841 iIsMulticast = controladdr.IsMulticast(); |
|
842 |
|
843 #if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE ) |
|
844 /* Commented out, for some reason can crash with RTP playback in debug. |
|
845 if ( iIsMulticast ) |
|
846 { |
|
847 LOG1( "CDvrSdpParser: detected MULTICAST (%S) control address in SDP", &addr ); |
|
848 } |
|
849 else |
|
850 { |
|
851 LOG1( "CDvrSdpParser: detected unicast (%S) control address in SDP", &addr ); |
|
852 } |
|
853 */ |
|
854 #endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE |
|
855 } |
|
856 } |
|
857 |
|
858 // ----------------------------------------------------------------------------- |
|
859 // CDvrSdpParser::FindAttributesL |
|
860 // |
|
861 // ----------------------------------------------------------------------------- |
|
862 // |
|
863 void CDvrSdpParser::FindAttributesL( |
|
864 const TDesC8& aSdpSection, |
|
865 RArray<TPtrC8>& aAttributeList ) |
|
866 { |
|
867 TInt last( 0 ); |
|
868 TInt start( KErrNotFound ); |
|
869 do |
|
870 { |
|
871 // Rest of the SDP section |
|
872 TPtrC8 rest( aSdpSection.Mid( last ) ); |
|
873 start = rest.Find( KKeyAttribute ); |
|
874 if ( start > KErrNotFound ) |
|
875 { |
|
876 last += start; |
|
877 TInt len( GetLen( rest, start, ETrue ) ); |
|
878 if ( len > 0 ) |
|
879 { |
|
880 // Add other than control attribute |
|
881 if ( rest.Mid( start, len ).Find( KKeyControl ) == KErrNotFound ) |
|
882 { |
|
883 TPtrC8 ptr( rest.Mid( start, len ) ); |
|
884 User::LeaveIfError( aAttributeList.Append( ptr ) ); |
|
885 } |
|
886 |
|
887 last += len; |
|
888 } |
|
889 } |
|
890 } |
|
891 while( start > KErrNotFound ); |
|
892 } |
|
893 |
|
894 // ----------------------------------------------------------------------------- |
|
895 // CDvrSdpParser::FindDataStreamsL |
|
896 // |
|
897 // ----------------------------------------------------------------------------- |
|
898 // |
|
899 void CDvrSdpParser::FindDataStreamsL( |
|
900 const TDesC8& aSdpSection, |
|
901 RArray<TPtrC8>& aStreamsList ) |
|
902 { |
|
903 TInt last( 0 ); |
|
904 TInt start( KErrNotFound ); |
|
905 do |
|
906 { |
|
907 // Rest of the SDP block |
|
908 TPtrC8 rest( aSdpSection.Mid( last ) ); |
|
909 start = rest.Find( KKeyDataStream ); |
|
910 if ( start > KErrNotFound ) |
|
911 { |
|
912 last += start; |
|
913 TInt len( GetLen( rest, start, ETrue ) ); |
|
914 if ( len > 0 ) |
|
915 { |
|
916 TPtrC8 ptr( rest.Mid( start, len ) ); |
|
917 User::LeaveIfError( aStreamsList.Append( ptr ) ); |
|
918 last += len; |
|
919 } |
|
920 } |
|
921 } |
|
922 while( start > KErrNotFound ); |
|
923 } |
|
924 |
|
925 // ----------------------------------------------------------------------------- |
|
926 // CDvrSdpParser::GetIntL |
|
927 // |
|
928 // ----------------------------------------------------------------------------- |
|
929 // |
|
930 TInt CDvrSdpParser::GetIntL( const TDesC8& aPtr, const TDesC8& aKeyword ) |
|
931 { |
|
932 TInt ret( KErrNotFound ); |
|
933 HBufC8* buf = GetStringL( aPtr, aKeyword ); |
|
934 if ( buf ) |
|
935 { |
|
936 ret = StrToUint( buf->Des() ); |
|
937 delete buf; |
|
938 } |
|
939 |
|
940 return ret; |
|
941 } |
|
942 |
|
943 // ----------------------------------------------------------------------------- |
|
944 // CDvrSdpParser::GetStringL |
|
945 // |
|
946 // ----------------------------------------------------------------------------- |
|
947 // |
|
948 HBufC8* CDvrSdpParser::GetStringL( const TDesC8& aPtr, const TDesC8& aKeyword ) |
|
949 { |
|
950 const TInt start( FindStart( aPtr, aKeyword ) ); |
|
951 const TInt len( GetLen( aPtr, start ) ); |
|
952 |
|
953 HBufC8* buf = NULL; |
|
954 if ( start > KErrNotFound && len > 0 && ( start + len ) <= aPtr.Length() ) |
|
955 { |
|
956 buf = aPtr.Mid( start, len ).AllocL(); |
|
957 } |
|
958 |
|
959 return buf; |
|
960 } |
|
961 |
|
962 // ----------------------------------------------------------------------------- |
|
963 // CDvrSdpParser::FindStart |
|
964 // |
|
965 // ----------------------------------------------------------------------------- |
|
966 // |
|
967 TInt CDvrSdpParser::FindStart( const TDesC8& aPtr, const TDesC8& aKeyword ) |
|
968 { |
|
969 TInt start( aPtr.Find( aKeyword ) ); |
|
970 |
|
971 if ( start > KErrNotFound ) |
|
972 { |
|
973 start += aKeyword.Length(); |
|
974 } |
|
975 |
|
976 return start; |
|
977 } |
|
978 |
|
979 // ----------------------------------------------------------------------------- |
|
980 // CDvrSdpParser::GetLen |
|
981 // |
|
982 // ----------------------------------------------------------------------------- |
|
983 // |
|
984 TInt CDvrSdpParser::GetLen( |
|
985 const TDesC8& aPtr, |
|
986 const TInt aStart, |
|
987 const TBool aIgnoreSpace ) |
|
988 { |
|
989 if ( aStart > KErrNotFound && aStart < aPtr.Length() ) |
|
990 { |
|
991 // Find next LF, CR or CRLF combination |
|
992 TInt len1( MinNonError( aPtr.Mid( aStart ).Find( KLFStr ), |
|
993 aPtr.Mid( aStart ).Find( KCRStr ) ) ); |
|
994 // Find space |
|
995 TInt len2( ( aIgnoreSpace )? KErrNotFound: |
|
996 aPtr.Mid( aStart ).Find( KSPStr ) ); |
|
997 |
|
998 if ( len1 == KErrNotFound && len2 == KErrNotFound ) |
|
999 { |
|
1000 // Rest of the buffer |
|
1001 return ( aPtr.Length() - aStart ); |
|
1002 } |
|
1003 else |
|
1004 { |
|
1005 // CRLF or space |
|
1006 return MinNonError( len1, len2 ); |
|
1007 } |
|
1008 } |
|
1009 |
|
1010 return KErrNotFound; |
|
1011 } |
|
1012 |
|
1013 // ----------------------------------------------------------------------------- |
|
1014 // CDvrSdpParser::MinNonError |
|
1015 // |
|
1016 // ----------------------------------------------------------------------------- |
|
1017 // |
|
1018 TInt CDvrSdpParser::MinNonError( const TInt aValue1, const TInt aValue2 ) |
|
1019 { |
|
1020 if ( aValue1 > KErrNotFound && aValue2 > KErrNotFound ) |
|
1021 { |
|
1022 return Min( aValue1, aValue2 ); |
|
1023 } |
|
1024 |
|
1025 return ( ( aValue1 > KErrNotFound )? aValue1: |
|
1026 ( aValue2 > KErrNotFound )? aValue2: KErrNotFound ); |
|
1027 } |
|
1028 |
|
1029 // ----------------------------------------------------------------------------- |
|
1030 // CDvrSdpParser::StrToUint |
|
1031 // Convert string to integer. |
|
1032 // ----------------------------------------------------------------------------- |
|
1033 // |
|
1034 TUint CDvrSdpParser::StrToUint( const TDesC8& aString ) |
|
1035 { |
|
1036 TLex8 templex; |
|
1037 templex.Assign( aString ); |
|
1038 TUint ret( KMaxTUint ); |
|
1039 templex.Val( ret ); |
|
1040 return ret; |
|
1041 } |
|
1042 |
|
1043 // ----------------------------------------------------------------------------- |
|
1044 // CDvrSdpParser::DeleteVariables |
|
1045 // |
|
1046 // ----------------------------------------------------------------------------- |
|
1047 // |
|
1048 void CDvrSdpParser::DeleteVariables( void ) |
|
1049 { |
|
1050 delete iSdp; iSdp = NULL; |
|
1051 delete iCommonIp; iCommonIp = NULL; |
|
1052 iMediaBuf.Reset(); |
|
1053 iSessionAttributes.Reset(); |
|
1054 iAudioAttributes.Reset(); |
|
1055 iVideoAttributes.Reset(); |
|
1056 iDataStreams.Reset(); |
|
1057 delete iAudioControlAddr; iAudioControlAddr = NULL; |
|
1058 delete iVideoControlAddr; iVideoControlAddr = NULL; |
|
1059 delete iAudioIpAddr; iAudioIpAddr = NULL; |
|
1060 delete iVideoIpAddr; iVideoIpAddr = NULL; |
|
1061 } |
|
1062 |
|
1063 // End of File |
|