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