@@ -54,8 +54,18 @@ typedef struct RTCContext {
54
54
* DTLS and ICE information.
55
55
* */
56
56
char * sdp_offer ;
57
+
58
+ /* The ICE username and pwd from remote server. */
59
+ char * ice_ufrag_remote ;
60
+ char * ice_pwd_remote ;
61
+ /* The ICE candidate protocol, priority, host and port. */
62
+ char * ice_protocol ;
63
+ int ice_priority ;
64
+ char * ice_host ;
65
+ int ice_port ;
57
66
/* The SDP answer received from the WebRTC server. */
58
67
char * sdp_answer ;
68
+
59
69
/* The HTTP URL context is the transport layer for the WHIP protocol. */
60
70
URLContext * whip_uc ;
61
71
} RTCContext ;
@@ -348,6 +358,71 @@ static int exchange_sdp(AVFormatContext *s)
348
358
return ret ;
349
359
}
350
360
361
+ /**
362
+ * Parse the ice ufrag, pwd and candidates from the answer.
363
+ *
364
+ * @return 0 if OK, AVERROR_xxx on error
365
+ */
366
+ static int parse_answer (AVFormatContext * s )
367
+ {
368
+ int ret = 0 ;
369
+ AVIOContext * pb ;
370
+ char line [MAX_URL_SIZE ];
371
+ const char * ptr ;
372
+ int i ;
373
+ RTCContext * rtc = s -> priv_data ;
374
+
375
+ pb = avio_alloc_context (
376
+ (unsigned char * )rtc -> sdp_answer , (int )strlen (rtc -> sdp_answer ),
377
+ AVIO_FLAG_READ , NULL , NULL , NULL , NULL );
378
+ if (!pb ) {
379
+ av_log (s , AV_LOG_ERROR , "Failed to alloc AVIOContext for answer: %s" , rtc -> sdp_answer );
380
+ ret = AVERROR (ENOMEM );
381
+ goto end ;
382
+ }
383
+
384
+ for (i = 0 ; !avio_feof (pb ); i ++ ) {
385
+ ff_get_chomp_line (pb , line , sizeof (line ));
386
+ if (av_strstart (line , "a=ice-ufrag:" , & ptr )) {
387
+ av_freep (& rtc -> ice_ufrag_remote );
388
+ rtc -> ice_ufrag_remote = av_strdup (ptr );
389
+ } else if (av_strstart (line , "a=ice-pwd:" , & ptr )) {
390
+ av_freep (& rtc -> ice_pwd_remote );
391
+ rtc -> ice_pwd_remote = av_strdup (ptr );
392
+ } else if (av_strstart (line , "a=candidate:" , & ptr )) {
393
+ ptr = av_stristr (ptr , "udp" );
394
+ if (ptr && av_stristr (ptr , "host" )) {
395
+ char protocol [17 ], host [129 ];
396
+ int priority , port ;
397
+ ret = sscanf (ptr , "%16s %d %128s %d typ host" , protocol , & priority , host , & port );
398
+ if (ret != 4 ) {
399
+ av_log (s , AV_LOG_ERROR , "Failed %d to parse line %d %s from %s" ,
400
+ ret , i , line , rtc -> sdp_answer );
401
+ ret = AVERROR (EINVAL );
402
+ goto end ;
403
+ }
404
+
405
+ if (av_strcasecmp (protocol , "udp" )) {
406
+ av_log (s , AV_LOG_ERROR , "Protocol %s is not supported by RTC, choose udp" , protocol );
407
+ ret = AVERROR (EINVAL );
408
+ goto end ;
409
+ }
410
+
411
+ av_freep (& rtc -> ice_protocol );
412
+ rtc -> ice_protocol = av_strdup (protocol );
413
+ av_freep (& rtc -> ice_host );
414
+ rtc -> ice_host = av_strdup (host );
415
+ rtc -> ice_priority = priority ;
416
+ rtc -> ice_port = port ;
417
+ }
418
+ }
419
+ }
420
+
421
+ end :
422
+ avio_context_free (& pb );
423
+ return ret ;
424
+ }
425
+
351
426
static int rtc_init (AVFormatContext * s )
352
427
{
353
428
int ret ;
@@ -361,6 +436,9 @@ static int rtc_init(AVFormatContext *s)
361
436
if ((ret = exchange_sdp (s )) < 0 )
362
437
return ret ;
363
438
439
+ if ((ret = parse_answer (s )) < 0 )
440
+ return ret ;
441
+
364
442
return 0 ;
365
443
}
366
444
@@ -385,6 +463,10 @@ static void rtc_deinit(AVFormatContext *s)
385
463
av_freep (& rtc -> sdp_offer );
386
464
av_freep (& rtc -> sdp_answer );
387
465
ffurl_closep (& rtc -> whip_uc );
466
+ av_freep (& rtc -> ice_ufrag_remote );
467
+ av_freep (& rtc -> ice_pwd_remote );
468
+ av_freep (& rtc -> ice_protocol );
469
+ av_freep (& rtc -> ice_host );
388
470
}
389
471
390
472
static const AVOption options [] = {
0 commit comments