Skip to content

Commit 2e26baf

Browse files
committed
WHIP: Support parse ice from answer.
1. Parse ice username and pwd. 2. Parse ice candidate, the priority and host. 3. Only support udp.
1 parent 54e45e4 commit 2e26baf

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

libavformat/rtcenc.c

+82
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,18 @@ typedef struct RTCContext {
5454
* DTLS and ICE information.
5555
* */
5656
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;
5766
/* The SDP answer received from the WebRTC server. */
5867
char *sdp_answer;
68+
5969
/* The HTTP URL context is the transport layer for the WHIP protocol. */
6070
URLContext *whip_uc;
6171
} RTCContext;
@@ -348,6 +358,71 @@ static int exchange_sdp(AVFormatContext *s)
348358
return ret;
349359
}
350360

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+
351426
static int rtc_init(AVFormatContext *s)
352427
{
353428
int ret;
@@ -361,6 +436,9 @@ static int rtc_init(AVFormatContext *s)
361436
if ((ret = exchange_sdp(s)) < 0)
362437
return ret;
363438

439+
if ((ret = parse_answer(s)) < 0)
440+
return ret;
441+
364442
return 0;
365443
}
366444

@@ -385,6 +463,10 @@ static void rtc_deinit(AVFormatContext *s)
385463
av_freep(&rtc->sdp_offer);
386464
av_freep(&rtc->sdp_answer);
387465
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);
388470
}
389471

390472
static const AVOption options[] = {

0 commit comments

Comments
 (0)