Skip to content

Commit 92c4187

Browse files
committed
WHIP: Refine code.
1 parent 2e26baf commit 92c4187

File tree

1 file changed

+58
-30
lines changed

1 file changed

+58
-30
lines changed

libavformat/rtcenc.c

+58-30
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,7 +60,11 @@ 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;
6369
int ice_priority;
6470
char *ice_host;
@@ -186,9 +192,15 @@ static int check_codec(AVFormatContext *s)
186192
*/
187193
static int generate_sdp_offer(AVFormatContext *s)
188194
{
189-
int profile_iop;
195+
int ret, profile_iop;
190196
RTCContext *rtc = s->priv_data;
191197

198+
char *tmp = av_mallocz(MAX_SDP_SIZE);
199+
if (!tmp) {
200+
av_log(s, AV_LOG_ERROR, "Failed to alloc answer: %s", s->url);
201+
return AVERROR(EINVAL);
202+
}
203+
192204
if (rtc->sdp_offer) {
193205
av_log(s, AV_LOG_ERROR, "SDP offer is already set\n");
194206
return AVERROR(EINVAL);
@@ -207,7 +219,8 @@ static int generate_sdp_offer(AVFormatContext *s)
207219
rtc->video_payload_type = 106;
208220

209221
profile_iop = rtc->video_par->profile & FF_PROFILE_H264_CONSTRAINED ? 0xe0 : 0x00;
210-
rtc->sdp_offer = av_asprintf(
222+
223+
ret = av_strlcatf(tmp, MAX_SDP_SIZE,
211224
"v=0\r\n"
212225
"o=FFmpeg 4489045141692799359 2 IN IP4 127.0.0.1\r\n"
213226
"s=FFmpegPublishSession\r\n"
@@ -262,11 +275,19 @@ static int generate_sdp_offer(AVFormatContext *s)
262275
profile_iop,
263276
rtc->video_par->level,
264277
rtc->video_ssrc,
265-
rtc->video_ssrc
266-
);
278+
rtc->video_ssrc);
279+
if (ret >= MAX_SDP_SIZE) {
280+
av_log(s, AV_LOG_ERROR, "Offer %d exceed max %d, %s", ret, MAX_SDP_SIZE, tmp);
281+
ret = AVERROR(EINVAL);
282+
goto end;
283+
}
284+
285+
rtc->sdp_offer = av_strdup(tmp);
267286
av_log(s, AV_LOG_VERBOSE, "Generated offer: %s", rtc->sdp_offer);
268287

269-
return 0;
288+
end:
289+
av_free(tmp);
290+
return ret;
270291
}
271292

272293
/**
@@ -313,30 +334,35 @@ static int generate_sdp_offer(AVFormatContext *s)
313334
static int exchange_sdp(AVFormatContext *s)
314335
{
315336
int ret;
316-
char headers[MAX_URL_SIZE], buf[MAX_URL_SIZE];
317-
char *p;
337+
char buf[MAX_URL_SIZE];
318338
RTCContext *rtc = s->priv_data;
319339

340+
char *tmp = av_mallocz(MAX_SDP_SIZE);
341+
if (!tmp) {
342+
av_log(s, AV_LOG_ERROR, "Failed to alloc answer: %s", s->url);
343+
return AVERROR(EINVAL);
344+
}
345+
320346
ret = ffurl_alloc(&rtc->whip_uc, s->url, AVIO_FLAG_READ_WRITE, &s->interrupt_callback);
321347
if (ret < 0) {
322348
av_log(s, AV_LOG_ERROR, "Failed to alloc HTTP context: %s", s->url);
323-
return ret;
349+
goto end;
324350
}
325351

326-
snprintf(headers, sizeof(headers),
352+
snprintf(buf, sizeof(buf),
327353
"Cache-Control: no-cache\r\n"
328354
"Content-Type: application/sdp\r\n");
329-
av_opt_set(rtc->whip_uc->priv_data, "headers", headers, 0);
355+
av_opt_set(rtc->whip_uc->priv_data, "headers", buf, 0);
330356
av_opt_set(rtc->whip_uc->priv_data, "chunked_post", "0", 0);
331357
av_opt_set_bin(rtc->whip_uc->priv_data, "post_data", rtc->sdp_offer, (int)strlen(rtc->sdp_offer), 0);
332358

333359
ret = ffurl_connect(rtc->whip_uc, NULL);
334360
if (ret < 0) {
335361
av_log(s, AV_LOG_ERROR, "Failed to request url=%s, offer: %s", s->url, rtc->sdp_offer);
336-
return ret;
362+
goto end;
337363
}
338364

339-
for (;;) {
365+
while (1) {
340366
ret = ffurl_read(rtc->whip_uc, buf, sizeof(buf));
341367
if (ret == AVERROR_EOF) {
342368
/* Reset the error because we read all response as answer util EOF. */
@@ -346,15 +372,22 @@ static int exchange_sdp(AVFormatContext *s)
346372
if (ret <= 0) {
347373
av_log(s, AV_LOG_ERROR, "Failed to read response from url=%s, offer is %s, answer is %s",
348374
s->url, rtc->sdp_offer, rtc->sdp_answer);
349-
return ret;
375+
goto end;
350376
}
351377

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

389+
end:
390+
av_free(tmp);
358391
return ret;
359392
}
360393

