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