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