Skip to content

Commit 58821db

Browse files
committed
WHIP: Refine code.
1 parent 2e26baf commit 58821db

File tree

2 files changed

+71
-41
lines changed

2 files changed

+71
-41
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@
4242
/mapfile
4343
/tools/python/__pycache__/
4444
.idea
45+
patcheck.*

libavformat/rtcenc.c

Lines changed: 70 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include "url.h"
3434
#include "libavutil/random_seed.h"
3535

36+
#define MAX_SDP_SIZE 8192
37+
3638
typedef struct RTCContext {
3739
AVClass *av_class;
3840

@@ -58,16 +60,16 @@ typedef struct RTCContext {
5860
/* The ICE username and pwd from remote server. */
5961
char *ice_ufrag_remote;
6062
char *ice_pwd_remote;
61-
/* The ICE candidate protocol, priority, host and port. */
63+
/**
64+
* The ICE candidate protocol, priority, host and port. Note that only
65+
* support one candidate for now. We will choose the first udp candidate.
66+
* We will support multiple candidates in the future.
67+
*/
6268
char *ice_protocol;
63-
int ice_priority;
6469
char *ice_host;
6570
int ice_port;
6671
/* The SDP answer received from the WebRTC server. */
6772
char *sdp_answer;
68-
69-
/* The HTTP URL context is the transport layer for the WHIP protocol. */
70-
URLContext *whip_uc;
7173
} RTCContext;
7274

7375
/**
@@ -186,9 +188,15 @@ static int check_codec(AVFormatContext *s)
186188
*/
187189
static int generate_sdp_offer(AVFormatContext *s)
188190
{
189-
int profile_iop;
191+
int ret, profile_iop;
190192
RTCContext *rtc = s->priv_data;
191193

194+
char *tmp = av_mallocz(MAX_SDP_SIZE);
195+
if (!tmp) {
196+
av_log(s, AV_LOG_ERROR, "Failed to alloc answer: %s", s->url);
197+
return AVERROR(EINVAL);
198+
}
199+
192200
if (rtc->sdp_offer) {
193201
av_log(s, AV_LOG_ERROR, "SDP offer is already set\n");
194202
return AVERROR(EINVAL);
@@ -207,7 +215,8 @@ static int generate_sdp_offer(AVFormatContext *s)
207215
rtc->video_payload_type = 106;
208216

209217
profile_iop = rtc->video_par->profile & FF_PROFILE_H264_CONSTRAINED ? 0xe0 : 0x00;
210-
rtc->sdp_offer = av_asprintf(
218+
219+
ret = av_strlcatf(tmp, MAX_SDP_SIZE,
211220
"v=0\r\n"
212221
"o=FFmpeg 4489045141692799359 2 IN IP4 127.0.0.1\r\n"
213222
"s=FFmpegPublishSession\r\n"
@@ -262,11 +271,19 @@ static int generate_sdp_offer(AVFormatContext *s)
262271
profile_iop,
263272
rtc->video_par->level,
264273
rtc->video_ssrc,
265-
rtc->video_ssrc
266-
);
274+
rtc->video_ssrc);
275+
if (ret >= MAX_SDP_SIZE) {
276+
av_log(s, AV_LOG_ERROR, "Offer %d exceed max %d, %s", ret, MAX_SDP_SIZE, tmp);
277+
ret = AVERROR(EINVAL);
278+
goto end;
279+
}
280+
281+
rtc->sdp_offer = av_strdup(tmp);
267282
av_log(s, AV_LOG_VERBOSE, "Generated offer: %s", rtc->sdp_offer);
268283

269-
return 0;
284+
end:
285+
av_free(tmp);
286+
return ret;
270287
}
271288

272289
/**
@@ -313,31 +330,38 @@ static int generate_sdp_offer(AVFormatContext *s)
313330
static int exchange_sdp(AVFormatContext *s)
314331
{
315332
int ret;
316-
char headers[MAX_URL_SIZE], buf[MAX_URL_SIZE];
317-
char *p;
333+
char buf[MAX_URL_SIZE];
318334
RTCContext *rtc = s->priv_data;
335+
/* The URL context is an HTTP transport layer for the WHIP protocol. */
336+
URLContext *whip_uc = NULL;
337+
338+
char *tmp = av_mallocz(MAX_SDP_SIZE);
339+
if (!tmp) {
340+
av_log(s, AV_LOG_ERROR, "Failed to alloc answer: %s", s->url);
341+
return AVERROR(EINVAL);
342+
}
319343

320-
ret = ffurl_alloc(&rtc->whip_uc, s->url, AVIO_FLAG_READ_WRITE, &s->interrupt_callback);
344+
ret = ffurl_alloc(&whip_uc, s->url, AVIO_FLAG_READ_WRITE, &s->interrupt_callback);
321345
if (ret < 0) {
322346
av_log(s, AV_LOG_ERROR, "Failed to alloc HTTP context: %s", s->url);
323-
return ret;
347+
goto end;
324348
}
325349

326-
snprintf(headers, sizeof(headers),
350+
snprintf(buf, sizeof(buf),
327351
"Cache-Control: no-cache\r\n"
328352
"Content-Type: application/sdp\r\n");
329-
av_opt_set(rtc->whip_uc->priv_data, "headers", headers, 0);
330-
av_opt_set(rtc->whip_uc->priv_data, "chunked_post", "0", 0);
331-
av_opt_set_bin(rtc->whip_uc->priv_data, "post_data", rtc->sdp_offer, (int)strlen(rtc->sdp_offer), 0);
353+
av_opt_set(whip_uc->priv_data, "headers", buf, 0);
354+
av_opt_set(whip_uc->priv_data, "chunked_post", "0", 0);
355+
av_opt_set_bin(whip_uc->priv_data, "post_data", rtc->sdp_offer, (int)strlen(rtc->sdp_offer), 0);
332356

333-
ret = ffurl_connect(rtc->whip_uc, NULL);
357+
ret = ffurl_connect(whip_uc, NULL);
334358
if (ret < 0) {
335359
av_log(s, AV_LOG_ERROR, "Failed to request url=%s, offer: %s", s->url, rtc->sdp_offer);
336-
return ret;
360+
goto end;
337361
}
338362

339-
for (;;) {
340-
ret = ffurl_read(rtc->whip_uc, buf, sizeof(buf));
363+
while (1) {
364+
ret = ffurl_read(whip_uc, buf, sizeof(buf));
341365
if (ret == AVERROR_EOF) {
342366
/* Reset the error because we read all response as answer util EOF. */
343367
ret = 0;
@@ -346,15 +370,23 @@ static int exchange_sdp(AVFormatContext *s)
346370
if (ret <= 0) {
347371
av_log(s, AV_LOG_ERROR, "Failed to read response from url=%s, offer is %s, answer is %s",
348372
s->url, rtc->sdp_offer, rtc->sdp_answer);
349-
return ret;
373+
goto end;
350374
}
351375

352-
p = rtc->sdp_answer;
353-
rtc->sdp_answer = av_asprintf("%s%.*s", p ? p : "", ret, buf);
354-
av_free(p);
376+
ret = av_strlcatf(tmp, MAX_SDP_SIZE, "%.*s", ret, buf);
377+
if (ret >= MAX_SDP_SIZE) {
378+
av_log(s, AV_LOG_ERROR, "Answer %d exceed max size %d, %s", ret, MAX_SDP_SIZE, tmp);
379+
ret = AVERROR(EINVAL);
380+
goto end;
381+
}
355382
}
383+
384+
rtc->sdp_answer = av_strdup(tmp);
356385
av_log(s, AV_LOG_VERBOSE, "Got answer: %s", rtc->sdp_answer);
357386

387+
end:
388+
ffurl_closep(&whip_uc);
389+
av_free(tmp);
358390
return ret;
359391
}
360392

@@ -372,9 +404,7 @@ static int parse_answer(AVFormatContext *s)
372404
int i;
373405
RTCContext *rtc = s->priv_data;
374406

375-
pb = avio_alloc_context(
376-
(unsigned char *)rtc->sdp_answer, (int)strlen(rtc->sdp_answer),
377-
AVIO_FLAG_READ, NULL, NULL, NULL, NULL);
407+
pb = avio_alloc_context(rtc->sdp_answer, strlen(rtc->sdp_answer), AVIO_FLAG_READ, NULL, NULL, NULL, NULL);
378408
if (!pb) {
379409
av_log(s, AV_LOG_ERROR, "Failed to alloc AVIOContext for answer: %s", rtc->sdp_answer);
380410
ret = AVERROR(ENOMEM);
@@ -383,13 +413,11 @@ static int parse_answer(AVFormatContext *s)
383413

384414
for (i = 0; !avio_feof(pb); i++) {
385415
ff_get_chomp_line(pb, line, sizeof(line));
386-
if (av_strstart(line, "a=ice-ufrag:", &ptr)) {
387-
av_freep(&rtc->ice_ufrag_remote);
416+
if (av_strstart(line, "a=ice-ufrag:", &ptr) && !rtc->ice_ufrag_remote) {
388417
rtc->ice_ufrag_remote = av_strdup(ptr);
389-
} else if (av_strstart(line, "a=ice-pwd:", &ptr)) {
390-
av_freep(&rtc->ice_pwd_remote);
418+
} else if (av_strstart(line, "a=ice-pwd:", &ptr) && !rtc->ice_pwd_remote) {
391419
rtc->ice_pwd_remote = av_strdup(ptr);
392-
} else if (av_strstart(line, "a=candidate:", &ptr)) {
420+
} else if (av_strstart(line, "a=candidate:", &ptr) && !rtc->ice_protocol) {
393421
ptr = av_stristr(ptr, "udp");
394422
if (ptr && av_stristr(ptr, "host")) {
395423
char protocol[17], host[129];
@@ -403,27 +431,29 @@ static int parse_answer(AVFormatContext *s)
403431
}
404432

405433
if (av_strcasecmp(protocol, "udp")) {
406-
av_log(s, AV_LOG_ERROR, "Protocol %s is not supported by RTC, choose udp", protocol);
434+
av_log(s, AV_LOG_ERROR, "Protocol %s is not supported by RTC, choose udp, line %d %s of %s",
435+
protocol, i, line, rtc->sdp_answer);
407436
ret = AVERROR(EINVAL);
408437
goto end;
409438
}
410439

411-
av_freep(&rtc->ice_protocol);
412440
rtc->ice_protocol = av_strdup(protocol);
413-
av_freep(&rtc->ice_host);
414441
rtc->ice_host = av_strdup(host);
415-
rtc->ice_priority = priority;
416442
rtc->ice_port = port;
417443
}
418444
}
419445
}
420446

447+
av_log(s, AV_LOG_VERBOSE, "SDP offer=%luB, answer=%luB, ufrag=%s, pwd=%luB, transport=%s://%s:%d\n",
448+
strlen(rtc->sdp_offer), strlen(rtc->sdp_answer), rtc->ice_ufrag_remote, strlen(rtc->ice_pwd_remote),
449+
rtc->ice_protocol, rtc->ice_host, rtc->ice_port);
450+
421451
end:
422452
avio_context_free(&pb);
423453
return ret;
424454
}
425455

426-
static int rtc_init(AVFormatContext *s)
456+
static av_cold int rtc_init(AVFormatContext *s)
427457
{
428458
int ret;
429459

@@ -457,12 +487,11 @@ static int rtc_write_trailer(AVFormatContext *s)
457487
return 0;
458488
}
459489

460-
static void rtc_deinit(AVFormatContext *s)
490+
static av_cold void rtc_deinit(AVFormatContext *s)
461491
{
462492
RTCContext *rtc = s->priv_data;
463493
av_freep(&rtc->sdp_offer);
464494
av_freep(&rtc->sdp_answer);
465-
ffurl_closep(&rtc->whip_uc);
466495
av_freep(&rtc->ice_ufrag_remote);
467496
av_freep(&rtc->ice_pwd_remote);
468497
av_freep(&rtc->ice_protocol);

0 commit comments

Comments
 (0)