@@ -372,9 +405,7 @@ static int parse_answer(AVFormatContext *s)
372405
int i;
373406
RTCContext *rtc = s->priv_data;
374407

375-
pb = avio_alloc_context(
376-
(unsigned char *)rtc->sdp_answer, (int)strlen(rtc->sdp_answer),
377-
AVIO_FLAG_READ, NULL, NULL, NULL, NULL);
408+
pb = avio_alloc_context(rtc->sdp_answer, strlen(rtc->sdp_answer), AVIO_FLAG_READ, NULL, NULL, NULL, NULL);
378409
if (!pb) {
379410
av_log(s, AV_LOG_ERROR, "Failed to alloc AVIOContext for answer: %s", rtc->sdp_answer);
380411
ret = AVERROR(ENOMEM);
@@ -383,13 +414,11 @@ static int parse_answer(AVFormatContext *s)
383414

384415
for (i = 0; !avio_feof(pb); i++) {
385416
ff_get_chomp_line(pb, line, sizeof(line));
386-
if (av_strstart(line, "a=ice-ufrag:", &ptr)) {
387-
av_freep(&rtc->ice_ufrag_remote);
417+
if (av_strstart(line, "a=ice-ufrag:", &ptr) && !rtc->ice_ufrag_remote) {
388418
rtc->ice_ufrag_remote = av_strdup(ptr);
389-
} else if (av_strstart(line, "a=ice-pwd:", &ptr)) {
390-
av_freep(&rtc->ice_pwd_remote);
419+
} else if (av_strstart(line, "a=ice-pwd:", &ptr) && !rtc->ice_pwd_remote) {
391420
rtc->ice_pwd_remote = av_strdup(ptr);
392-
} else if (av_strstart(line, "a=candidate:", &ptr)) {
421+
} else if (av_strstart(line, "a=candidate:", &ptr) && !rtc->ice_protocol) {
393422
ptr = av_stristr(ptr, "udp");
394423
if (ptr && av_stristr(ptr, "host")) {
395424
char protocol[17], host[129];
@@ -403,14 +432,13 @@ static int parse_answer(AVFormatContext *s)
403432
}
404433

405434
if (av_strcasecmp(protocol, "udp")) {
406-
av_log(s, AV_LOG_ERROR, "Protocol %s is not supported by RTC, choose udp", protocol);
435+
av_log(s, AV_LOG_ERROR, "Protocol %s is not supported by RTC, choose udp, line %d %s of %s",
436+
protocol, i, line, rtc->sdp_answer);
407437
ret = AVERROR(EINVAL);
408438
goto end;
409439
}
410440

411-
av_freep(&rtc->ice_protocol);
412441
rtc->ice_protocol = av_strdup(protocol);
413-
av_freep(&rtc->ice_host);
414442
rtc->ice_host = av_strdup(host);
415443
rtc->ice_priority = priority;
416444
rtc->ice_port = port;
@@ -423,7 +451,7 @@ static int parse_answer(AVFormatContext *s)
423451
return ret;
424452
}
425453

426-
static int rtc_init(AVFormatContext *s)
454+
static av_cold int rtc_init(AVFormatContext *s)
427455
{
428456
int ret;
429457

@@ -457,7 +485,7 @@ static int rtc_write_trailer(AVFormatContext *s)
457485
return 0;
458486
}
459487

460-
static void rtc_deinit(AVFormatContext *s)
488+
static av_cold void rtc_deinit(AVFormatContext *s)
461489
{
462490
RTCContext *rtc = s->priv_data;
463491
av_freep(&rtc->sdp_offer);

0 commit comments

Comments
 (0)