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