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