FFmpeg
Loading...
Searching...
No Matches
whip.c
Go to the documentation of this file.
1/*
2 * WebRTC-HTTP ingestion protocol (WHIP) muxer
3 * Copyright (c) 2023 The FFmpeg Project
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include "libavcodec/h264.h"
24
26#include "libavutil/avassert.h"
27#include "libavutil/base64.h"
28#include "libavutil/bprint.h"
29#include "libavutil/crc.h"
30#include "libavutil/hmac.h"
32#include "libavutil/lfg.h"
33#include "libavutil/opt.h"
34#include "libavutil/mem.h"
36#include "libavutil/time.h"
37#include "avc.h"
38#include "nal.h"
39#include "avio_internal.h"
40#include "http.h"
41#include "internal.h"
42#include "mux.h"
43#include "network.h"
44#include "rtp.h"
45#include "srtp.h"
46#include "tls.h"
47
48/**
49 * Maximum size limit of a Session Description Protocol (SDP),
50 * be it an offer or answer.
51 */
52#define MAX_SDP_SIZE 8192
53
54/**
55 * The size of the Secure Real-time Transport Protocol (SRTP) master key material
56 * that is exported by Secure Sockets Layer (SSL) after a successful Datagram
57 * Transport Layer Security (DTLS) handshake. This material consists of a key
58 * of 16 bytes and a salt of 14 bytes.
59 */
60#define DTLS_SRTP_KEY_LEN 16
61#define DTLS_SRTP_SALT_LEN 14
62
63/**
64 * The maximum size of the Secure Real-time Transport Protocol (SRTP) HMAC checksum
65 * and padding that is appended to the end of the packet. To calculate the maximum
66 * size of the User Datagram Protocol (UDP) packet that can be sent out, subtract
67 * this size from the `pkt_size`.
68 */
69#define DTLS_SRTP_CHECKSUM_LEN 16
70
71#define WHIP_US_PER_MS 1000
72
73/**
74 * If we try to read from UDP and get EAGAIN, we sleep for 5ms and retry up to 10 times.
75 * This will limit the total duration (in milliseconds, 50ms)
76 */
77#define ICE_DTLS_READ_MAX_RETRY 10
78#define ICE_DTLS_READ_SLEEP_DURATION 5
79
80/* The magic cookie for Session Traversal Utilities for NAT (STUN) messages. */
81#define STUN_MAGIC_COOKIE 0x2112A442
82
83/**
84 * Refer to RFC 8445 5.1.2
85 * priority = (2^24)*(type preference) + (2^8)*(local preference) + (2^0)*(256 - component ID)
86 * host candidate priority is 126 << 24 | 65535 << 8 | 255
87 */
88#define STUN_HOST_CANDIDATE_PRIORITY 126 << 24 | 65535 << 8 | 255
89
90/**
91 * Maximum size of the buffer for sending and receiving UDP packets.
92 * Please note that this size does not limit the size of the UDP packet that can be sent.
93 * To set the limit for packet size, modify the `pkt_size` parameter.
94 * For instance, it is possible to set the UDP buffer to 4096 to send or receive packets,
95 * but please keep in mind that the `pkt_size` option limits the packet size to 1400.
96 */
97#define MAX_UDP_BUFFER_SIZE 4096
98
99/* Referring to Chrome's definition of RTP payload types. */
100#define WHIP_RTP_PAYLOAD_TYPE_H264 106
101#define WHIP_RTP_PAYLOAD_TYPE_OPUS 111
102#define WHIP_RTP_PAYLOAD_TYPE_VIDEO_RTX 105
103
104/**
105 * The STUN message header, which is 20 bytes long, comprises the
106 * STUNMessageType (1B), MessageLength (2B), MagicCookie (4B),
107 * and TransactionID (12B).
108 * See https://datatracker.ietf.org/doc/html/rfc5389#section-6
109 */
110#define ICE_STUN_HEADER_SIZE 20
111
112/**
113 * The RTP header is 12 bytes long, comprising the Version(1B), PT(1B),
114 * SequenceNumber(2B), Timestamp(4B), and SSRC(4B).
115 * See https://www.rfc-editor.org/rfc/rfc3550#section-5.1
116 */
117#define WHIP_RTP_HEADER_SIZE 12
118
119/**
120 * For RTCP, PT is [128, 223] (or without marker [0, 95]). Literally, RTCP starts
121 * from 64 not 0, so PT is [192, 223] (or without marker [64, 95]), see "RTCP Control
122 * Packet Types (PT)" at
123 * https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-4
124 *
125 * For RTP, the PT is [96, 127], or [224, 255] with marker. See "RTP Payload Types (PT)
126 * for standard audio and video encodings" at
127 * https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-1
128 */
129#define WHIP_RTCP_PT_START 192
130#define WHIP_RTCP_PT_END 223
131
132/**
133 * In the case of ICE-LITE, these fields are not used; instead, they are defined
134 * as constant values.
135 */
136#define WHIP_SDP_SESSION_ID "4489045141692799359"
137#define WHIP_SDP_CREATOR_IP "127.0.0.1"
138
139/**
140 * Refer to RFC 7675 5.1,
141 *
142 * To prevent expiry of consent, a STUN binding request can be sent periodically.
143 * Implementations SHOULD set a default interval of 5 seconds(5000ms).
144 *
145 * Consent expires after 30 seconds(30000ms).
146 */
147#define WHIP_ICE_CONSENT_CHECK_INTERVAL 5000
148#define WHIP_ICE_CONSENT_EXPIRED_TIMER 30000
149
150/**
151 * RTP history packet size.
152 * Target is buffering 1000ms of RTP history packets.
153 *
154 * bandwidth_bps = (RTP payload bytes) * (RTP history size) * 8
155 * Assumes average RTP payload is 1184 bytes (MTU - SRTP_CHECKSUM_LEN).
156 */
157#define WHIP_RTP_HISTORY_MIN 64 /* around 0.61 Mbps */
158#define WHIP_RTP_HISTORY_DEFAULT 512 /* around 4.85 Mbps */
159#define WHIP_RTP_HISTORY_MAX 2048 /* around 19.40 Mbps */
160
161/* Calculate the elapsed time from starttime to endtime in milliseconds. */
162#define ELAPSED(starttime, endtime) ((float)(endtime - starttime) / 1000)
163
164/* STUN Attribute, comprehension-required range (0x0000-0x7FFF) */
166 STUN_ATTR_USERNAME = 0x0006, /// shared secret response/bind request
167 STUN_ATTR_PRIORITY = 0x0024, /// must be included in a Binding request
168 STUN_ATTR_USE_CANDIDATE = 0x0025, /// bind request
169 STUN_ATTR_MESSAGE_INTEGRITY = 0x0008, /// bind request/response
170 STUN_ATTR_FINGERPRINT = 0x8028, /// rfc5389
171 STUN_ATTR_ICE_CONTROLLING = 0x802A, /// ICE controlling role
172};
173
176
177 /* The initial state. */
179 /* The muxer has sent the offer to the peer. */
181 /* The muxer has received the answer from the peer. */
183 /**
184 * After parsing the answer received from the peer, the muxer negotiates the abilities
185 * in the offer that it generated.
186 */
188 /* The muxer has connected to the peer via UDP. */
190 /* The muxer has sent the ICE request to the peer. */
192 /* The muxer has received the ICE response from the peer. */
194 /* The muxer has finished the DTLS handshake with the peer. */
196 /* The muxer has finished the SRTP setup. */
198 /* The muxer is ready to send/receive media frames. */
200 /* The muxer is failed. */
202};
203
204typedef enum WHIPFlags {
206} WHIPFlags;
207
208typedef struct RtpHistoryItem {
209 uint16_t seq;
210 int size;
211 uint8_t *buf;
213
214typedef struct WHIPContext {
216
217 uint32_t flags;
218 /* The state of the RTC connection. */
220
221 /* Parameters for the input audio and video codecs. */
224
225 /**
226 * The h264_mp4toannexb Bitstream Filter (BSF) bypasses the AnnexB packet;
227 * therefore, it is essential to insert the SPS and PPS before each IDR frame
228 * in such cases.
229 */
231
232 /* The random number generator. */
234
235 /* The ICE username and pwd fragment generated by the muxer. */
238 /* The SSRC of the audio and video stream, generated by the muxer. */
239 uint32_t audio_ssrc;
240 uint32_t video_ssrc;
242
245
247 /* The PT(Payload Type) of stream, generated by the muxer. */
251 /**
252 * This is the SDP offer generated by the muxer based on the codec parameters,
253 * DTLS, and ICE information.
254 */
256
258 uint64_t ice_tie_breaker; // random 64 bit, for ICE-CONTROLLING
259 /* The ICE username and pwd from remote server. */
262 /**
263 * This represents the ICE candidate protocol, priority, host and port.
264 * Currently, we only support one candidate and choose the first UDP candidate.
265 * However, we plan to support multiple candidates in the future.
266 */
268 char *ice_host;
270
271 /* The SDP answer received from the WebRTC server. */
273 /* The resource URL returned in the Location header of WHIP HTTP response. */
275
276 /* These variables represent timestamps used for calculating and tracking the cost. */
287
288 /* The certificate and private key content used for DTLS handshake */
291 /* The fingerprint of certificate, used in SDP offer. */
293 /* remote DTLS cert fingerprint from SDP answer (sha-256). */
295 /**
296 * This represents the material used to build the SRTP master key. It is
297 * generated by DTLS and has the following layout:
298 * 16B 16B 14B 14B
299 * client_key | server_key | client_salt | server_salt
300 */
302
303 /* TODO: Use AVIOContext instead of URLContext */
305
306 /* The SRTP send context, to encrypt outgoing packets. */
311 /* The SRTP receive context, to decrypt incoming packets. */
313
314 /* The UDP transport is used for delivering ICE, DTLS and SRTP packets. */
316 /* The buffer for UDP transmission. */
318
319 /* The timeout in milliseconds for ICE and DTLS handshake. */
321
322 /* The timeout in microseconds for HTTP operations. */
324 /**
325 * The size of RTP packet, should generally be set to MTU.
326 * Note that pion requires a smaller value, for example, 1200.
327 */
329 int ts_buffer_size;/* Underlying protocol send/receive buffer size */
330 /**
331 * The optional Bearer token for WHIP Authorization.
332 * See https://www.ietf.org/archive/id/draft-ietf-wish-whip-08.html#name-authentication-and-authoriz
333 */
335 /* The certificate and private key used for DTLS handshake. */
337 char* key_file;
338
341 uint8_t *hist_pool;
344
345/**
346 * Get or Generate a self-signed certificate and private key for DTLS,
347 * fingerprint for SDP
348 */
350{
351 int ret = 0;
352 WHIPContext *whip = s->priv_data;
353
354 if (whip->cert_file && whip->key_file) {
355 /* Read the private key and certificate from the file. */
356 if ((ret = ff_ssl_read_key_cert(whip->key_file, whip->cert_file,
357 whip->key_buf, sizeof(whip->key_buf),
358 whip->cert_buf, sizeof(whip->cert_buf),
359 &whip->dtls_fingerprint)) < 0) {
360 av_log(s, AV_LOG_ERROR, "Failed to read DTLS certificate from cert=%s, key=%s\n",
361 whip->cert_file, whip->key_file);
362 return ret;
363 }
364 } else {
365 /* Generate a private key to ctx->dtls_pkey and self-signed certificate. */
366 if ((ret = ff_ssl_gen_key_cert(whip->key_buf, sizeof(whip->key_buf),
367 whip->cert_buf, sizeof(whip->cert_buf),
368 &whip->dtls_fingerprint)) < 0) {
369 av_log(s, AV_LOG_ERROR, "Failed to generate DTLS private key and certificate\n");
370 return ret;
371 }
372 }
373
374 return ret;
375}
376
378{
379 int ret = 0;
380 WHIPContext *whip = s->priv_data;
381 int is_dtls_active = whip->flags & WHIP_DTLS_ACTIVE;
383 char buf[256];
384
385 ff_url_join(buf, sizeof(buf), "dtls", NULL, whip->ice_host, whip->ice_port, NULL);
386 av_dict_set_int(&opts, "mtu", whip->pkt_size, 0);
387 if (whip->cert_file) {
388 av_dict_set(&opts, "cert_file", whip->cert_file, 0);
389 } else
390 av_dict_set(&opts, "cert_pem", whip->cert_buf, 0);
391
392 if (whip->key_file) {
393 av_dict_set(&opts, "key_file", whip->key_file, 0);
394 } else
395 av_dict_set(&opts, "key_pem", whip->key_buf, 0);
396 av_dict_set_int(&opts, "external_sock", 1, 0);
397 av_dict_set_int(&opts, "use_srtp", 1, 0);
398 av_dict_set_int(&opts, "listen", is_dtls_active ? 0 : 1, 0);
399 // Do not verify CA
400 av_dict_set_int(&opts, "verify", 0, 0);
401 ret = ffurl_open_whitelist(&whip->dtls_uc, buf, AVIO_FLAG_READ_WRITE, &s->interrupt_callback,
402 &opts, s->protocol_whitelist, s->protocol_blacklist, NULL);
404 if (ret < 0) {
405 av_log(whip, AV_LOG_ERROR, "Failed to open DTLS url:%s\n", buf);
406 goto end;
407 }
408 /* reuse the udp created by whip */
410end:
411 return ret;
412}
413
414/**
415 * Initialize and check the options for the WebRTC muxer.
416 */
418{
419 int ret, ideal_pkt_size = 532;
420 WHIPContext *whip = s->priv_data;
421 uint32_t seed;
422
424
425 ret = certificate_key_init(s);
426 if (ret < 0) {
427 av_log(whip, AV_LOG_ERROR, "Failed to init certificate and key\n");
428 return ret;
429 }
430
431 /* Initialize the random number generator. */
433 av_lfg_init(&whip->rnd, seed);
434
435 /* 64 bit tie breaker for ICE-CONTROLLING (RFC 8445 16.1) */
436 ret = av_random_bytes((uint8_t *)&whip->ice_tie_breaker, sizeof(whip->ice_tie_breaker));
437 if (ret < 0) {
438 av_log(whip, AV_LOG_ERROR, "Couldn't generate random bytes for ICE tie breaker\n");
439 return ret;
440 }
441
442 whip->audio_first_seq = av_lfg_get(&whip->rnd) & 0x0fff;
443 whip->video_first_seq = whip->audio_first_seq + 1;
444
445 if (whip->pkt_size < ideal_pkt_size)
446 av_log(whip, AV_LOG_WARNING, "pkt_size=%d(<%d) is too small, may cause packet loss\n",
447 whip->pkt_size, ideal_pkt_size);
448
449 whip->hist = av_calloc(whip->hist_sz, sizeof(*whip->hist));
450 if (!whip->hist)
451 return AVERROR(ENOMEM);
452
454 if (!whip->hist_pool)
455 return AVERROR(ENOMEM);
456
457 for (int i = 0; i < whip->hist_sz; i++)
458 whip->hist[i].buf = whip->hist_pool + i * (whip->pkt_size - DTLS_SRTP_CHECKSUM_LEN);
459
460 if (whip->state < WHIP_STATE_INIT)
461 whip->state = WHIP_STATE_INIT;
463 av_log(whip, AV_LOG_VERBOSE, "Init state=%d, handshake_timeout=%dms, pkt_size=%d, seed=%d, elapsed=%.2fms\n",
465
466 return 0;
467}
468
469/**
470 * When duplicating a stream, the demuxer has already set the extradata, profile, and
471 * level of the par. Keep in mind that this function will not be invoked since the
472 * profile and level are set.
473 *
474 * When utilizing an encoder, such as libx264, to encode a stream, the extradata in
475 * par->extradata contains the SPS, which includes profile and level information.
476 * However, the profile and level of par remain unspecified. Therefore, it is necessary
477 * to extract the profile and level data from the extradata and assign it to the par's
478 * profile and level. Keep in mind that AVFMT_GLOBALHEADER must be enabled; otherwise,
479 * the extradata will remain empty.
480 */
482{
483 int ret = 0;
484 const uint8_t *r = par->extradata, *r1, *end = par->extradata + par->extradata_size;
485 H264SPS seq, *const sps = &seq;
486 uint32_t state;
487 WHIPContext *whip = s->priv_data;
488
489 if (par->codec_id != AV_CODEC_ID_H264)
490 return ret;
491
492 if (par->profile != AV_PROFILE_UNKNOWN && par->level != AV_LEVEL_UNKNOWN)
493 return ret;
494
495 if (!par->extradata || par->extradata_size <= 0) {
496 av_log(whip, AV_LOG_ERROR, "Unable to parse profile from empty extradata=%p, size=%d\n",
497 par->extradata, par->extradata_size);
498 return AVERROR(EINVAL);
499 }
500
501 while (1) {
503 if (r >= end)
504 break;
505
506 r1 = ff_nal_find_startcode(r, end);
507 if ((state & 0x1f) == H264_NAL_SPS) {
508 ret = ff_avc_decode_sps(sps, r, r1 - r);
509 if (ret < 0) {
510 av_log(whip, AV_LOG_ERROR, "Failed to decode SPS, state=%x, size=%d\n",
511 state, (int)(r1 - r));
512 return ret;
513 }
514
515 av_log(whip, AV_LOG_VERBOSE, "Parse profile=%d, level=%d from SPS\n",
516 sps->profile_idc, sps->level_idc);
517 par->profile = sps->profile_idc;
518 par->level = sps->level_idc;
519 }
520
521 r = r1;
522 }
523
524 return ret;
525}
526
527/**
528 * Parses video SPS/PPS from the extradata of codecpar and checks the codec.
529 * Currently only supports video(h264) and audio(opus). Note that only baseline
530 * and constrained baseline profiles of h264 are supported.
531 *
532 * If the profile is less than 0, the function considers the profile as baseline.
533 * It may need to parse the profile from SPS/PPS. This situation occurs when ingesting
534 * desktop and transcoding.
535 *
536 * @param s Pointer to the AVFormatContext
537 * @returns Returns 0 if successful or AVERROR_xxx in case of an error.
538 *
539 * TODO: FIXME: There is an issue with the timestamp of OPUS audio, especially when
540 * the input is an MP4 file. The timestamp deviates from the expected value of 960,
541 * causing Chrome to play the audio stream with noise. This problem can be replicated
542 * by transcoding a specific file into MP4 format and publishing it using the WHIP
543 * muxer. However, when directly transcoding and publishing through the WHIP muxer,
544 * the issue is not present, and the audio timestamp remains consistent. The root
545 * cause is still unknown, and this comment has been added to address this issue
546 * in the future. Further research is needed to resolve the problem.
547 */
549{
550 int i, ret = 0;
551 WHIPContext *whip = s->priv_data;
552
553 for (i = 0; i < s->nb_streams; i++) {
554 AVCodecParameters *par = s->streams[i]->codecpar;
555 switch (par->codec_type) {
557 whip->video_par = par;
558
559 if (par->video_delay > 0) {
560 av_log(whip, AV_LOG_ERROR, "Unsupported B frames by RTC\n");
562 }
563
564 if ((ret = parse_profile_level(s, par)) < 0) {
565 av_log(whip, AV_LOG_ERROR, "Failed to parse SPS/PPS from extradata\n");
566 return AVERROR(EINVAL);
567 }
568
569 if (par->profile == AV_PROFILE_UNKNOWN) {
570 av_log(whip, AV_LOG_WARNING, "No profile found in extradata, consider baseline\n");
571 return AVERROR(EINVAL);
572 }
573 if (par->level == AV_LEVEL_UNKNOWN) {
574 av_log(whip, AV_LOG_WARNING, "No level found in extradata, consider 3.1\n");
575 return AVERROR(EINVAL);
576 }
577 break;
579 whip->audio_par = par;
580
581 if (par->ch_layout.nb_channels != 2) {
582 av_log(whip, AV_LOG_ERROR, "Unsupported audio channels %d by RTC, choose stereo\n",
585 }
586
587 if (par->sample_rate != 48000) {
588 av_log(whip, AV_LOG_ERROR, "Unsupported audio sample rate %d by RTC, choose 48000\n", par->sample_rate);
590 }
591 break;
592 default:
593 av_unreachable("already checked via FF_OFMT flags");
594 }
595 }
596
597 return ret;
598}
599
600/**
601 * Generate SDP offer according to the codec parameters, DTLS and ICE information.
602 *
603 * Note that we don't use av_sdp_create to generate SDP offer because it doesn't
604 * support DTLS and ICE information.
605 *
606 * @return 0 if OK, AVERROR_xxx on error
607 */
609{
610 int ret = 0, profile_idc = 0, level, profile_iop = 0;
611 const char *acodec_name = NULL, *vcodec_name = NULL;
612 char bundle[4];
613 int bundle_index = 0;
614 AVBPrint bp;
615 WHIPContext *whip = s->priv_data;
616 int is_dtls_active = whip->flags & WHIP_DTLS_ACTIVE;
617
618 /* To prevent a crash during cleanup, always initialize it. */
620
621 if (whip->sdp_offer) {
622 av_log(whip, AV_LOG_ERROR, "SDP offer is already set\n");
623 ret = AVERROR(EINVAL);
624 goto end;
625 }
626
627 snprintf(whip->ice_ufrag_local, sizeof(whip->ice_ufrag_local), "%08x",
628 av_lfg_get(&whip->rnd));
629 snprintf(whip->ice_pwd_local, sizeof(whip->ice_pwd_local), "%08x%08x%08x%08x",
630 av_lfg_get(&whip->rnd), av_lfg_get(&whip->rnd), av_lfg_get(&whip->rnd),
631 av_lfg_get(&whip->rnd));
632
633 whip->audio_ssrc = av_lfg_get(&whip->rnd);
634 whip->video_ssrc = whip->audio_ssrc + 1;
635 whip->video_rtx_ssrc = whip->video_ssrc + 1;
636
640
641 if (whip->audio_par) {
642 bundle[bundle_index++] = '0';
643 bundle[bundle_index++] = ' ';
644 }
645 if (whip->video_par) {
646 bundle[bundle_index++] = '1';
647 bundle[bundle_index++] = ' ';
648 }
649 bundle[bundle_index - 1] = '\0';
650
651 av_bprintf(&bp, ""
652 "v=0\r\n"
653 "o=FFmpeg %s 2 IN IP4 %s\r\n"
654 "s=FFmpegPublishSession\r\n"
655 "t=0 0\r\n"
656 "a=group:BUNDLE %s\r\n"
657 "a=extmap-allow-mixed\r\n"
658 "a=msid-semantic: WMS\r\n",
661 bundle);
662
663 if (whip->audio_par) {
664 if (whip->audio_par->codec_id == AV_CODEC_ID_OPUS)
665 acodec_name = "opus";
666
667 av_bprintf(&bp, ""
668 "m=audio 9 UDP/TLS/RTP/SAVPF %u\r\n"
669 "c=IN IP4 0.0.0.0\r\n"
670 "a=ice-ufrag:%s\r\n"
671 "a=ice-pwd:%s\r\n"
672 "a=fingerprint:sha-256 %s\r\n"
673 "a=setup:%s\r\n"
674 "a=mid:0\r\n"
675 "a=sendonly\r\n"
676 "a=msid:FFmpeg audio\r\n"
677 "a=rtcp-mux\r\n"
678 "a=rtpmap:%u %s/%d/%d\r\n"
679 "a=ssrc:%u cname:FFmpeg\r\n"
680 "a=ssrc:%u msid:FFmpeg audio\r\n",
681 whip->audio_payload_type,
682 whip->ice_ufrag_local,
683 whip->ice_pwd_local,
684 whip->dtls_fingerprint,
685 is_dtls_active ? "active" : "passive",
686 whip->audio_payload_type,
687 acodec_name,
688 whip->audio_par->sample_rate,
690 whip->audio_ssrc,
691 whip->audio_ssrc);
692 }
693
694 if (whip->video_par) {
695 level = whip->video_par->level;
696 if (whip->video_par->codec_id == AV_CODEC_ID_H264) {
697 vcodec_name = "H264";
698 profile_iop |= whip->video_par->profile & AV_PROFILE_H264_CONSTRAINED ? 1 << 6 : 0;
699 profile_iop |= whip->video_par->profile & AV_PROFILE_H264_INTRA ? 1 << 4 : 0;
700 profile_idc = whip->video_par->profile & 0x00ff;
701 }
702
703 av_bprintf(&bp, ""
704 "m=video 9 UDP/TLS/RTP/SAVPF %u %u\r\n"
705 "c=IN IP4 0.0.0.0\r\n"
706 "a=ice-ufrag:%s\r\n"
707 "a=ice-pwd:%s\r\n"
708 "a=fingerprint:sha-256 %s\r\n"
709 "a=setup:%s\r\n"
710 "a=mid:1\r\n"
711 "a=sendonly\r\n"
712 "a=msid:FFmpeg video\r\n"
713 "a=rtcp-mux\r\n"
714 "a=rtcp-rsize\r\n"
715 "a=rtpmap:%u %s/90000\r\n"
716 "a=fmtp:%u level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=%02x%02x%02x\r\n"
717 "a=rtcp-fb:%u nack\r\n"
718 "a=rtpmap:%u rtx/90000\r\n"
719 "a=fmtp:%u apt=%u\r\n"
720 "a=ssrc-group:FID %u %u\r\n"
721 "a=ssrc:%u cname:FFmpeg\r\n"
722 "a=ssrc:%u msid:FFmpeg video\r\n",
723 whip->video_payload_type,
725 whip->ice_ufrag_local,
726 whip->ice_pwd_local,
727 whip->dtls_fingerprint,
728 is_dtls_active ? "active" : "passive",
729 whip->video_payload_type,
730 vcodec_name,
731 whip->video_payload_type,
733 profile_iop,
734 level,
735 whip->video_payload_type,
738 whip->video_payload_type,
739 whip->video_ssrc,
740 whip->video_rtx_ssrc,
741 whip->video_ssrc,
742 whip->video_ssrc);
743 }
744
745 if (!av_bprint_is_complete(&bp)) {
746 av_log(whip, AV_LOG_ERROR, "Offer exceed max %d, %s\n", MAX_SDP_SIZE, bp.str);
747 ret = AVERROR(EIO);
748 goto end;
749 }
750
751 whip->sdp_offer = av_strdup(bp.str);
752 if (!whip->sdp_offer) {
753 ret = AVERROR(ENOMEM);
754 goto end;
755 }
756
757 if (whip->state < WHIP_STATE_OFFER)
758 whip->state = WHIP_STATE_OFFER;
760 av_log(whip, AV_LOG_VERBOSE, "Generated state=%d, offer: %s\n", whip->state, whip->sdp_offer);
761
762end:
764 return ret;
765}
766
767/**
768 * Exchange SDP offer with WebRTC peer to get the answer.
769 *
770 * @return 0 if OK, AVERROR_xxx on error
771 */
773{
774 int ret;
775 char buf[MAX_URL_SIZE];
776 AVBPrint bp;
777 WHIPContext *whip = s->priv_data;
778 /* The URL context is an HTTP transport layer for the WHIP protocol. */
779 URLContext *whip_uc = NULL;
781 char *hex_data = NULL;
782 const char *proto_name = avio_find_protocol_name(s->url);
783
784 /* To prevent a crash during cleanup, always initialize it. */
786
787 if (!av_strstart(proto_name, "http", NULL)) {
788 av_log(whip, AV_LOG_ERROR, "Protocol %s is not supported by RTC, choose http, url is %s\n",
789 proto_name, s->url);
790 ret = AVERROR(EINVAL);
791 goto end;
792 }
793
794 if (!whip->sdp_offer || !*whip->sdp_offer) {
795 av_log(whip, AV_LOG_ERROR, "No offer to exchange\n");
796 ret = AVERROR(EINVAL);
797 goto end;
798 }
799
800 ret = snprintf(buf, sizeof(buf), "Cache-Control: no-cache\r\nContent-Type: application/sdp\r\n");
801 if (whip->authorization)
802 ret += snprintf(buf + ret, sizeof(buf) - ret, "Authorization: Bearer %s\r\n", whip->authorization);
803 if (ret <= 0 || ret >= sizeof(buf)) {
804 av_log(whip, AV_LOG_ERROR, "Failed to generate headers, size=%d, %s\n", ret, buf);
805 ret = AVERROR(EINVAL);
806 goto end;
807 }
808
809 av_dict_set(&opts, "headers", buf, 0);
810 av_dict_set_int(&opts, "chunked_post", 0, 0);
811
812 if (whip->timeout >= 0)
813 av_dict_set_int(&opts, "timeout", whip->timeout, 0);
814
815 const size_t sdp_offer_len = strlen(whip->sdp_offer);
816 hex_data = av_malloc(2 * sdp_offer_len + 1);
817 if (!hex_data) {
818 ret = AVERROR(ENOMEM);
819 goto end;
820 }
821 ff_data_to_hex(hex_data, whip->sdp_offer, sdp_offer_len, 0);
822 av_dict_set(&opts, "post_data", hex_data, AV_DICT_DONT_STRDUP_VAL);
823
824 ret = ffurl_open_whitelist(&whip_uc, s->url, AVIO_FLAG_READ_WRITE, &s->interrupt_callback,
825 &opts, s->protocol_whitelist, s->protocol_blacklist, NULL);
826 if (ret < 0) {
827 av_log(whip, AV_LOG_ERROR, "Failed to request url=%s, offer: %s\n", s->url, whip->sdp_offer);
828 goto end;
829 }
830
831 if (ff_http_get_new_location(whip_uc)) {
833 if (!whip->whip_resource_url) {
834 ret = AVERROR(ENOMEM);
835 goto end;
836 }
837 }
838
839 while (1) {
840 ret = ffurl_read(whip_uc, buf, sizeof(buf));
841 if (ret == AVERROR_EOF) {
842 /* Reset the error because we read all response as answer util EOF. */
843 ret = 0;
844 break;
845 }
846 if (ret <= 0) {
847 av_log(whip, AV_LOG_ERROR, "Failed to read response from url=%s, offer is %s, answer is %s\n",
848 s->url, whip->sdp_offer, whip->sdp_answer);
849 goto end;
850 }
851
852 av_bprintf(&bp, "%.*s", ret, buf);
853 if (!av_bprint_is_complete(&bp)) {
854 av_log(whip, AV_LOG_ERROR, "Answer exceed max size %d, %.*s, %s\n", MAX_SDP_SIZE, ret, buf, bp.str);
855 ret = AVERROR(EIO);
856 goto end;
857 }
858 }
859
860 if (!av_strstart(bp.str, "v=", NULL)) {
861 av_log(whip, AV_LOG_ERROR, "Invalid answer: %s\n", bp.str);
862 ret = AVERROR(EINVAL);
863 goto end;
864 }
865
866 whip->sdp_answer = av_strdup(bp.str);
867 if (!whip->sdp_answer) {
868 ret = AVERROR(ENOMEM);
869 goto end;
870 }
871
872 if (whip->state < WHIP_STATE_ANSWER)
873 whip->state = WHIP_STATE_ANSWER;
874 av_log(whip, AV_LOG_VERBOSE, "Got state=%d, answer: %s\n", whip->state, whip->sdp_answer);
875
876end:
877 ffurl_closep(&whip_uc);
880 return ret;
881}
882
883/**
884 * Parses the ICE ufrag, pwd, and candidates from the SDP answer.
885 *
886 * This function is used to extract the ICE ufrag, pwd, and candidates from the SDP answer.
887 * It returns an error if any of these fields is NULL. The function only uses the first
888 * candidate if there are multiple candidates. However, support for multiple candidates
889 * will be added in the future.
890 *
891 * @param s Pointer to the AVFormatContext
892 * @returns Returns 0 if successful or AVERROR_xxx if an error occurs.
893 */
895{
896 int ret = 0;
897 AVIOContext *pb;
898 char line[MAX_URL_SIZE];
899 const char *ptr;
900 int i;
901 WHIPContext *whip = s->priv_data;
902
903 if (!whip->sdp_answer || !strlen(whip->sdp_answer)) {
904 av_log(whip, AV_LOG_ERROR, "No answer to parse\n");
905 return AVERROR(EINVAL);
906 }
907
908 pb = avio_alloc_context(whip->sdp_answer, strlen(whip->sdp_answer), 0, NULL, NULL, NULL, NULL);
909 if (!pb)
910 return AVERROR(ENOMEM);
911
912 for (i = 0; !avio_feof(pb); i++) {
913 ff_get_chomp_line(pb, line, sizeof(line));
914 if (av_strstart(line, "a=ice-lite", &ptr))
915 whip->is_peer_ice_lite = 1;
916 if (av_strstart(line, "a=ice-ufrag:", &ptr) && !whip->ice_ufrag_remote) {
917 whip->ice_ufrag_remote = av_strdup(ptr);
918 if (!whip->ice_ufrag_remote) {
919 ret = AVERROR(ENOMEM);
920 goto end;
921 }
922 } else if (av_strstart(line, "a=ice-pwd:", &ptr) && !whip->ice_pwd_remote) {
923 whip->ice_pwd_remote = av_strdup(ptr);
924 if (!whip->ice_pwd_remote) {
925 ret = AVERROR(ENOMEM);
926 goto end;
927 }
928 } else if (av_strstart(line, "a=fingerprint:", &ptr) && !whip->remote_fingerprint) {
929 /* SDP a=fingerprint format is "<algo> <hex:hex:...>". Skip
930 * the algo token, store the hex string for post-handshake compare. */
931 const char *space = strchr(ptr, ' ');
932 if (space) {
934 if (!whip->remote_fingerprint) {
935 ret = AVERROR(ENOMEM);
936 goto end;
937 }
938 }
939 } else if (av_strstart(line, "a=candidate:", &ptr) && !whip->ice_protocol) {
940 if (ptr && av_stristr(ptr, "host")) {
941 /* Refer to RFC 5245 15.1 */
942 char foundation[33], protocol[17], host[129];
943 int component_id, priority, port;
944 ret = sscanf(ptr, "%32s %d %16s %d %128s %d typ host", foundation, &component_id, protocol, &priority, host, &port);
945 if (ret != 6) {
946 av_log(whip, AV_LOG_ERROR, "Failed %d to parse line %d %s from %s\n",
947 ret, i, line, whip->sdp_answer);
948 ret = AVERROR(EIO);
949 goto end;
950 }
951
952 if (av_strcasecmp(protocol, "udp")) {
953 av_log(whip, AV_LOG_ERROR, "Protocol %s is not supported by RTC, choose udp, line %d %s of %s\n",
954 protocol, i, line, whip->sdp_answer);
955 ret = AVERROR(EIO);
956 goto end;
957 }
958
959 whip->ice_protocol = av_strdup(protocol);
960 whip->ice_host = av_strdup(host);
961 whip->ice_port = port;
962 if (!whip->ice_protocol || !whip->ice_host) {
963 ret = AVERROR(ENOMEM);
964 goto end;
965 }
966 }
967 }
968 }
969
970 if (!whip->ice_pwd_remote || !strlen(whip->ice_pwd_remote)) {
971 av_log(whip, AV_LOG_ERROR, "No remote ice pwd parsed from %s\n", whip->sdp_answer);
972 ret = AVERROR(EINVAL);
973 goto end;
974 }
975
976 if (!whip->ice_ufrag_remote || !strlen(whip->ice_ufrag_remote)) {
977 av_log(whip, AV_LOG_ERROR, "No remote ice ufrag parsed from %s\n", whip->sdp_answer);
978 ret = AVERROR(EINVAL);
979 goto end;
980 }
981
982 if (!whip->ice_protocol || !whip->ice_host || !whip->ice_port) {
983 av_log(whip, AV_LOG_ERROR, "No ice candidate parsed from %s\n", whip->sdp_answer);
984 ret = AVERROR(EINVAL);
985 goto end;
986 }
987
988 /* per RFC 8829/8842, SDP answer MUST carry a=fingerprint and that
989 * fingerprint MUST match the DTLS peer certificate. Without it, an
990 * on-path attacker can complete DTLS with an arbitrary self-signed
991 * certificate and the resulting SRTP session is unauthenticated. */
992 if (!whip->remote_fingerprint || !strlen(whip->remote_fingerprint)) {
993 av_log(whip, AV_LOG_ERROR,
994 "No remote DTLS fingerprint in SDP answer; refusing unauthenticated session\n");
995 ret = AVERROR(EINVAL);
996 goto end;
997 }
998
999 if (whip->state < WHIP_STATE_NEGOTIATED)
1002 av_log(whip, AV_LOG_VERBOSE, "SDP state=%d, offer=%zuB, answer=%zuB, ufrag=%s, pwd=%zuB, transport=%s://%s:%d, elapsed=%.2fms\n",
1003 whip->state, strlen(whip->sdp_offer), strlen(whip->sdp_answer), whip->ice_ufrag_remote, strlen(whip->ice_pwd_remote),
1005
1006end:
1007 avio_context_free(&pb);
1008 return ret;
1009}
1010
1011/**
1012 * Creates and marshals an ICE binding request packet.
1013 *
1014 * This function creates and marshals an ICE binding request packet. The function only
1015 * generates the username attribute and does not include goog-network-info,
1016 * use-candidate. However, some of these attributes may be added in the future.
1017 *
1018 * @param s Pointer to the AVFormatContext
1019 * @param buf Pointer to memory buffer to store the request packet
1020 * @param buf_size Size of the memory buffer
1021 * @param request_size Pointer to an integer that receives the size of the request packet
1022 * @return Returns 0 if successful or AVERROR_xxx if an error occurs.
1023 */
1024static int ice_create_request(AVFormatContext *s, uint8_t *buf, int buf_size, int *request_size)
1025{
1026 int ret, size, crc32;
1027 char username[128];
1028 AVIOContext *pb = NULL;
1029 AVHMAC *hmac = NULL;
1030 WHIPContext *whip = s->priv_data;
1031
1032 pb = avio_alloc_context(buf, buf_size, 1, NULL, NULL, NULL, NULL);
1033 if (!pb)
1034 return AVERROR(ENOMEM);
1035
1037 if (!hmac) {
1038 ret = AVERROR(ENOMEM);
1039 goto end;
1040 }
1041
1042 /* Write 20 bytes header */
1043 avio_wb16(pb, 0x0001); /* STUN binding request */
1044 avio_wb16(pb, 0); /* length */
1045 avio_wb32(pb, STUN_MAGIC_COOKIE); /* magic cookie */
1046 avio_wb32(pb, av_lfg_get(&whip->rnd)); /* transaction ID */
1047 avio_wb32(pb, av_lfg_get(&whip->rnd)); /* transaction ID */
1048 avio_wb32(pb, av_lfg_get(&whip->rnd)); /* transaction ID */
1049
1050 /* The username is the concatenation of the two ICE ufrag */
1051 ret = snprintf(username, sizeof(username), "%s:%s", whip->ice_ufrag_remote, whip->ice_ufrag_local);
1052 if (ret <= 0 || ret >= sizeof(username)) {
1053 av_log(whip, AV_LOG_ERROR, "Failed to build username %s:%s, max=%zu, ret=%d\n",
1054 whip->ice_ufrag_remote, whip->ice_ufrag_local, sizeof(username), ret);
1055 ret = AVERROR(EIO);
1056 goto end;
1057 }
1058
1059 /* Write the username attribute */
1060 avio_wb16(pb, STUN_ATTR_USERNAME); /* attribute type username */
1061 avio_wb16(pb, ret); /* size of username */
1062 avio_write(pb, username, ret); /* bytes of username */
1063 ffio_fill(pb, 0, (4 - (ret % 4)) % 4); /* padding */
1064
1065 /* Write the use-candidate attribute */
1066 avio_wb16(pb, STUN_ATTR_USE_CANDIDATE); /* attribute type use-candidate */
1067 avio_wb16(pb, 0); /* size of use-candidate */
1068
1070 avio_wb16(pb, 4);
1072
1074 avio_wb16(pb, 8);
1075 avio_wb64(pb, whip->ice_tie_breaker);
1076
1077 /* Build and update message integrity */
1078 avio_wb16(pb, STUN_ATTR_MESSAGE_INTEGRITY); /* attribute type message integrity */
1079 avio_wb16(pb, 20); /* size of message integrity */
1080 ffio_fill(pb, 0, 20); /* fill with zero to directly write and skip it */
1081 size = avio_tell(pb);
1082 buf[2] = (size - 20) >> 8;
1083 buf[3] = (size - 20) & 0xFF;
1084 av_hmac_init(hmac, whip->ice_pwd_remote, strlen(whip->ice_pwd_remote));
1085 av_hmac_update(hmac, buf, size - 24);
1086 av_hmac_final(hmac, buf + size - 20, 20);
1087
1088 /* Write the fingerprint attribute */
1089 avio_wb16(pb, STUN_ATTR_FINGERPRINT); /* attribute type fingerprint */
1090 avio_wb16(pb, 4); /* size of fingerprint */
1091 ffio_fill(pb, 0, 4); /* fill with zero to directly write and skip it */
1092 size = avio_tell(pb);
1093 buf[2] = (size - 20) >> 8;
1094 buf[3] = (size - 20) & 0xFF;
1095 /* Refer to the av_hash_alloc("CRC32"), av_hash_init and av_hash_final */
1096 crc32 = av_crc(av_crc_get_table(AV_CRC_32_IEEE_LE), 0xFFFFFFFF, buf, size - 8) ^ 0xFFFFFFFF;
1097 avio_skip(pb, -4);
1098 avio_wb32(pb, crc32 ^ 0x5354554E); /* xor with "STUN" */
1099
1100 *request_size = size;
1101
1102end:
1103 avio_context_free(&pb);
1104 av_hmac_free(hmac);
1105 return ret;
1106}
1107
1108/**
1109 * Create an ICE binding response.
1110 *
1111 * This function generates an ICE binding response and writes it to the provided
1112 * buffer. The response is signed using the local password for message integrity.
1113 *
1114 * @param s Pointer to the AVFormatContext structure.
1115 * @param tid Pointer to the transaction ID of the binding request. The tid_size should be 12.
1116 * @param tid_size The size of the transaction ID, should be 12.
1117 * @param buf Pointer to the buffer where the response will be written.
1118 * @param buf_size The size of the buffer provided for the response.
1119 * @param response_size Pointer to an integer that will store the size of the generated response.
1120 * @return Returns 0 if successful or AVERROR_xxx if an error occurs.
1121 */
1122static int ice_create_response(AVFormatContext *s, char *tid, int tid_size, uint8_t *buf, int buf_size, int *response_size)
1123{
1124 int ret = 0, size, crc32;
1125 AVIOContext *pb = NULL;
1126 AVHMAC *hmac = NULL;
1127 WHIPContext *whip = s->priv_data;
1128
1129 if (tid_size != 12) {
1130 av_log(whip, AV_LOG_ERROR, "Invalid transaction ID size. Expected 12, got %d\n", tid_size);
1131 return AVERROR(EINVAL);
1132 }
1133
1134 pb = avio_alloc_context(buf, buf_size, 1, NULL, NULL, NULL, NULL);
1135 if (!pb)
1136 return AVERROR(ENOMEM);
1137
1139 if (!hmac) {
1140 ret = AVERROR(ENOMEM);
1141 goto end;
1142 }
1143
1144 /* Write 20 bytes header */
1145 avio_wb16(pb, 0x0101); /* STUN binding response */
1146 avio_wb16(pb, 0); /* length */
1147 avio_wb32(pb, STUN_MAGIC_COOKIE); /* magic cookie */
1148 avio_write(pb, tid, tid_size); /* transaction ID */
1149
1150 /* Build and update message integrity */
1151 avio_wb16(pb, STUN_ATTR_MESSAGE_INTEGRITY); /* attribute type message integrity */
1152 avio_wb16(pb, 20); /* size of message integrity */
1153 ffio_fill(pb, 0, 20); /* fill with zero to directly write and skip it */
1154 size = avio_tell(pb);
1155 buf[2] = (size - 20) >> 8;
1156 buf[3] = (size - 20) & 0xFF;
1157 av_hmac_init(hmac, whip->ice_pwd_local, strlen(whip->ice_pwd_local));
1158 av_hmac_update(hmac, buf, size - 24);
1159 av_hmac_final(hmac, buf + size - 20, 20);
1160
1161 /* Write the fingerprint attribute */
1162 avio_wb16(pb, STUN_ATTR_FINGERPRINT); /* attribute type fingerprint */
1163 avio_wb16(pb, 4); /* size of fingerprint */
1164 ffio_fill(pb, 0, 4); /* fill with zero to directly write and skip it */
1165 size = avio_tell(pb);
1166 buf[2] = (size - 20) >> 8;
1167 buf[3] = (size - 20) & 0xFF;
1168 /* Refer to the av_hash_alloc("CRC32"), av_hash_init and av_hash_final */
1169 crc32 = av_crc(av_crc_get_table(AV_CRC_32_IEEE_LE), 0xFFFFFFFF, buf, size - 8) ^ 0xFFFFFFFF;
1170 avio_skip(pb, -4);
1171 avio_wb32(pb, crc32 ^ 0x5354554E); /* xor with "STUN" */
1172
1173 *response_size = size;
1174
1175end:
1176 avio_context_free(&pb);
1177 av_hmac_free(hmac);
1178 return ret;
1179}
1180
1181/**
1182 * A Binding request has class=0b00 (request) and method=0b000000000001 (Binding)
1183 * and is encoded into the first 16 bits as 0x0001.
1184 * See https://datatracker.ietf.org/doc/html/rfc5389#section-6
1185 */
1186static int ice_is_binding_request(uint8_t *b, int size)
1187{
1188 return size >= ICE_STUN_HEADER_SIZE && AV_RB16(&b[0]) == 0x0001;
1189}
1190
1191/**
1192 * A Binding response has class=0b10 (success response) and method=0b000000000001,
1193 * and is encoded into the first 16 bits as 0x0101.
1194 */
1195static int ice_is_binding_response(uint8_t *b, int size)
1196{
1197 return size >= ICE_STUN_HEADER_SIZE && AV_RB16(&b[0]) == 0x0101;
1198}
1199
1200/**
1201 * In RTP packets, the first byte is represented as 0b10xxxxxx, where the initial
1202 * two bits (0b10) indicate the RTP version,
1203 * see https://www.rfc-editor.org/rfc/rfc3550#section-5.1
1204 * The RTCP packet header is similar to RTP,
1205 * see https://www.rfc-editor.org/rfc/rfc3550#section-6.4.1
1206 */
1207static int media_is_rtp_rtcp(const uint8_t *b, int size)
1208{
1209 return size >= WHIP_RTP_HEADER_SIZE && (b[0] & 0xC0) == 0x80;
1210}
1211
1212/* Whether the packet is RTCP. */
1213static int media_is_rtcp(const uint8_t *b, int size)
1214{
1215 return size >= WHIP_RTP_HEADER_SIZE && b[1] >= WHIP_RTCP_PT_START && b[1] <= WHIP_RTCP_PT_END;
1216}
1217
1218/**
1219 * This function handles incoming binding request messages by responding to them.
1220 * If the message is not a binding request, it will be ignored.
1221 */
1222static int ice_handle_binding_request(AVFormatContext *s, char *buf, int buf_size)
1223{
1224 int ret = 0, size;
1225 char tid[12];
1226 WHIPContext *whip = s->priv_data;
1227
1228 /* Ignore if not a binding request. */
1229 if (!ice_is_binding_request(buf, buf_size))
1230 return ret;
1231
1232 if (buf_size < ICE_STUN_HEADER_SIZE) {
1233 av_log(whip, AV_LOG_ERROR, "Invalid STUN message, expected at least %d, got %d\n",
1234 ICE_STUN_HEADER_SIZE, buf_size);
1235 return AVERROR(EINVAL);
1236 }
1237
1238 /* Parse transaction id from binding request in buf. */
1239 memcpy(tid, buf + 8, 12);
1240
1241 /* Build the STUN binding response. */
1242 ret = ice_create_response(s, tid, sizeof(tid), whip->buf, sizeof(whip->buf), &size);
1243 if (ret < 0) {
1244 av_log(whip, AV_LOG_ERROR, "Failed to create STUN binding response, size=%d\n", size);
1245 return ret;
1246 }
1247
1248 ret = ffurl_write(whip->udp, whip->buf, size);
1249 if (ret < 0) {
1250 av_log(whip, AV_LOG_ERROR, "Failed to send STUN binding response, size=%d\n", size);
1251 return ret;
1252 }
1253
1254 return 0;
1255}
1256
1257/**
1258 * To establish a connection with the UDP server, we utilize ICE-LITE in a Client-Server
1259 * mode. In this setup, FFmpeg acts as the UDP client, while the peer functions as the
1260 * UDP server.
1261 */
1263{
1264 int ret = 0;
1265 char url[256];
1267 WHIPContext *whip = s->priv_data;
1268
1269 /* Build UDP URL and create the UDP context as transport. */
1270 ff_url_join(url, sizeof(url), "udp", NULL, whip->ice_host, whip->ice_port, NULL);
1271
1272 av_dict_set_int(&opts, "connect", 1, 0);
1273 av_dict_set_int(&opts, "fifo_size", 0, 0);
1274 /* Pass through the pkt_size and buffer_size to underling protocol */
1275 av_dict_set_int(&opts, "pkt_size", whip->pkt_size, 0);
1276 av_dict_set_int(&opts, "buffer_size", whip->ts_buffer_size, 0);
1277
1278 ret = ffurl_open_whitelist(&whip->udp, url, AVIO_FLAG_WRITE, &s->interrupt_callback,
1279 &opts, s->protocol_whitelist, s->protocol_blacklist, NULL);
1280 if (ret < 0) {
1281 av_log(whip, AV_LOG_ERROR, "Failed to connect udp://%s:%d\n", whip->ice_host, whip->ice_port);
1282 goto end;
1283 }
1284
1285 /* Make the socket non-blocking, set to READ and WRITE mode after connected */
1288
1289 if (whip->state < WHIP_STATE_UDP_CONNECTED)
1292 av_log(whip, AV_LOG_VERBOSE, "UDP state=%d, elapsed=%.2fms, connected to udp://%s:%d\n",
1293 whip->state, ELAPSED(whip->whip_starttime, av_gettime_relative()), whip->ice_host, whip->ice_port);
1294
1295end:
1297 return ret;
1298}
1299
1301{
1302 int ret = 0, size, i;
1303 int64_t starttime = av_gettime_relative(), now;
1304 WHIPContext *whip = s->priv_data;
1305 int is_dtls_active = whip->flags & WHIP_DTLS_ACTIVE;
1306
1307 if (whip->state < WHIP_STATE_UDP_CONNECTED || !whip->udp) {
1308 av_log(whip, AV_LOG_ERROR, "UDP not connected, state=%d, udp=%p\n", whip->state, whip->udp);
1309 return AVERROR(EINVAL);
1310 }
1311
1312 while (1) {
1313 if (whip->state <= WHIP_STATE_ICE_CONNECTING) {
1314 /* Build the STUN binding request. */
1315 ret = ice_create_request(s, whip->buf, sizeof(whip->buf), &size);
1316 if (ret < 0) {
1317 av_log(whip, AV_LOG_ERROR, "Failed to create STUN binding request, size=%d\n", size);
1318 goto end;
1319 }
1320
1321 ret = ffurl_write(whip->udp, whip->buf, size);
1322 if (ret < 0) {
1323 av_log(whip, AV_LOG_ERROR, "Failed to send STUN binding request, size=%d\n", size);
1324 goto end;
1325 }
1326
1327 if (whip->state < WHIP_STATE_ICE_CONNECTING)
1329 }
1330
1331next_packet:
1332 if (whip->state >= WHIP_STATE_DTLS_FINISHED)
1333 /* DTLS handshake is done, exit the loop. */
1334 break;
1335
1336 now = av_gettime_relative();
1337 if (now - starttime >= whip->handshake_timeout * WHIP_US_PER_MS) {
1338 av_log(whip, AV_LOG_ERROR, "DTLS handshake timeout=%dms, cost=%.2fms, elapsed=%.2fms, state=%d\n",
1339 whip->handshake_timeout, ELAPSED(starttime, now), ELAPSED(whip->whip_starttime, now), whip->state);
1340 ret = AVERROR(ETIMEDOUT);
1341 goto end;
1342 }
1343
1344 /* Read the STUN or DTLS messages from peer. */
1345 for (i = 0; i < ICE_DTLS_READ_MAX_RETRY; i++) {
1346 if (whip->state > WHIP_STATE_ICE_CONNECTED)
1347 break;
1348 ret = ffurl_read(whip->udp, whip->buf, sizeof(whip->buf));
1349 if (ret > 0)
1350 break;
1351 if (ret == AVERROR(EAGAIN)) {
1353 continue;
1354 }
1355 if (is_dtls_active)
1356 break;
1357 av_log(whip, AV_LOG_ERROR, "Failed to read message\n");
1358 goto end;
1359 }
1360
1361 /* Handle the ICE binding response. */
1362 if (ice_is_binding_response(whip->buf, ret)) {
1363 if (whip->state < WHIP_STATE_ICE_CONNECTED) {
1364 if (whip->is_peer_ice_lite)
1366 }
1367 goto next_packet;
1368 }
1369
1370 /* When a binding request is received, it is necessary to respond immediately. */
1371 if (ice_is_binding_request(whip->buf, ret)) {
1372 if ((ret = ice_handle_binding_request(s, whip->buf, ret)) < 0)
1373 goto end;
1374 goto next_packet;
1375 }
1376
1377 /* Handle DTLS handshake */
1378 if (ff_is_dtls_packet(whip->buf, ret) || is_dtls_active) {
1380 /* Start consent timer when ICE selected */
1383 av_log(whip, AV_LOG_VERBOSE, "ICE STUN ok, state=%d, url=udp://%s:%d, location=%s, username=%s:%s, res=%dB, elapsed=%.2fms\n",
1384 whip->state, whip->ice_host, whip->ice_port, whip->whip_resource_url ? whip->whip_resource_url : "",
1385 whip->ice_ufrag_remote, whip->ice_ufrag_local, ret, ELAPSED(whip->whip_starttime, whip->whip_ice_time));
1386
1387 ret = dtls_initialize(s);
1388 if (ret < 0)
1389 goto end;
1390 ret = ffurl_handshake(whip->dtls_uc);
1391 if (ret < 0) {
1392 whip->state = WHIP_STATE_FAILED;
1393 av_log(whip, AV_LOG_ERROR, "DTLS session failed\n");
1394 goto end;
1395 }
1396 if (!ret) {
1399 av_log(whip, AV_LOG_VERBOSE, "DTLS handshake is done, elapsed=%.2fms\n",
1400 ELAPSED(whip->whip_starttime, whip->whip_dtls_time));
1401 }
1402 goto next_packet;
1403 }
1404 }
1405
1406end:
1407 return ret;
1408}
1409
1410/**
1411 * Establish the SRTP context using the keying material exported from DTLS.
1412 *
1413 * Create separate SRTP contexts for sending video and audio, as their sequences differ
1414 * and should not share a single context. Generate a single SRTP context for receiving
1415 * RTCP only.
1416 *
1417 * @return 0 if OK, AVERROR_xxx on error
1418 */
1420{
1421 int ret;
1422 char recv_key[DTLS_SRTP_KEY_LEN + DTLS_SRTP_SALT_LEN];
1423 char send_key[DTLS_SRTP_KEY_LEN + DTLS_SRTP_SALT_LEN];
1425 /**
1426 * The profile for OpenSSL's SRTP is SRTP_AES128_CM_SHA1_80, see ssl/d1_srtp.c.
1427 * The profile for FFmpeg's SRTP is SRTP_AES128_CM_HMAC_SHA1_80, see libavformat/srtp.c.
1428 */
1429 const char* suite = "SRTP_AES128_CM_HMAC_SHA1_80";
1430 WHIPContext *whip = s->priv_data;
1431 int is_dtls_active = whip->flags & WHIP_DTLS_ACTIVE;
1432 char *cp = is_dtls_active ? send_key : recv_key;
1433 char *sp = is_dtls_active ? recv_key : send_key;
1434
1436 if (ret < 0)
1437 goto end;
1438 /**
1439 * This represents the material used to build the SRTP master key. It is
1440 * generated by DTLS and has the following layout:
1441 * 16B 16B 14B 14B
1442 * client_key | server_key | client_salt | server_salt
1443 */
1444 char *client_key = whip->dtls_srtp_materials;
1445 char *server_key = whip->dtls_srtp_materials + DTLS_SRTP_KEY_LEN;
1446 char *client_salt = server_key + DTLS_SRTP_KEY_LEN;
1447 char *server_salt = client_salt + DTLS_SRTP_SALT_LEN;
1448
1449 memcpy(cp, client_key, DTLS_SRTP_KEY_LEN);
1450 memcpy(cp + DTLS_SRTP_KEY_LEN, client_salt, DTLS_SRTP_SALT_LEN);
1451
1452 memcpy(sp, server_key, DTLS_SRTP_KEY_LEN);
1453 memcpy(sp + DTLS_SRTP_KEY_LEN, server_salt, DTLS_SRTP_SALT_LEN);
1454
1455 /* Setup SRTP context for outgoing packets */
1456 if (!av_base64_encode(buf, sizeof(buf), send_key, sizeof(send_key))) {
1457 av_log(whip, AV_LOG_ERROR, "Failed to encode send key\n");
1458 ret = AVERROR(EIO);
1459 goto end;
1460 }
1461
1462 ret = ff_srtp_set_crypto(&whip->srtp_audio_send, suite, buf);
1463 if (ret < 0) {
1464 av_log(whip, AV_LOG_ERROR, "Failed to set crypto for audio send\n");
1465 goto end;
1466 }
1467
1468 ret = ff_srtp_set_crypto(&whip->srtp_video_send, suite, buf);
1469 if (ret < 0) {
1470 av_log(whip, AV_LOG_ERROR, "Failed to set crypto for video send\n");
1471 goto end;
1472 }
1473
1474 ret = ff_srtp_set_crypto(&whip->srtp_video_rtx_send, suite, buf);
1475 if (ret < 0) {
1476 av_log(whip, AV_LOG_ERROR, "Failed to set crypto for video rtx send\n");
1477 goto end;
1478 }
1479
1480 ret = ff_srtp_set_crypto(&whip->srtp_rtcp_send, suite, buf);
1481 if (ret < 0) {
1482 av_log(whip, AV_LOG_ERROR, "Failed to set crypto for rtcp send\n");
1483 goto end;
1484 }
1485
1486 /* Setup SRTP context for incoming packets */
1487 if (!av_base64_encode(buf, sizeof(buf), recv_key, sizeof(recv_key))) {
1488 av_log(whip, AV_LOG_ERROR, "Failed to encode recv key\n");
1489 ret = AVERROR(EIO);
1490 goto end;
1491 }
1492
1493 ret = ff_srtp_set_crypto(&whip->srtp_recv, suite, buf);
1494 if (ret < 0) {
1495 av_log(whip, AV_LOG_ERROR, "Failed to set crypto for recv\n");
1496 goto end;
1497 }
1498
1499 if (whip->state < WHIP_STATE_SRTP_FINISHED)
1502 av_log(whip, AV_LOG_VERBOSE, "SRTP setup done, state=%d, suite=%s, key=%zuB, elapsed=%.2fms\n",
1503 whip->state, suite, sizeof(send_key), ELAPSED(whip->whip_starttime, av_gettime_relative()));
1504
1505end:
1506 return ret;
1507}
1508
1509static int rtp_history_store(WHIPContext *whip, const uint8_t *buf, int size)
1510{
1511 uint16_t seq = AV_RB16(buf + 2);
1512 uint32_t pos = ((uint32_t)seq - (uint32_t)whip->video_first_seq) % (uint32_t)whip->hist_sz;
1513 RtpHistoryItem *it = &whip->hist[pos];
1514 if (size > whip->pkt_size - DTLS_SRTP_CHECKSUM_LEN)
1515 return AVERROR_INVALIDDATA;
1516 memcpy(it->buf, buf, size);
1517 it->size = size;
1518 it->seq = seq;
1519
1520 whip->hist_head = ++pos;
1521 return 0;
1522}
1523
1524static const RtpHistoryItem *rtp_history_find(WHIPContext *whip, uint16_t seq)
1525{
1526 uint32_t pos = ((uint32_t)seq - (uint32_t)whip->video_first_seq) % (uint32_t)whip->hist_sz;
1527 const RtpHistoryItem *it = &whip->hist[pos];
1528 return it->seq == seq ? it : NULL;
1529}
1530
1531/**
1532 * Callback triggered by the RTP muxer when it creates and sends out an RTP packet.
1533 *
1534 * This function modifies the video STAP packet, removing the markers, and updating the
1535 * NRI of the first NALU. Additionally, it uses the corresponding SRTP context to encrypt
1536 * the RTP packet, where the video packet is handled by the video SRTP context.
1537 */
1538static int on_rtp_write_packet(void *opaque, const uint8_t *buf, int buf_size)
1539{
1540 int ret, cipher_size, is_rtcp, is_video;
1541 uint8_t payload_type;
1542 AVFormatContext *s = opaque;
1543 WHIPContext *whip = s->priv_data;
1544 SRTPContext *srtp;
1545
1546 /* Ignore if not RTP or RTCP packet. */
1547 if (!media_is_rtp_rtcp(buf, buf_size))
1548 return 0;
1549
1550 /* Only support audio, video and rtcp. */
1551 is_rtcp = media_is_rtcp(buf, buf_size);
1552 payload_type = buf[1] & 0x7f;
1553 is_video = payload_type == whip->video_payload_type;
1554 if (!is_rtcp && payload_type != whip->video_payload_type && payload_type != whip->audio_payload_type)
1555 return 0;
1556
1557 /* Get the corresponding SRTP context. */
1558 srtp = is_rtcp ? &whip->srtp_rtcp_send : (is_video? &whip->srtp_video_send : &whip->srtp_audio_send);
1559
1560 /* Encrypt by SRTP and send out. */
1561 cipher_size = ff_srtp_encrypt(srtp, buf, buf_size, whip->buf, sizeof(whip->buf));
1562 if (cipher_size <= 0 || cipher_size < buf_size) {
1563 av_log(whip, AV_LOG_WARNING, "Failed to encrypt packet=%dB, cipher=%dB\n", buf_size, cipher_size);
1564 return 0;
1565 }
1566
1567 if (is_video) {
1568 ret = rtp_history_store(whip, buf, buf_size);
1569 if (ret < 0)
1570 return ret;
1571 }
1572
1573 ret = ffurl_write(whip->udp, whip->buf, cipher_size);
1574 if (ret < 0) {
1575 av_log(whip, AV_LOG_ERROR, "Failed to write packet=%dB, ret=%d\n", cipher_size, ret);
1576 return ret;
1577 }
1578
1579 return ret;
1580}
1581
1582/**
1583 * Creates dedicated RTP muxers for each stream in the AVFormatContext to build RTP
1584 * packets from the encoded frames.
1585 *
1586 * The corresponding SRTP context is utilized to encrypt each stream's RTP packets. For
1587 * example, a video SRTP context is used for the video stream. Additionally, the
1588 * "on_rtp_write_packet" callback function is set as the write function for each RTP
1589 * muxer to send out encrypted RTP packets.
1590 *
1591 * @return 0 if OK, AVERROR_xxx on error
1592 */
1594{
1595 int ret, i, is_video, buffer_size, max_packet_size;
1596 AVFormatContext *rtp_ctx = NULL;
1598 uint8_t *buffer = NULL;
1599 WHIPContext *whip = s->priv_data;
1600 whip->udp->flags |= AVIO_FLAG_NONBLOCK;
1601
1602
1603 /* The UDP buffer size, may greater than MTU. */
1604 buffer_size = MAX_UDP_BUFFER_SIZE;
1605 /* The RTP payload max size. Reserved some bytes for SRTP checksum and padding. */
1606 max_packet_size = whip->pkt_size - DTLS_SRTP_CHECKSUM_LEN;
1607
1608 for (i = 0; i < s->nb_streams; i++) {
1609 rtp_ctx = avformat_alloc_context();
1610 if (!rtp_ctx) {
1611 ret = AVERROR(ENOMEM);
1612 goto end;
1613 }
1614
1616 rtp_ctx->oformat = &ff_rtp_muxer.p;
1617 if (!avformat_new_stream(rtp_ctx, NULL)) {
1618 ret = AVERROR(ENOMEM);
1619 goto end;
1620 }
1621 /* Pass the interrupt callback on */
1622 rtp_ctx->interrupt_callback = s->interrupt_callback;
1623 /* Copy the max delay setting; the rtp muxer reads this. */
1624 rtp_ctx->max_delay = s->max_delay;
1625 /* Copy other stream parameters. */
1626 rtp_ctx->streams[0]->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
1627 rtp_ctx->flags |= s->flags & AVFMT_FLAG_BITEXACT;
1628 rtp_ctx->strict_std_compliance = s->strict_std_compliance;
1629
1630 /* Set the synchronized start time. */
1631 rtp_ctx->start_time_realtime = s->start_time_realtime;
1632
1633 avcodec_parameters_copy(rtp_ctx->streams[0]->codecpar, s->streams[i]->codecpar);
1634 rtp_ctx->streams[0]->time_base = s->streams[i]->time_base;
1635
1636 /**
1637 * For H.264, consistently utilize the annexb format through the Bitstream Filter (BSF);
1638 * therefore, we deactivate the extradata detection for the RTP muxer.
1639 */
1640 if (s->streams[i]->codecpar->codec_id == AV_CODEC_ID_H264) {
1641 av_freep(&rtp_ctx->streams[0]->codecpar->extradata);
1642 rtp_ctx->streams[0]->codecpar->extradata_size = 0;
1643 }
1644
1645 buffer = av_malloc(buffer_size);
1646 if (!buffer) {
1647 ret = AVERROR(ENOMEM);
1648 goto end;
1649 }
1650
1651 rtp_ctx->pb = avio_alloc_context(buffer, buffer_size, 1, s, NULL, on_rtp_write_packet, NULL);
1652 if (!rtp_ctx->pb) {
1653 ret = AVERROR(ENOMEM);
1654 goto end;
1655 }
1656 rtp_ctx->pb->max_packet_size = max_packet_size;
1657 rtp_ctx->pb->av_class = &ff_avio_class;
1658
1659 is_video = s->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;
1660 av_dict_set_int(&opts, "payload_type", is_video ? whip->video_payload_type : whip->audio_payload_type, 0);
1661 av_dict_set_int(&opts, "ssrc", is_video ? whip->video_ssrc : whip->audio_ssrc, 0);
1662 av_dict_set_int(&opts, "seq", is_video ? whip->video_first_seq : whip->audio_first_seq, 0);
1663
1664 ret = avformat_write_header(rtp_ctx, &opts);
1665 if (ret < 0) {
1666 av_log(whip, AV_LOG_ERROR, "Failed to write rtp header\n");
1667 goto end;
1668 }
1669
1670 ff_format_set_url(rtp_ctx, av_strdup(s->url));
1671 s->streams[i]->time_base = rtp_ctx->streams[0]->time_base;
1672 s->streams[i]->priv_data = rtp_ctx;
1673 rtp_ctx = NULL;
1674 }
1675
1676 if (whip->state < WHIP_STATE_READY)
1677 whip->state = WHIP_STATE_READY;
1678 av_log(whip, AV_LOG_INFO, "Muxer state=%d, buffer_size=%d, max_packet_size=%d, "
1679 "elapsed=%.2fms(init:%.2f,offer:%.2f,answer:%.2f,udp:%.2f,ice:%.2f,dtls:%.2f,srtp:%.2f)\n",
1680 whip->state, buffer_size, max_packet_size, ELAPSED(whip->whip_starttime, av_gettime_relative()),
1685 ELAPSED(whip->whip_udp_time, whip->whip_ice_time),
1686 ELAPSED(whip->whip_ice_time, whip->whip_dtls_time),
1687 ELAPSED(whip->whip_dtls_time, whip->whip_srtp_time));
1688
1689end:
1690 if (rtp_ctx) {
1691 if (!rtp_ctx->pb)
1692 av_freep(&buffer);
1693 avio_context_free(&rtp_ctx->pb);
1694 }
1695 avformat_free_context(rtp_ctx);
1697 return ret;
1698}
1699
1700/**
1701 * RTC is connectionless, for it's based on UDP, so it check whether sesison is
1702 * timeout. In such case, publishers can't republish the stream util the session
1703 * is timeout.
1704 * This function is called to notify the server that the stream is ended, server
1705 * should expire and close the session immediately, so that publishers can republish
1706 * the stream quickly.
1707 */
1709{
1710 int ret;
1711 char buf[MAX_URL_SIZE];
1712 URLContext *whip_uc = NULL;
1714 WHIPContext *whip = s->priv_data;
1715
1716 if (!whip->whip_resource_url)
1717 return 0;
1718
1719 ret = snprintf(buf, sizeof(buf), "Cache-Control: no-cache\r\n");
1720 if (whip->authorization)
1721 ret += snprintf(buf + ret, sizeof(buf) - ret, "Authorization: Bearer %s\r\n", whip->authorization);
1722 if (ret <= 0 || ret >= sizeof(buf)) {
1723 av_log(whip, AV_LOG_ERROR, "Failed to generate headers, size=%d, %s\n", ret, buf);
1724 ret = AVERROR(EINVAL);
1725 goto end;
1726 }
1727
1728 av_dict_set(&opts, "headers", buf, 0);
1729 av_dict_set_int(&opts, "chunked_post", 0, 0);
1730 av_dict_set(&opts, "method", "DELETE", 0);
1731
1732 if (whip->timeout >= 0)
1733 av_dict_set_int(&opts, "timeout", whip->timeout, 0);
1734
1735 ret = ffurl_open_whitelist(&whip_uc, whip->whip_resource_url, AVIO_FLAG_READ_WRITE, &s->interrupt_callback,
1736 &opts, s->protocol_whitelist, s->protocol_blacklist, NULL);
1737 if (ret < 0) {
1738 av_log(whip, AV_LOG_ERROR, "Failed to DELETE url=%s\n", whip->whip_resource_url);
1739 goto end;
1740 }
1741
1742 while (1) {
1743 ret = ffurl_read(whip_uc, buf, sizeof(buf));
1744 if (ret == AVERROR_EOF) {
1745 ret = 0;
1746 break;
1747 }
1748 if (ret < 0) {
1749 av_log(whip, AV_LOG_ERROR, "Failed to read response from DELETE url=%s\n", whip->whip_resource_url);
1750 goto end;
1751 }
1752 }
1753
1754 av_log(whip, AV_LOG_INFO, "Dispose resource %s ok\n", whip->whip_resource_url);
1755
1756end:
1757 ffurl_closep(&whip_uc);
1759 return ret;
1760}
1761
1762/**
1763 * Since the h264_mp4toannexb filter only processes the MP4 ISOM format and bypasses
1764 * the annexb format, it is necessary to manually insert encoder metadata before each
1765 * IDR when dealing with annexb format packets. For instance, in the case of H.264,
1766 * we must insert SPS and PPS before the IDR frame.
1767 */
1769{
1770 int ret = 0;
1771 AVPacket *in = NULL;
1772 AVCodecParameters *par = s->streams[pkt->stream_index]->codecpar;
1773 uint32_t nal_size = 0, out_size = par ? par->extradata_size : 0;
1774 uint8_t unit_type, sps_seen = 0, pps_seen = 0, idr_seen = 0, *out;
1775 const uint8_t *buf, *buf_end, *r1;
1776
1777 if (!par || !par->extradata || par->extradata_size <= 0)
1778 return ret;
1779
1780 /* Discover NALU type from packet. */
1781 buf_end = pkt->data + pkt->size;
1782 for (buf = ff_nal_find_startcode(pkt->data, buf_end); buf < buf_end; buf += nal_size) {
1783 while (!*(buf++));
1784 r1 = ff_nal_find_startcode(buf, buf_end);
1785 if ((nal_size = r1 - buf) > 0) {
1786 unit_type = *buf & 0x1f;
1787 if (unit_type == H264_NAL_SPS) {
1788 sps_seen = 1;
1789 } else if (unit_type == H264_NAL_PPS) {
1790 pps_seen = 1;
1791 } else if (unit_type == H264_NAL_IDR_SLICE) {
1792 idr_seen = 1;
1793 }
1794
1795 out_size += 3 + nal_size;
1796 }
1797 }
1798
1799 if (!idr_seen || (sps_seen && pps_seen))
1800 return ret;
1801
1802 /* See av_bsf_send_packet */
1803 in = av_packet_alloc();
1804 if (!in)
1805 return AVERROR(ENOMEM);
1806
1808 if (ret < 0)
1809 goto fail;
1810
1812
1813 /* Create a new packet with sps/pps inserted. */
1814 ret = av_new_packet(pkt, out_size);
1815 if (ret < 0)
1816 goto fail;
1817
1818 ret = av_packet_copy_props(pkt, in);
1819 if (ret < 0)
1820 goto fail;
1821
1822 memcpy(pkt->data, par->extradata, par->extradata_size);
1823 out = pkt->data + par->extradata_size;
1824 buf_end = in->data + in->size;
1825 for (buf = ff_nal_find_startcode(in->data, buf_end); buf < buf_end; buf += nal_size) {
1826 while (!*(buf++));
1827 r1 = ff_nal_find_startcode(buf, buf_end);
1828 if ((nal_size = r1 - buf) > 0) {
1829 AV_WB24(out, 0x00001);
1830 memcpy(out + 3, buf, nal_size);
1831 out += 3 + nal_size;
1832 }
1833 }
1834
1835fail:
1836 if (ret < 0)
1838 av_packet_free(&in);
1839
1840 return ret;
1841}
1842
1844{
1845 int ret;
1846 WHIPContext *whip = s->priv_data;
1847
1848 if ((ret = initialize(s)) < 0)
1849 goto end;
1850
1851 if ((ret = parse_codec(s)) < 0)
1852 goto end;
1853
1854 if ((ret = generate_sdp_offer(s)) < 0)
1855 goto end;
1856
1857 if ((ret = exchange_sdp(s)) < 0)
1858 goto end;
1859
1860 if ((ret = parse_answer(s)) < 0)
1861 goto end;
1862
1863 if ((ret = udp_connect(s)) < 0)
1864 goto end;
1865
1866 if ((ret = ice_dtls_handshake(s)) < 0)
1867 goto end;
1868
1869 if ((ret = setup_srtp(s)) < 0)
1870 goto end;
1871
1872 if ((ret = create_rtp_muxer(s)) < 0)
1873 goto end;
1874
1875end:
1876 if (ret < 0)
1877 whip->state = WHIP_STATE_FAILED;
1878 return ret;
1879}
1880
1881/**
1882 * See https://datatracker.ietf.org/doc/html/rfc4588#section-4
1883 * Create RTX packet and send it out.
1884 */
1885static void handle_rtx_packet(AVFormatContext *s, uint16_t seq)
1886{
1887 int ret = -1;
1888 WHIPContext *whip = s->priv_data;
1889 uint8_t *ori_buf, rtx_buf[MAX_UDP_BUFFER_SIZE] = { 0 };
1890 int ori_size, rtx_size, cipher_size;
1891 uint16_t ori_seq;
1892 const RtpHistoryItem *it = rtp_history_find(whip, seq);
1893 uint16_t latest_seq = whip->hist[(whip->hist_head - 1 + whip->hist_sz) % whip->hist_sz].seq;
1894
1895 if (!it) {
1896 av_log(whip, AV_LOG_DEBUG,
1897 "RTP history packet seq=%"PRIu16" not found, latest seq=%"PRIu16"\n",
1898 seq, latest_seq);
1899 return;
1900 }
1901 av_log(whip, AV_LOG_DEBUG,
1902 "Found RTP history packet for RTX, seq=%"PRIu16", latest seq=%"PRIu16"\n",
1903 seq, latest_seq);
1904
1905 ori_buf = it->buf;
1906 ori_size = it->size;
1907
1908 /* A valid RTP packet must have at least a RTP header. */
1909 if (ori_size < WHIP_RTP_HEADER_SIZE) {
1910 av_log(whip, AV_LOG_WARNING, "RTX history packet too small, size=%d\n", ori_size);
1911 goto end;
1912 }
1913
1914 /* RTX packet format: header + original seq (2 bytes) + payload */
1915 if (ori_size + 2 > sizeof(rtx_buf)) {
1916 av_log(whip, AV_LOG_WARNING, "RTX packet is too large, size=%d\n", ori_size);
1917 goto end;
1918 }
1919
1920 memcpy(rtx_buf, ori_buf, ori_size);
1921 ori_seq = AV_RB16(rtx_buf + 2);
1922
1923 /* rewrite RTX packet header */
1924 rtx_buf[1] = (rtx_buf[1] & 0x80) | whip->video_rtx_payload_type; /* keep M bit */
1925 AV_WB16(rtx_buf + 2, whip->video_rtx_seq++);
1926 AV_WB32(rtx_buf + 8, whip->video_rtx_ssrc);
1927
1928 /* shift payload 2 bytes to write the original seq number */
1929 memmove(rtx_buf + 12 + 2, rtx_buf + 12, ori_size - 12);
1930 AV_WB16(rtx_buf + 12, ori_seq);
1931
1932 rtx_size = ori_size + 2;
1933 cipher_size = ff_srtp_encrypt(&whip->srtp_video_rtx_send,
1934 rtx_buf, rtx_size,
1935 whip->buf, sizeof(whip->buf));
1936 if (cipher_size <= 0) {
1937 av_log(whip, AV_LOG_WARNING,
1938 "Failed to encrypt RTX packet, size=%d, cipher_size=%d\n",
1939 rtx_size, cipher_size);
1940 goto end;
1941 }
1942 ret = ffurl_write(whip->udp, whip->buf, cipher_size);
1943end:
1944 if (ret < 0)
1945 av_log(whip, AV_LOG_WARNING, "Failed to send RTX packet, skip this one\n");
1946}
1947
1949{
1950 int ret, i = 0;
1951 WHIPContext *whip = s->priv_data;
1952 uint8_t *buf = NULL;
1953 int rtcp_len, srtcp_len, header_len = 12/*RFC 4585 6.1*/;
1954 uint32_t ssrc;
1955
1956 /**
1957 * Refer to RFC 3550 6.4.1
1958 * The length of this RTCP packet in 32 bit words minus one,
1959 * including the header and any padding.
1960 */
1961 rtcp_len = (AV_RB16(&whip->buf[2]) + 1) * 4;
1962 if (rtcp_len <= header_len) {
1963 av_log(whip, AV_LOG_WARNING, "NACK packet is broken, size: %d\n", rtcp_len);
1964 goto error;
1965 }
1966 /* SRTCP index(4 bytes) + HMAC(SRTP_ARS128_CM_SHA1_80) 10bytes */
1967 srtcp_len = rtcp_len + 4 + 10;
1968 if (srtcp_len != size) {
1969 av_log(whip, AV_LOG_WARNING, "NACK packet size not match, srtcp_len:%d, size:%d\n", srtcp_len, size);
1970 goto error;
1971 }
1972 buf = av_memdup(whip->buf, srtcp_len);
1973 if (!buf)
1974 goto error;
1975 if ((ret = ff_srtp_decrypt(&whip->srtp_recv, buf, &srtcp_len)) < 0) {
1976 av_log(whip, AV_LOG_WARNING, "NACK packet decrypt failed: %d\n", ret);
1977 goto error;
1978 }
1979 ssrc = AV_RB32(&buf[8]);
1980 if (ssrc != whip->video_ssrc) {
1981 av_log(whip, AV_LOG_DEBUG,
1982 "NACK packet SSRC: %"PRIu32" not match with video track SSRC: %"PRIu32"\n",
1983 ssrc, whip->video_ssrc);
1984 goto end;
1985 }
1986 while (header_len + i + 4 <= rtcp_len) {
1987 /**
1988 * See https://datatracker.ietf.org/doc/html/rfc4585#section-6.1
1989 * Handle multi NACKs in bundled packet.
1990 */
1991 uint16_t pid = AV_RB16(&buf[12 + i]);
1992 uint16_t blp = AV_RB16(&buf[14 + i]);
1993
1994 handle_rtx_packet(s, pid);
1995 /* retransmit pid + any bit set in blp */
1996 for (int bit = 0; bit < 16; bit++) {
1997 uint16_t seq = pid + bit + 1;
1998 if (!blp)
1999 break;
2000 if (!(blp & (1 << bit)))
2001 continue;
2002
2003 handle_rtx_packet(s, seq);
2004 }
2005 i += 4;
2006 }
2007 goto end;
2008error:
2009 av_log(whip, AV_LOG_WARNING, "Failed to handle NACK and RTX, Skip...\n");
2010end:
2011 av_freep(&buf);
2012}
2013
2015{
2016 int ret;
2017 WHIPContext *whip = s->priv_data;
2018 AVStream *st = s->streams[pkt->stream_index];
2019 AVFormatContext *rtp_ctx = st->priv_data;
2021 /**
2022 * Refer to RFC 7675
2023 * Periodically send Consent Freshness STUN Binding Request
2024 */
2026 int size;
2027 ret = ice_create_request(s, whip->buf, sizeof(whip->buf), &size);
2028 if (ret < 0) {
2029 av_log(whip, AV_LOG_ERROR, "Failed to create STUN binding request, size=%d\n", size);
2030 goto end;
2031 }
2032 ret = ffurl_write(whip->udp, whip->buf, size);
2033 if (ret < 0) {
2034 av_log(whip, AV_LOG_ERROR, "Failed to send STUN binding request, size=%d\n", size);
2035 goto end;
2036 }
2037 whip->whip_last_consent_tx_time = now;
2038 av_log(whip, AV_LOG_DEBUG, "Consent Freshness check sent\n");
2039 }
2040
2041 /**
2042 * Receive packets from the server such as ICE binding requests, DTLS messages,
2043 * and RTCP like PLI requests, then respond to them.
2044 */
2045 ret = ffurl_read(whip->udp, whip->buf, sizeof(whip->buf));
2046 if (ret < 0) {
2047 if (ret == AVERROR(EAGAIN))
2048 goto write_packet;
2049 av_log(whip, AV_LOG_ERROR, "Failed to read from UDP socket\n");
2050 goto end;
2051 }
2052 if (!ret) {
2053 av_log(whip, AV_LOG_ERROR, "Receive EOF from UDP socket\n");
2054 goto end;
2055 }
2056 if (ice_is_binding_response(whip->buf, ret)) {
2058 av_log(whip, AV_LOG_DEBUG, "Consent Freshness check received\n");
2059 }
2060 if (ff_is_dtls_packet(whip->buf, ret)) {
2061 if ((ret = ffurl_write(whip->dtls_uc, whip->buf, ret)) < 0) {
2062 av_log(whip, AV_LOG_ERROR, "Failed to handle DTLS message\n");
2063 goto end;
2064 }
2065 }
2066 if (media_is_rtcp(whip->buf, ret)) {
2067 uint8_t fmt = whip->buf[0] & 0x1f;
2068 uint8_t pt = whip->buf[1];
2069 /**
2070 * Handle RTCP NACK packet
2071 * Refer to RFC 4585 6.2.1
2072 * The Generic NACK message is identified by PT=RTPFB and FMT=1
2073 */
2074 if (pt != RTCP_RTPFB)
2075 goto write_packet;
2076 if (fmt == 1)
2077 handle_nack_rtx(s, ret);
2078 }
2080 now = av_gettime_relative();
2082 av_log(whip, AV_LOG_ERROR,
2083 "Consent Freshness expired after %.2fms (limited %dms), terminate session\n",
2085 ret = AVERROR(ETIMEDOUT);
2086 goto end;
2087 }
2089 if ((ret = h264_annexb_insert_sps_pps(s, pkt)) < 0) {
2090 av_log(whip, AV_LOG_ERROR, "Failed to insert SPS/PPS before IDR\n");
2091 goto end;
2092 }
2093 }
2094
2095 ret = ff_write_chained(rtp_ctx, 0, pkt, s, 0);
2096 if (ret < 0) {
2097 if (ret == AVERROR(EINVAL)) {
2098 av_log(whip, AV_LOG_WARNING, "Ignore failed to write packet=%dB, ret=%d\n", pkt->size, ret);
2099 ret = 0;
2100 } else if (ret == AVERROR(EAGAIN)) {
2101 av_log(whip, AV_LOG_ERROR, "UDP send blocked, please increase the buffer via -ts_buffer_size\n");
2102 } else
2103 av_log(whip, AV_LOG_ERROR, "Failed to write packet, size=%d, ret=%d\n", pkt->size, ret);
2104 goto end;
2105 }
2106
2107end:
2108 if (ret < 0)
2109 whip->state = WHIP_STATE_FAILED;
2110 return ret;
2111}
2112
2114{
2115 int i, ret;
2116 WHIPContext *whip = s->priv_data;
2117
2118 ret = dispose_session(s);
2119 if (ret < 0)
2120 av_log(whip, AV_LOG_WARNING, "Failed to dispose resource, ret=%d\n", ret);
2121
2122 for (i = 0; i < s->nb_streams; i++) {
2123 AVFormatContext* rtp_ctx = s->streams[i]->priv_data;
2124 if (!rtp_ctx)
2125 continue;
2126
2127 av_write_trailer(rtp_ctx);
2128 /**
2129 * Keep in mind that it is necessary to free the buffer of pb since we allocate
2130 * it and pass it to pb using avio_alloc_context, while avio_context_free does
2131 * not perform this action.
2132 */
2133 av_freep(&rtp_ctx->pb->buffer);
2134 avio_context_free(&rtp_ctx->pb);
2135 avformat_free_context(rtp_ctx);
2136 s->streams[i]->priv_data = NULL;
2137 }
2138
2139 av_freep(&whip->hist_pool);
2140 av_freep(&whip->hist);
2141 av_freep(&whip->sdp_offer);
2142 av_freep(&whip->sdp_answer);
2144 av_freep(&whip->ice_ufrag_remote);
2145 av_freep(&whip->ice_pwd_remote);
2146 av_freep(&whip->ice_protocol);
2147 av_freep(&whip->ice_host);
2148 av_freep(&whip->authorization);
2149 av_freep(&whip->cert_file);
2150 av_freep(&whip->key_file);
2155 ff_srtp_free(&whip->srtp_recv);
2156 ffurl_closep(&whip->dtls_uc);
2157 ffurl_closep(&whip->udp);
2158 av_freep(&whip->dtls_fingerprint);
2160}
2161
2163{
2164 int ret = 1, extradata_isom = 0;
2165 uint8_t *b = pkt->data;
2166 WHIPContext *whip = s->priv_data;
2167
2168 if (st->codecpar->codec_id == AV_CODEC_ID_H264) {
2169 extradata_isom = st->codecpar->extradata_size > 0 && st->codecpar->extradata[0] == 1;
2170 if (pkt->size >= 5 && AV_RB32(b) != 0x0000001 && (AV_RB24(b) != 0x000001 || extradata_isom)) {
2171 ret = ff_stream_add_bitstream_filter(st, "h264_mp4toannexb", NULL);
2172 av_log(whip, AV_LOG_VERBOSE, "Enable BSF h264_mp4toannexb, packet=[%x %x %x %x %x ...], extradata_isom=%d\n",
2173 b[0], b[1], b[2], b[3], b[4], extradata_isom);
2174 } else
2176 }
2177
2178 return ret;
2179}
2180
2181#define OFFSET(x) offsetof(WHIPContext, x)
2182#define ENC AV_OPT_FLAG_ENCODING_PARAM
2183static const AVOption options[] = {
2184 { "handshake_timeout", "Timeout in milliseconds for ICE and DTLS handshake.", OFFSET(handshake_timeout), AV_OPT_TYPE_INT, { .i64 = 5000 }, -1, INT_MAX, ENC },
2185 { "timeout", "Set timeout for socket I/O operations", OFFSET(timeout), AV_OPT_TYPE_DURATION, { .i64 = -1 }, -1, INT_MAX, ENC },
2186 { "pkt_size", "The maximum size, in bytes, of RTP packets that send out", OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = 1200 }, -1, INT_MAX, ENC },
2187 { "ts_buffer_size", "The buffer size, in bytes, of underlying protocol", OFFSET(ts_buffer_size), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ENC },
2188 { "whip_flags", "Set flags affecting WHIP connection behavior", OFFSET(flags), AV_OPT_TYPE_FLAGS, { .i64 = 0}, 0, UINT_MAX, ENC, .unit = "flags" },
2189 { "dtls_active", "Set dtls role as active", 0, AV_OPT_TYPE_CONST, { .i64 = WHIP_DTLS_ACTIVE}, 0, UINT_MAX, ENC, .unit = "flags" },
2190 { "rtp_history", "The number of RTP history items to store", OFFSET(hist_sz), AV_OPT_TYPE_INT, { .i64 = WHIP_RTP_HISTORY_DEFAULT }, WHIP_RTP_HISTORY_MIN, WHIP_RTP_HISTORY_MAX, ENC },
2191 { "authorization", "The optional Bearer token for WHIP Authorization", OFFSET(authorization), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, ENC },
2192 { "cert_file", "The optional certificate file path for DTLS", OFFSET(cert_file), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, ENC },
2193 { "key_file", "The optional private key file path for DTLS", OFFSET(key_file), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, ENC },
2194 { NULL },
2195};
2196
2198 .class_name = "WHIP muxer",
2199 .item_name = av_default_item_name,
2200 .option = options,
2201 .version = LIBAVUTIL_VERSION_INT,
2202};
2203
2205 .p.name = "whip",
2206 .p.long_name = NULL_IF_CONFIG_SMALL("WHIP(WebRTC-HTTP ingestion protocol) muxer"),
2207 .p.audio_codec = AV_CODEC_ID_OPUS,
2208 .p.video_codec = AV_CODEC_ID_H264,
2209 .p.subtitle_codec = AV_CODEC_ID_NONE,
2211 .p.priv_class = &whip_muxer_class,
2213 .priv_data_size = sizeof(WHIPContext),
2214 .init = whip_init,
2218};
const FFOutputFormat ff_rtp_muxer
Definition rtpenc.c:701
const FFOutputFormat ff_whip_muxer
Definition whip.c:2204
static FILE * out
static int out_size
static AVDictionary * opts
#define EXTERN
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
Definition avassert.h:109
int ff_avc_decode_sps(H264SPS *sps, const uint8_t *buf, int buf_size)
Definition avc.c:196
void ff_format_set_url(AVFormatContext *s, char *url)
Set AVFormatContext url field to the provided pointer.
Definition avformat.c:923
#define AVFMT_FLAG_BITEXACT
When muxing, try to avoid writing any random/volatile data to the output.
Definition avformat.h:1501
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition avformat.h:488
#define AVFMT_EXPERIMENTAL
The muxer/demuxer is experimental and should be used with caution.
Definition avformat.h:495
#define AVFMT_GLOBALHEADER
Format wants global header.
Definition avformat.h:497
int ffurl_handshake(URLContext *c)
Perform one step of the protocol handshake to accept a new client.
Definition avio.c:294
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it.
Definition avio.c:461
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition avio.c:656
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
Definition avio.c:882
const AVClass ff_avio_class
Definition avio.c:103
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
Definition avio.c:725
void avio_wb32(AVIOContext *s, unsigned int val)
Definition aviobuf.c:368
void avio_wb16(AVIOContext *s, unsigned int val)
Definition aviobuf.c:446
#define AVIO_FLAG_READ
read-only
Definition avio.h:617
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition aviobuf.c:349
#define AVIO_FLAG_WRITE
write-only
Definition avio.h:618
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition avio.h:494
void avio_wb64(AVIOContext *s, uint64_t val)
Definition aviobuf.c:434
AVIOContext * avio_alloc_context(unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int(*read_packet)(void *opaque, uint8_t *buf, int buf_size), int(*write_packet)(void *opaque, const uint8_t *buf, int buf_size), int64_t(*seek)(void *opaque, int64_t offset, int whence))
Allocate and initialize an AVIOContext for buffered I/O.
Definition aviobuf.c:109
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition aviobuf.c:321
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition avio.h:619
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition aviobuf.c:206
void avio_context_free(AVIOContext **s)
Free the supplied IO context and everything associated with it.
Definition aviobuf.c:126
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
Definition avio.h:636
void ffio_fill(AVIOContext *s, int b, int64_t count)
Definition aviobuf.c:192
int ff_get_chomp_line(AVIOContext *s, char *buf, int maxlen)
Same as ff_get_line but strip the white-space characters in the text tail.
Definition aviobuf.c:789
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition bprint.c:122
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:69
AVBPrint public header.
#define ENC
Definition caca.c:198
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
static int FUNC sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
#define bit(string, value)
Definition cbs_mpeg2.c:56
#define s(width, name)
Definition cbs_vp9.c:198
static void deinit(AVFormatContext *s)
Definition chromaprint.c:53
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Definition codec_par.c:107
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
Public header for CRC hash function implementation.
static unsigned crc32(const uint8_t *data, unsigned size)
#define AV_PROFILE_UNKNOWN
Definition defs.h:65
#define AV_PROFILE_H264_CONSTRAINED
Definition defs.h:107
#define AV_LEVEL_UNKNOWN
Definition defs.h:209
#define AV_PROFILE_H264_INTRA
Definition defs.h:108
static AVPacket * pkt
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
static struct @346255127015250356166251341105367306144006377143 state
static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
Definition ffmpeg_mux.c:204
#define fail
Definition test.h:479
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_DURATION
Underlying C type is int64_t.
Definition opt.h:318
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
Definition opt.h:254
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
@ AV_CODEC_ID_H264
Definition codec_id.h:77
@ AV_CODEC_ID_NONE
Definition codec_id.h:48
@ AV_CODEC_ID_OPUS
Definition codec_id.h:513
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
Definition packet.c:74
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition packet.c:434
int av_packet_make_refcounted(AVPacket *pkt)
Ensure the data described by a given packet is reference counted.
Definition packet.c:497
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
Definition packet.c:491
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
Definition packet.c:63
int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
Copy only "properties" fields from src to dst.
Definition packet.c:397
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition packet.c:98
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
Definition options.c:165
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition avformat.c:150
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition mux.c:467
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition mux.c:1238
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition bprint.h:218
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:235
char * av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
Encode data to base64 and null-terminate.
Definition base64.c:147
#define AV_BASE64_SIZE(x)
Calculate the output size needed to base64-encode x bytes to a null-terminated string.
Definition base64.h:66
const AVCRC * av_crc_get_table(AVCRCId crc_id)
Get an initialized standard CRC table.
Definition crc.c:389
uint32_t av_crc(const AVCRC *ctx, uint32_t crc, const uint8_t *buffer, size_t length)
Calculate the CRC of a block.
Definition crc.c:421
@ AV_CRC_32_IEEE_LE
Definition crc.h:53
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
int av_random_bytes(uint8_t *buf, size_t len)
Generate cryptographically secure random data, i.e.
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:233
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that's been allocated with av_malloc() or another memory allocation functio...
Definition dict.h:79
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition dict.c:86
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
Definition dict.c:177
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition error.h:64
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
int av_hmac_final(AVHMAC *c, uint8_t *out, unsigned int outlen)
Finish hashing and output the HMAC digest.
Definition hmac.c:181
AVHMAC * av_hmac_alloc(enum AVHMACType type)
Allocate an AVHMAC context.
Definition hmac.c:82
void av_hmac_update(AVHMAC *c, const uint8_t *data, unsigned int len)
Hash data with the HMAC.
Definition hmac.c:176
void av_hmac_free(AVHMAC *c)
Free an AVHMAC context.
Definition hmac.c:147
void av_hmac_init(AVHMAC *c, const uint8_t *key, unsigned int keylen)
Initialize an AVHMAC context with an authentication key.
Definition hmac.c:155
@ AV_HMAC_SHA1
Definition hmac.h:34
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_VERBOSE
Detailed information.
Definition log.h:226
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
Definition mem.c:302
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle.
Definition avstring.c:58
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition avstring.c:208
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition avstring.c:36
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
H.264 common definitions.
@ H264_NAL_PPS
Definition h264.h:42
@ H264_NAL_SPS
Definition h264.h:41
@ H264_NAL_IDR_SLICE
Definition h264.h:39
int profile_idc
Definition h264_levels.c:53
static uint64_t request_size(URLContext *h)
Definition http.c:1535
const char * ff_http_get_new_location(URLContext *h)
Definition http.c:615
#define r
Definition input.c:42
#define b
Definition input.c:43
#define AV_WB24(p, d)
#define AV_WB32(p, v)
#define AV_RB32(p)
#define AV_WB16(p, v)
#define AV_RB24(x)
#define AV_RB16(p)
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
Definition lfg.c:32
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
Definition lfg.h:53
char * ff_data_to_hex(char *buf, const uint8_t *src, int size, int lowercase)
Write hexadecimal string corresponding to given binary data.
Definition utils.c:464
#define MAX_URL_SIZE
Definition internal.h:30
int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, AVFormatContext *src, int interleave)
Write a packet to another muxer than the one the user originally intended.
Definition mux.c:1337
static int check_bitstream(AVFormatContext *s, FFStream *sti, AVPacket *pkt)
Definition mux.c:1056
int ff_stream_add_bitstream_filter(AVStream *st, const char *name, const char *args)
Add a bitstream filter to a stream.
Definition mux.c:1294
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
enum AVColorSpace space
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:264
Memory handling functions.
#define FF_OFMT_FLAG_MAX_ONE_OF_EACH
If this flag is set, it indicates that for each codec type whose corresponding default codec (i....
Definition mux.h:50
#define FF_OFMT_FLAG_ONLY_DEFAULT_CODECS
If this flag is set, then the only permitted audio/video/subtitle codec ids are AVOutputFormat....
Definition mux.h:59
const uint8_t * ff_nal_find_startcode(const uint8_t *p, const uint8_t *end)
Definition nal.c:68
int ff_socket_nonblock(int socket, int enable)
#define av_strdup(s)
Definition ops_static.c:55
#define av_malloc(s)
Definition ops_static.c:52
AVOptions.
int pt
Definition rtp.c:35
@ RTCP_RTPFB
Definition rtp.h:104
#define snprintf
Definition snprintf.h:34
unsigned int pos
Definition spdifenc.c:431
int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len, uint8_t *out, int outlen)
Definition srtp.c:239
int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite, const char *params)
Definition srtp.c:66
int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
Definition srtp.c:127
void ff_srtp_free(struct SRTPContext *s)
Definition srtp.c:32
Accelerated start code search function for start codes common to MPEG-1/2/4 video,...
const uint8_t * avpriv_find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state)
int nb_channels
Number of channels in this layout.
Describe the class of an AVClass context structure.
Definition log.h:76
This struct describes the properties of an encoded stream.
Definition codec_par.h:49
int extradata_size
Size of the extradata content in bytes.
Definition codec_par.h:75
AVChannelLayout ch_layout
The channel layout and number of channels.
Definition codec_par.h:207
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
int profile
Codec-specific bitstream restrictions that the stream conforms to.
Definition codec_par.h:135
int video_delay
Number of delayed frames.
Definition codec_par.h:200
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition codec_par.h:71
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
int sample_rate
The number of audio samples per second.
Definition codec_par.h:213
Format I/O context.
Definition avformat.h:1333
AVIOContext * pb
I/O context.
Definition avformat.h:1375
int flags
Flags modifying the (de)muxer behaviour.
Definition avformat.h:1484
const struct AVOutputFormat * oformat
The output container format.
Definition avformat.h:1352
int strict_std_compliance
Allow non-standard and experimental extension.
Definition avformat.h:1707
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition avformat.h:1618
int64_t start_time_realtime
Start time of the stream in real world time, in microseconds since the Unix epoch (00:00 1st January ...
Definition avformat.h:1593
AVStream ** streams
A list of all streams in the file.
Definition avformat.h:1401
Definition hmac.c:40
Bytestream IO Context.
Definition avio.h:160
const AVClass * av_class
A class for private options.
Definition avio.h:173
unsigned char * buffer
Start of the buffer.
Definition avio.h:225
int max_packet_size
Definition avio.h:241
Context structure for the Lagged Fibonacci PRNG.
Definition lfg.h:33
AVOption.
Definition opt.h:428
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
uint8_t * data
Definition packet.h:603
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
Definition avformat.h:844
void * priv_data
Definition avformat.h:791
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition avformat.h:805
Definition avc.h:32
uint16_t seq
Definition whip.c:209
uint8_t * buf
Definition whip.c:211
int flags
Definition url.h:40
int64_t whip_last_consent_tx_time
Definition whip.c:285
enum WHIPState state
Definition whip.c:219
int ice_port
Definition whip.c:269
char * authorization
The optional Bearer token for WHIP Authorization.
Definition whip.c:334
SRTPContext srtp_rtcp_send
Definition whip.c:310
AVCodecParameters * audio_par
Definition whip.c:222
char * ice_ufrag_remote
Definition whip.c:260
char * remote_fingerprint
Definition whip.c:294
char key_buf[MAX_CERTIFICATE_SIZE]
Definition whip.c:290
char cert_buf[MAX_CERTIFICATE_SIZE]
Definition whip.c:289
uint16_t audio_first_seq
Definition whip.c:243
char * ice_protocol
This represents the ICE candidate protocol, priority, host and port.
Definition whip.c:267
uint8_t video_payload_type
Definition whip.c:249
char * ice_pwd_remote
Definition whip.c:261
int64_t whip_last_consent_rx_time
Definition whip.c:286
int ts_buffer_size
Definition whip.c:329
uint32_t video_ssrc
Definition whip.c:240
int64_t whip_offer_time
Definition whip.c:279
int64_t timeout
Definition whip.c:323
SRTPContext srtp_recv
Definition whip.c:312
char buf[MAX_UDP_BUFFER_SIZE]
Definition whip.c:317
uint8_t video_rtx_payload_type
Definition whip.c:250
uint32_t audio_ssrc
Definition whip.c:239
AVClass * av_class
Definition whip.c:215
int64_t whip_dtls_time
Definition whip.c:283
char * cert_file
Definition whip.c:336
int hist_head
Definition whip.c:342
int64_t whip_starttime
Definition whip.c:277
uint8_t dtls_srtp_materials[(DTLS_SRTP_KEY_LEN+DTLS_SRTP_SALT_LEN) *2]
This represents the material used to build the SRTP master key.
Definition whip.c:301
int pkt_size
The size of RTP packet, should generally be set to MTU.
Definition whip.c:328
uint16_t video_rtx_seq
Definition whip.c:246
char * key_file
Definition whip.c:337
AVCodecParameters * video_par
Definition whip.c:223
uint64_t ice_tie_breaker
Definition whip.c:258
int64_t whip_answer_time
Definition whip.c:280
SRTPContext srtp_audio_send
Definition whip.c:307
int64_t whip_srtp_time
Definition whip.c:284
char ice_ufrag_local[9]
Definition whip.c:236
SRTPContext srtp_video_send
Definition whip.c:308
char * ice_host
Definition whip.c:268
int64_t whip_udp_time
Definition whip.c:281
RtpHistoryItem * hist
Definition whip.c:340
int64_t whip_ice_time
Definition whip.c:282
uint32_t flags
Definition whip.c:217
int64_t whip_init_time
Definition whip.c:278
int h264_annexb_insert_sps_pps
The h264_mp4toannexb Bitstream Filter (BSF) bypasses the AnnexB packet; therefore,...
Definition whip.c:230
int hist_sz
Definition whip.c:339
SRTPContext srtp_video_rtx_send
Definition whip.c:309
uint8_t * hist_pool
Definition whip.c:341
uint32_t video_rtx_ssrc
Definition whip.c:241
int is_peer_ice_lite
Definition whip.c:257
URLContext * dtls_uc
Definition whip.c:304
char ice_pwd_local[33]
Definition whip.c:237
char * sdp_answer
Definition whip.c:272
AVLFG rnd
Definition whip.c:233
URLContext * udp
Definition whip.c:315
char * dtls_fingerprint
Definition whip.c:292
char * sdp_offer
This is the SDP offer generated by the muxer based on the codec parameters, DTLS, and ICE information...
Definition whip.c:255
char * whip_resource_url
Definition whip.c:274
uint16_t video_first_seq
Definition whip.c:244
int handshake_timeout
Definition whip.c:320
uint8_t audio_payload_type
Definition whip.c:248
uint8_t level
Definition svq3.c:208
#define av_freep(p)
#define av_log(a,...)
static void error(const char *err)
static char buffer[20]
Definition seek.c:32
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition time.c:93
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
Definition time.c:57
int ff_is_dtls_packet(const uint8_t *buf, int size)
Whether the packet is a DTLS packet, as defined by RFC 5764 Section 5.1.2.
Definition tls.c:167
int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
Definition tls_gnutls.c:299
int ff_ssl_read_key_cert(char *key_url, char *cert_url, char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
Definition tls_gnutls.c:115
#define MAX_CERTIFICATE_SIZE
Maximum size limit of a certificate and private key size.
Definition tls.h:34
int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
Definition tls_gnutls.c:379
int ff_tls_set_external_socket(URLContext *h, URLContext *sock)
Definition tls_gnutls.c:366
int size
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
Definition url.c:40
static int ffurl_write(URLContext *h, const uint8_t *buf, int size)
Write size bytes from buf to the resource accessed by h.
Definition url.h:204
static int ffurl_read(URLContext *h, uint8_t *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.
Definition url.h:183
static unsigned int seed
Definition videogen.c:78
static int rtp_history_store(WHIPContext *whip, const uint8_t *buf, int size)
Definition whip.c:1509
#define STUN_MAGIC_COOKIE
Definition whip.c:81
static int udp_connect(AVFormatContext *s)
To establish a connection with the UDP server, we utilize ICE-LITE in a Client-Server mode.
Definition whip.c:1262
#define WHIP_ICE_CONSENT_EXPIRED_TIMER
Definition whip.c:148
#define MAX_SDP_SIZE
Maximum size limit of a Session Description Protocol (SDP), be it an offer or answer.
Definition whip.c:52
static int ice_create_response(AVFormatContext *s, char *tid, int tid_size, uint8_t *buf, int buf_size, int *response_size)
Create an ICE binding response.
Definition whip.c:1122
#define WHIP_US_PER_MS
Definition whip.c:71
static int parse_codec(AVFormatContext *s)
Parses video SPS/PPS from the extradata of codecpar and checks the codec.
Definition whip.c:548
WHIPState
Definition whip.c:174
@ WHIP_STATE_READY
Definition whip.c:199
@ WHIP_STATE_INIT
Definition whip.c:178
@ WHIP_STATE_NEGOTIATED
After parsing the answer received from the peer, the muxer negotiates the abilities in the offer that...
Definition whip.c:187
@ WHIP_STATE_ANSWER
Definition whip.c:182
@ WHIP_STATE_ICE_CONNECTING
Definition whip.c:191
@ WHIP_STATE_ICE_CONNECTED
Definition whip.c:193
@ WHIP_STATE_DTLS_FINISHED
Definition whip.c:195
@ WHIP_STATE_OFFER
Definition whip.c:180
@ WHIP_STATE_NONE
Definition whip.c:175
@ WHIP_STATE_SRTP_FINISHED
Definition whip.c:197
@ WHIP_STATE_UDP_CONNECTED
Definition whip.c:189
@ WHIP_STATE_FAILED
Definition whip.c:201
static void handle_nack_rtx(AVFormatContext *s, int size)
Definition whip.c:1948
static const RtpHistoryItem * rtp_history_find(WHIPContext *whip, uint16_t seq)
Definition whip.c:1524
static int ice_dtls_handshake(AVFormatContext *s)
Definition whip.c:1300
#define MAX_UDP_BUFFER_SIZE
Maximum size of the buffer for sending and receiving UDP packets.
Definition whip.c:97
#define DTLS_SRTP_SALT_LEN
Definition whip.c:61
#define ICE_STUN_HEADER_SIZE
The STUN message header, which is 20 bytes long, comprises the STUNMessageType (1B),...
Definition whip.c:110
#define WHIP_RTP_PAYLOAD_TYPE_OPUS
Definition whip.c:101
#define WHIP_RTP_HEADER_SIZE
The RTP header is 12 bytes long, comprising the Version(1B), PT(1B), SequenceNumber(2B),...
Definition whip.c:117
static int exchange_sdp(AVFormatContext *s)
Exchange SDP offer with WebRTC peer to get the answer.
Definition whip.c:772
#define ELAPSED(starttime, endtime)
Definition whip.c:162
static int whip_write_packet(AVFormatContext *s, AVPacket *pkt)
Definition whip.c:2014
static int generate_sdp_offer(AVFormatContext *s)
Generate SDP offer according to the codec parameters, DTLS and ICE information.
Definition whip.c:608
static int media_is_rtp_rtcp(const uint8_t *b, int size)
In RTP packets, the first byte is represented as 0b10xxxxxx, where the initial two bits (0b10) indica...
Definition whip.c:1207
static int on_rtp_write_packet(void *opaque, const uint8_t *buf, int buf_size)
Callback triggered by the RTP muxer when it creates and sends out an RTP packet.
Definition whip.c:1538
static int whip_check_bitstream(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
Definition whip.c:2162
STUNAttr
Definition whip.c:165
@ STUN_ATTR_PRIORITY
shared secret response/bind request
Definition whip.c:167
@ STUN_ATTR_MESSAGE_INTEGRITY
bind request
Definition whip.c:169
@ STUN_ATTR_ICE_CONTROLLING
rfc5389
Definition whip.c:171
@ STUN_ATTR_USE_CANDIDATE
must be included in a Binding request
Definition whip.c:168
@ STUN_ATTR_FINGERPRINT
bind request/response
Definition whip.c:170
@ STUN_ATTR_USERNAME
Definition whip.c:166
#define ICE_DTLS_READ_SLEEP_DURATION
Definition whip.c:78
static int media_is_rtcp(const uint8_t *b, int size)
Definition whip.c:1213
#define WHIP_ICE_CONSENT_CHECK_INTERVAL
Refer to RFC 7675 5.1,.
Definition whip.c:147
static int ice_create_request(AVFormatContext *s, uint8_t *buf, int buf_size, int *request_size)
Creates and marshals an ICE binding request packet.
Definition whip.c:1024
#define WHIP_SDP_CREATOR_IP
Definition whip.c:137
static av_cold int whip_init(AVFormatContext *s)
Definition whip.c:1843
static av_cold int initialize(AVFormatContext *s)
Initialize and check the options for the WebRTC muxer.
Definition whip.c:417
#define WHIP_RTP_PAYLOAD_TYPE_VIDEO_RTX
Definition whip.c:102
WHIPFlags
Definition whip.c:204
@ WHIP_DTLS_ACTIVE
Definition whip.c:205
static int ice_is_binding_request(uint8_t *b, int size)
A Binding request has class=0b00 (request) and method=0b000000000001 (Binding) and is encoded into th...
Definition whip.c:1186
#define WHIP_RTCP_PT_START
For RTCP, PT is [128, 223] (or without marker [0, 95]).
Definition whip.c:129
static int ice_is_binding_response(uint8_t *b, int size)
A Binding response has class=0b10 (success response) and method=0b000000000001, and is encoded into t...
Definition whip.c:1195
#define WHIP_SDP_SESSION_ID
In the case of ICE-LITE, these fields are not used; instead, they are defined as constant values.
Definition whip.c:136
#define WHIP_RTCP_PT_END
Definition whip.c:130
#define STUN_HOST_CANDIDATE_PRIORITY
Refer to RFC 8445 5.1.2 priority = (2^24)*(type preference) + (2^8)*(local preference) + (2^0)*(256 -...
Definition whip.c:88
static int dispose_session(AVFormatContext *s)
RTC is connectionless, for it's based on UDP, so it check whether sesison is timeout.
Definition whip.c:1708
static av_cold int certificate_key_init(AVFormatContext *s)
Get or Generate a self-signed certificate and private key for DTLS, fingerprint for SDP.
Definition whip.c:349
#define WHIP_RTP_HISTORY_MIN
RTP history packet size.
Definition whip.c:157
#define ICE_DTLS_READ_MAX_RETRY
If we try to read from UDP and get EAGAIN, we sleep for 5ms and retry up to 10 times.
Definition whip.c:77
#define WHIP_RTP_PAYLOAD_TYPE_H264
Definition whip.c:100
#define DTLS_SRTP_KEY_LEN
The size of the Secure Real-time Transport Protocol (SRTP) master key material that is exported by Se...
Definition whip.c:60
static av_cold int dtls_initialize(AVFormatContext *s)
Definition whip.c:377
#define WHIP_RTP_HISTORY_DEFAULT
Definition whip.c:158
static int setup_srtp(AVFormatContext *s)
Establish the SRTP context using the keying material exported from DTLS.
Definition whip.c:1419
static int parse_answer(AVFormatContext *s)
Parses the ICE ufrag, pwd, and candidates from the SDP answer.
Definition whip.c:894
static av_cold void whip_deinit(AVFormatContext *s)
Definition whip.c:2113
#define WHIP_RTP_HISTORY_MAX
Definition whip.c:159
static int ice_handle_binding_request(AVFormatContext *s, char *buf, int buf_size)
This function handles incoming binding request messages by responding to them.
Definition whip.c:1222
#define OFFSET(x)
Definition whip.c:2181
static int h264_annexb_insert_sps_pps(AVFormatContext *s, AVPacket *pkt)
Since the h264_mp4toannexb filter only processes the MP4 ISOM format and bypasses the annexb format,...
Definition whip.c:1768
static void handle_rtx_packet(AVFormatContext *s, uint16_t seq)
See https://datatracker.ietf.org/doc/html/rfc4588#section-4 Create RTX packet and send it out.
Definition whip.c:1885
static int parse_profile_level(AVFormatContext *s, AVCodecParameters *par)
When duplicating a stream, the demuxer has already set the extradata, profile, and level of the par.
Definition whip.c:481
static const AVClass whip_muxer_class
Definition whip.c:2197
static int create_rtp_muxer(AVFormatContext *s)
Creates dedicated RTP muxers for each stream in the AVFormatContext to build RTP packets from the enc...
Definition whip.c:1593
#define DTLS_SRTP_CHECKSUM_LEN
The maximum size of the Secure Real-time Transport Protocol (SRTP) HMAC checksum and padding that is ...
Definition whip.c:69