52#define MAX_SDP_SIZE 8192
60#define DTLS_SRTP_KEY_LEN 16
61#define DTLS_SRTP_SALT_LEN 14
69#define DTLS_SRTP_CHECKSUM_LEN 16
71#define WHIP_US_PER_MS 1000
77#define ICE_DTLS_READ_MAX_RETRY 10
78#define ICE_DTLS_READ_SLEEP_DURATION 5
81#define STUN_MAGIC_COOKIE 0x2112A442
88#define STUN_HOST_CANDIDATE_PRIORITY 126 << 24 | 65535 << 8 | 255
97#define MAX_UDP_BUFFER_SIZE 4096
100#define WHIP_RTP_PAYLOAD_TYPE_H264 106
101#define WHIP_RTP_PAYLOAD_TYPE_OPUS 111
102#define WHIP_RTP_PAYLOAD_TYPE_VIDEO_RTX 105
110#define ICE_STUN_HEADER_SIZE 20
117#define WHIP_RTP_HEADER_SIZE 12
129#define WHIP_RTCP_PT_START 192
130#define WHIP_RTCP_PT_END 223
136#define WHIP_SDP_SESSION_ID "4489045141692799359"
137#define WHIP_SDP_CREATOR_IP "127.0.0.1"
147#define WHIP_ICE_CONSENT_CHECK_INTERVAL 5000
148#define WHIP_ICE_CONSENT_EXPIRED_TIMER 30000
157#define WHIP_RTP_HISTORY_MIN 64
158#define WHIP_RTP_HISTORY_DEFAULT 512
159#define WHIP_RTP_HISTORY_MAX 2048
162#define ELAPSED(starttime, endtime) ((float)(endtime - starttime) / 1000)
402 &
opts,
s->protocol_whitelist,
s->protocol_blacklist,
NULL);
419 int ret, ideal_pkt_size = 532;
445 if (whip->
pkt_size < ideal_pkt_size)
463 av_log(whip,
AV_LOG_VERBOSE,
"Init state=%d, handshake_timeout=%dms, pkt_size=%d, seed=%d, elapsed=%.2fms\n",
496 av_log(whip,
AV_LOG_ERROR,
"Unable to parse profile from empty extradata=%p, size=%d\n",
516 sps->profile_idc,
sps->level_idc);
553 for (
i = 0;
i <
s->nb_streams;
i++) {
611 const char *acodec_name =
NULL, *vcodec_name =
NULL;
613 int bundle_index = 0;
642 bundle[bundle_index++] =
'0';
643 bundle[bundle_index++] =
' ';
646 bundle[bundle_index++] =
'1';
647 bundle[bundle_index++] =
' ';
649 bundle[bundle_index - 1] =
'\0';
653 "o=FFmpeg %s 2 IN IP4 %s\r\n"
654 "s=FFmpegPublishSession\r\n"
656 "a=group:BUNDLE %s\r\n"
657 "a=extmap-allow-mixed\r\n"
658 "a=msid-semantic: WMS\r\n",
665 acodec_name =
"opus";
668 "m=audio 9 UDP/TLS/RTP/SAVPF %u\r\n"
669 "c=IN IP4 0.0.0.0\r\n"
672 "a=fingerprint:sha-256 %s\r\n"
676 "a=msid:FFmpeg audio\r\n"
678 "a=rtpmap:%u %s/%d/%d\r\n"
679 "a=ssrc:%u cname:FFmpeg\r\n"
680 "a=ssrc:%u msid:FFmpeg audio\r\n",
685 is_dtls_active ?
"active" :
"passive",
697 vcodec_name =
"H264";
704 "m=video 9 UDP/TLS/RTP/SAVPF %u %u\r\n"
705 "c=IN IP4 0.0.0.0\r\n"
708 "a=fingerprint:sha-256 %s\r\n"
712 "a=msid:FFmpeg video\r\n"
715 "a=rtpmap:%u %s/90000\r\n"
716 "a=fmtp:%u level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=%02x%02x%02x\r\n"
717 "a=rtcp-fb:%u nack\r\n"
718 "a=rtpmap:%u rtx/90000\r\n"
719 "a=fmtp:%u apt=%u\r\n"
720 "a=ssrc-group:FID %u %u\r\n"
721 "a=ssrc:%u cname:FFmpeg\r\n"
722 "a=ssrc:%u msid:FFmpeg video\r\n",
728 is_dtls_active ?
"active" :
"passive",
781 char *hex_data =
NULL;
788 av_log(whip,
AV_LOG_ERROR,
"Protocol %s is not supported by RTC, choose http, url is %s\n",
800 ret =
snprintf(buf,
sizeof(buf),
"Cache-Control: no-cache\r\nContent-Type: application/sdp\r\n");
803 if (ret <= 0 || ret >=
sizeof(buf)) {
815 const size_t sdp_offer_len = strlen(whip->
sdp_offer);
816 hex_data =
av_malloc(2 * sdp_offer_len + 1);
825 &
opts,
s->protocol_whitelist,
s->protocol_blacklist,
NULL);
847 av_log(whip,
AV_LOG_ERROR,
"Failed to read response from url=%s, offer is %s, answer is %s\n",
931 const char *
space = strchr(ptr,
' ');
942 char foundation[33], protocol[17], host[129];
943 int component_id, priority, port;
944 ret = sscanf(ptr,
"%32s %d %16s %d %128s %d typ host", foundation, &component_id, protocol, &priority, host, &port);
953 av_log(whip,
AV_LOG_ERROR,
"Protocol %s is not supported by RTC, choose udp, line %d %s of %s\n",
994 "No remote DTLS fingerprint in SDP answer; refusing unauthenticated session\n");
1002 av_log(whip,
AV_LOG_VERBOSE,
"SDP state=%d, offer=%zuB, answer=%zuB, ufrag=%s, pwd=%zuB, transport=%s://%s:%d, elapsed=%.2fms\n",
1052 if (ret <= 0 || ret >=
sizeof(username)) {
1082 buf[2] = (
size - 20) >> 8;
1083 buf[3] = (
size - 20) & 0xFF;
1093 buf[2] = (
size - 20) >> 8;
1094 buf[3] = (
size - 20) & 0xFF;
1129 if (tid_size != 12) {
1130 av_log(whip,
AV_LOG_ERROR,
"Invalid transaction ID size. Expected 12, got %d\n", tid_size);
1155 buf[2] = (
size - 20) >> 8;
1156 buf[3] = (
size - 20) & 0xFF;
1166 buf[2] = (
size - 20) >> 8;
1167 buf[3] = (
size - 20) & 0xFF;
1173 *response_size =
size;
1239 memcpy(tid, buf + 8, 12);
1279 &
opts,
s->protocol_whitelist,
s->protocol_blacklist,
NULL);
1302 int ret = 0,
size,
i;
1338 av_log(whip,
AV_LOG_ERROR,
"DTLS handshake timeout=%dms, cost=%.2fms, elapsed=%.2fms, state=%d\n",
1383 av_log(whip,
AV_LOG_VERBOSE,
"ICE STUN ok, state=%d, url=udp://%s:%d, location=%s, username=%s:%s, res=%dB, elapsed=%.2fms\n",
1429 const char* suite =
"SRTP_AES128_CM_HMAC_SHA1_80";
1432 char *cp = is_dtls_active ? send_key : recv_key;
1433 char *sp = is_dtls_active ? recv_key : send_key;
1502 av_log(whip,
AV_LOG_VERBOSE,
"SRTP setup done, state=%d, suite=%s, key=%zuB, elapsed=%.2fms\n",
1511 uint16_t seq =
AV_RB16(buf + 2);
1528 return it->
seq == seq ? it :
NULL;
1540 int ret, cipher_size, is_rtcp, is_video;
1541 uint8_t payload_type;
1552 payload_type = buf[1] & 0x7f;
1562 if (cipher_size <= 0 || cipher_size < buf_size) {
1563 av_log(whip,
AV_LOG_WARNING,
"Failed to encrypt packet=%dB, cipher=%dB\n", buf_size, cipher_size);
1575 av_log(whip,
AV_LOG_ERROR,
"Failed to write packet=%dB, ret=%d\n", cipher_size, ret);
1595 int ret,
i, is_video, buffer_size, max_packet_size;
1608 for (
i = 0;
i <
s->nb_streams;
i++) {
1672 s->streams[
i]->priv_data = rtp_ctx;
1678 av_log(whip,
AV_LOG_INFO,
"Muxer state=%d, buffer_size=%d, max_packet_size=%d, "
1679 "elapsed=%.2fms(init:%.2f,offer:%.2f,answer:%.2f,udp:%.2f,ice:%.2f,dtls:%.2f,srtp:%.2f)\n",
1719 ret =
snprintf(buf,
sizeof(buf),
"Cache-Control: no-cache\r\n");
1722 if (ret <= 0 || ret >=
sizeof(buf)) {
1736 &
opts,
s->protocol_whitelist,
s->protocol_blacklist,
NULL);
1774 uint8_t unit_type, sps_seen = 0, pps_seen = 0, idr_seen = 0, *
out;
1775 const uint8_t *buf, *buf_end, *r1;
1781 buf_end =
pkt->data +
pkt->size;
1785 if ((nal_size = r1 - buf) > 0) {
1786 unit_type = *buf & 0x1f;
1799 if (!idr_seen || (sps_seen && pps_seen))
1828 if ((nal_size = r1 - buf) > 0) {
1830 memcpy(
out + 3, buf, nal_size);
1831 out += 3 + nal_size;
1890 int ori_size, rtx_size, cipher_size;
1897 "RTP history packet seq=%"PRIu16
" not found, latest seq=%"PRIu16
"\n",
1902 "Found RTP history packet for RTX, seq=%"PRIu16
", latest seq=%"PRIu16
"\n",
1906 ori_size = it->
size;
1915 if (ori_size + 2 >
sizeof(rtx_buf)) {
1920 memcpy(rtx_buf, ori_buf, ori_size);
1921 ori_seq =
AV_RB16(rtx_buf + 2);
1929 memmove(rtx_buf + 12 + 2, rtx_buf + 12, ori_size - 12);
1930 AV_WB16(rtx_buf + 12, ori_seq);
1932 rtx_size = ori_size + 2;
1935 whip->
buf,
sizeof(whip->
buf));
1936 if (cipher_size <= 0) {
1938 "Failed to encrypt RTX packet, size=%d, cipher_size=%d\n",
1939 rtx_size, cipher_size);
1952 uint8_t *buf =
NULL;
1953 int rtcp_len, srtcp_len, header_len = 12;
1962 if (rtcp_len <= header_len) {
1967 srtcp_len = rtcp_len + 4 + 10;
1968 if (srtcp_len !=
size) {
1982 "NACK packet SSRC: %"PRIu32
" not match with video track SSRC: %"PRIu32
"\n",
1986 while (header_len +
i + 4 <= rtcp_len) {
1991 uint16_t pid =
AV_RB16(&buf[12 +
i]);
1992 uint16_t blp =
AV_RB16(&buf[14 +
i]);
1997 uint16_t seq = pid +
bit + 1;
2000 if (!(blp & (1 <<
bit)))
2067 uint8_t fmt = whip->
buf[0] & 0x1f;
2068 uint8_t
pt = whip->
buf[1];
2083 "Consent Freshness expired after %.2fms (limited %dms), terminate session\n",
2100 }
else if (ret ==
AVERROR(EAGAIN)) {
2101 av_log(whip,
AV_LOG_ERROR,
"UDP send blocked, please increase the buffer via -ts_buffer_size\n");
2122 for (
i = 0;
i <
s->nb_streams;
i++) {
2136 s->streams[
i]->priv_data =
NULL;
2164 int ret = 1, extradata_isom = 0;
2165 uint8_t *
b =
pkt->data;
2170 if (
pkt->size >= 5 &&
AV_RB32(
b) != 0x0000001 && (
AV_RB24(
b) != 0x000001 || extradata_isom)) {
2172 av_log(whip,
AV_LOG_VERBOSE,
"Enable BSF h264_mp4toannexb, packet=[%x %x %x %x %x ...], extradata_isom=%d\n",
2173 b[0],
b[1],
b[2],
b[3],
b[4], extradata_isom);
2181#define OFFSET(x) offsetof(WHIPContext, x)
2182#define ENC AV_OPT_FLAG_ENCODING_PARAM
2184 {
"handshake_timeout",
"Timeout in milliseconds for ICE and DTLS handshake.",
OFFSET(handshake_timeout),
AV_OPT_TYPE_INT, { .i64 = 5000 }, -1, INT_MAX,
ENC },
2186 {
"pkt_size",
"The maximum size, in bytes, of RTP packets that send out",
OFFSET(pkt_size),
AV_OPT_TYPE_INT, { .i64 = 1200 }, -1, INT_MAX,
ENC },
2187 {
"ts_buffer_size",
"The buffer size, in bytes, of underlying protocol",
OFFSET(ts_buffer_size),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX,
ENC },
2198 .class_name =
"WHIP muxer",
static AVDictionary * opts
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
int ff_avc_decode_sps(H264SPS *sps, const uint8_t *buf, int buf_size)
int ffurl_handshake(URLContext *c)
Perform one step of the protocol handshake to accept a new client.
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.
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
int ffurl_get_file_handle(URLContext *h)
Return the file descriptor associated with this URL.
const AVClass ff_avio_class
const char * avio_find_protocol_name(const char *url)
Return the name of the protocol that will handle the passed URL.
void avio_wb32(AVIOContext *s, unsigned int val)
void avio_wb16(AVIOContext *s, unsigned int val)
#define AVIO_FLAG_READ
read-only
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
#define AVIO_FLAG_WRITE
write-only
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
void avio_wb64(AVIOContext *s, uint64_t val)
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.
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
void avio_context_free(AVIOContext **s)
Free the supplied IO context and everything associated with it.
#define AVIO_FLAG_NONBLOCK
Use non-blocking mode.
void ffio_fill(AVIOContext *s, int b, int64_t count)
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.
void av_bprintf(AVBPrint *buf, const char *fmt,...)
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
#define flags(name, subs,...)
#define i(width, name, range_min, range_max)
static int FUNC sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
#define bit(string, value)
static void deinit(AVFormatContext *s)
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Public header for CRC hash function implementation.
static unsigned crc32(const uint8_t *data, unsigned size)
#define AV_PROFILE_UNKNOWN
#define AV_PROFILE_H264_CONSTRAINED
#define AV_PROFILE_H264_INTRA
int(* init)(AVBSFContext *ctx)
static struct @346255127015250356166251341105367306144006377143 state
static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_DURATION
Underlying C type is int64_t.
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ 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...
void av_packet_free(AVPacket **pkt)
Free the packet, if the packet is reference counted, it will be unreferenced first.
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
int av_packet_make_refcounted(AVPacket *pkt)
Ensure the data described by a given packet is reference counted.
void av_packet_move_ref(AVPacket *dst, AVPacket *src)
Move every field in src to dst and reset src.
AVPacket * av_packet_alloc(void)
Allocate an AVPacket and set its fields to default values.
int av_packet_copy_props(AVPacket *dst, const AVPacket *src)
Copy only "properties" fields from src to dst.
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
AVStream * avformat_new_stream(AVFormatContext *s, const struct AVCodec *c)
Add a new stream to a media file.
AVFormatContext * avformat_alloc_context(void)
Allocate an AVFormatContext.
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
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.
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
char * av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
Encode data to base64 and null-terminate.
#define AV_BASE64_SIZE(x)
Calculate the output size needed to base64-encode x bytes to a null-terminated string.
const AVCRC * av_crc_get_table(AVCRCId crc_id)
Get an initialized standard CRC table.
uint32_t av_crc(const AVCRC *ctx, uint32_t crc, const uint8_t *buffer, size_t length)
Calculate the CRC of a block.
uint32_t av_get_random_seed(void)
Get a seed to use in conjunction with random functions.
int av_random_bytes(uint8_t *buf, size_t len)
Generate cryptographically secure random data, i.e.
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that's been allocated with av_malloc() or another memory allocation functio...
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
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.
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
#define AVERROR_EOF
End of file.
int av_hmac_final(AVHMAC *c, uint8_t *out, unsigned int outlen)
Finish hashing and output the HMAC digest.
AVHMAC * av_hmac_alloc(enum AVHMACType type)
Allocate an AVHMAC context.
void av_hmac_update(AVHMAC *c, const uint8_t *data, unsigned int len)
Hash data with the HMAC.
void av_hmac_free(AVHMAC *c)
Free an AVHMAC context.
void av_hmac_init(AVHMAC *c, const uint8_t *key, unsigned int keylen)
Initialize an AVHMAC context with an authentication key.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const char * av_default_item_name(void *ptr)
Return the context name.
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
char * av_stristr(const char *s1, const char *s2)
Locate the first case-independent occurrence in the string haystack of the string needle.
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
#define LIBAVUTIL_VERSION_INT
H.264 common definitions.
static uint64_t request_size(URLContext *h)
const char * ff_http_get_new_location(URLContext *h)
av_cold void av_lfg_init(AVLFG *c, unsigned int seed)
static unsigned int av_lfg_get(AVLFG *c)
Get the next random unsigned 32-bit number using an ALFG.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
#define FF_OFMT_FLAG_MAX_ONE_OF_EACH
If this flag is set, it indicates that for each codec type whose corresponding default codec (i....
#define FF_OFMT_FLAG_ONLY_DEFAULT_CODECS
If this flag is set, then the only permitted audio/video/subtitle codec ids are AVOutputFormat....
const uint8_t * ff_nal_find_startcode(const uint8_t *p, const uint8_t *end)
int ff_socket_nonblock(int socket, int enable)
int ff_srtp_encrypt(struct SRTPContext *s, const uint8_t *in, int len, uint8_t *out, int outlen)
int ff_srtp_set_crypto(struct SRTPContext *s, const char *suite, const char *params)
int ff_srtp_decrypt(struct SRTPContext *s, uint8_t *buf, int *lenptr)
void ff_srtp_free(struct SRTPContext *s)
Accelerated start code search function for start codes common to MPEG-1/2/4 video,...
const uint8_t * avpriv_find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state)
int nb_channels
Number of channels in this layout.
Describe the class of an AVClass context structure.
This struct describes the properties of an encoded stream.
int extradata_size
Size of the extradata content in bytes.
AVChannelLayout ch_layout
The channel layout and number of channels.
enum AVMediaType codec_type
General type of the encoded data.
int profile
Codec-specific bitstream restrictions that the stream conforms to.
int video_delay
Number of delayed frames.
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
int sample_rate
The number of audio samples per second.
AVIOContext * pb
I/O context.
int flags
Flags modifying the (de)muxer behaviour.
const struct AVOutputFormat * oformat
The output container format.
int strict_std_compliance
Allow non-standard and experimental extension.
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
int64_t start_time_realtime
Start time of the stream in real world time, in microseconds since the Unix epoch (00:00 1st January ...
AVStream ** streams
A list of all streams in the file.
const AVClass * av_class
A class for private options.
unsigned char * buffer
Start of the buffer.
Context structure for the Lagged Fibonacci PRNG.
This structure stores compressed data.
AVCodecParameters * codecpar
Codec parameters associated with this stream.
AVRational sample_aspect_ratio
sample aspect ratio (0 if unknown)
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
int64_t whip_last_consent_tx_time
char * authorization
The optional Bearer token for WHIP Authorization.
SRTPContext srtp_rtcp_send
AVCodecParameters * audio_par
char * remote_fingerprint
char key_buf[MAX_CERTIFICATE_SIZE]
char cert_buf[MAX_CERTIFICATE_SIZE]
char * ice_protocol
This represents the ICE candidate protocol, priority, host and port.
uint8_t video_payload_type
int64_t whip_last_consent_rx_time
char buf[MAX_UDP_BUFFER_SIZE]
uint8_t video_rtx_payload_type
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.
int pkt_size
The size of RTP packet, should generally be set to MTU.
AVCodecParameters * video_par
SRTPContext srtp_audio_send
SRTPContext srtp_video_send
int h264_annexb_insert_sps_pps
The h264_mp4toannexb Bitstream Filter (BSF) bypasses the AnnexB packet; therefore,...
SRTPContext srtp_video_rtx_send
char * sdp_offer
This is the SDP offer generated by the muxer based on the codec parameters, DTLS, and ICE information...
uint8_t audio_payload_type
static void error(const char *err)
int av_usleep(unsigned usec)
Sleep for a period of time.
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
int ff_is_dtls_packet(const uint8_t *buf, int size)
Whether the packet is a DTLS packet, as defined by RFC 5764 Section 5.1.2.
int ff_ssl_gen_key_cert(char *key_buf, size_t key_sz, char *cert_buf, size_t cert_sz, char **fingerprint)
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)
#define MAX_CERTIFICATE_SIZE
Maximum size limit of a certificate and private key size.
int ff_dtls_export_materials(URLContext *h, char *dtls_srtp_materials, size_t materials_sz)
int ff_tls_set_external_socket(URLContext *h, URLContext *sock)
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
static int ffurl_write(URLContext *h, const uint8_t *buf, int size)
Write size bytes from buf to the resource accessed by h.
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.
static int rtp_history_store(WHIPContext *whip, const uint8_t *buf, int size)
#define STUN_MAGIC_COOKIE
static int udp_connect(AVFormatContext *s)
To establish a connection with the UDP server, we utilize ICE-LITE in a Client-Server mode.
#define WHIP_ICE_CONSENT_EXPIRED_TIMER
#define MAX_SDP_SIZE
Maximum size limit of a Session Description Protocol (SDP), be it an offer or answer.
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.
static int parse_codec(AVFormatContext *s)
Parses video SPS/PPS from the extradata of codecpar and checks the codec.
@ WHIP_STATE_NEGOTIATED
After parsing the answer received from the peer, the muxer negotiates the abilities in the offer that...
@ WHIP_STATE_ICE_CONNECTING
@ WHIP_STATE_ICE_CONNECTED
@ WHIP_STATE_DTLS_FINISHED
@ WHIP_STATE_SRTP_FINISHED
@ WHIP_STATE_UDP_CONNECTED
static void handle_nack_rtx(AVFormatContext *s, int size)
static const RtpHistoryItem * rtp_history_find(WHIPContext *whip, uint16_t seq)
static int ice_dtls_handshake(AVFormatContext *s)
#define MAX_UDP_BUFFER_SIZE
Maximum size of the buffer for sending and receiving UDP packets.
#define DTLS_SRTP_SALT_LEN
#define ICE_STUN_HEADER_SIZE
The STUN message header, which is 20 bytes long, comprises the STUNMessageType (1B),...
#define WHIP_RTP_PAYLOAD_TYPE_OPUS
#define WHIP_RTP_HEADER_SIZE
The RTP header is 12 bytes long, comprising the Version(1B), PT(1B), SequenceNumber(2B),...
static int exchange_sdp(AVFormatContext *s)
Exchange SDP offer with WebRTC peer to get the answer.
#define ELAPSED(starttime, endtime)
static int whip_write_packet(AVFormatContext *s, AVPacket *pkt)
static int generate_sdp_offer(AVFormatContext *s)
Generate SDP offer according to the codec parameters, DTLS and ICE information.
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...
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.
static int whip_check_bitstream(AVFormatContext *s, AVStream *st, const AVPacket *pkt)
@ STUN_ATTR_PRIORITY
shared secret response/bind request
@ STUN_ATTR_MESSAGE_INTEGRITY
bind request
@ STUN_ATTR_ICE_CONTROLLING
rfc5389
@ STUN_ATTR_USE_CANDIDATE
must be included in a Binding request
@ STUN_ATTR_FINGERPRINT
bind request/response
#define ICE_DTLS_READ_SLEEP_DURATION
static int media_is_rtcp(const uint8_t *b, int size)
#define WHIP_ICE_CONSENT_CHECK_INTERVAL
Refer to RFC 7675 5.1,.
static int ice_create_request(AVFormatContext *s, uint8_t *buf, int buf_size, int *request_size)
Creates and marshals an ICE binding request packet.
#define WHIP_SDP_CREATOR_IP
static av_cold int whip_init(AVFormatContext *s)
static av_cold int initialize(AVFormatContext *s)
Initialize and check the options for the WebRTC muxer.
#define WHIP_RTP_PAYLOAD_TYPE_VIDEO_RTX
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...
#define WHIP_RTCP_PT_START
For RTCP, PT is [128, 223] (or without marker [0, 95]).
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...
#define WHIP_SDP_SESSION_ID
In the case of ICE-LITE, these fields are not used; instead, they are defined as constant values.
#define STUN_HOST_CANDIDATE_PRIORITY
Refer to RFC 8445 5.1.2 priority = (2^24)*(type preference) + (2^8)*(local preference) + (2^0)*(256 -...
static int dispose_session(AVFormatContext *s)
RTC is connectionless, for it's based on UDP, so it check whether sesison is timeout.
static av_cold int certificate_key_init(AVFormatContext *s)
Get or Generate a self-signed certificate and private key for DTLS, fingerprint for SDP.
#define WHIP_RTP_HISTORY_MIN
RTP history packet size.
#define ICE_DTLS_READ_MAX_RETRY
If we try to read from UDP and get EAGAIN, we sleep for 5ms and retry up to 10 times.
#define WHIP_RTP_PAYLOAD_TYPE_H264
#define DTLS_SRTP_KEY_LEN
The size of the Secure Real-time Transport Protocol (SRTP) master key material that is exported by Se...
static av_cold int dtls_initialize(AVFormatContext *s)
#define WHIP_RTP_HISTORY_DEFAULT
static int setup_srtp(AVFormatContext *s)
Establish the SRTP context using the keying material exported from DTLS.
static int parse_answer(AVFormatContext *s)
Parses the ICE ufrag, pwd, and candidates from the SDP answer.
static av_cold void whip_deinit(AVFormatContext *s)
#define WHIP_RTP_HISTORY_MAX
static int ice_handle_binding_request(AVFormatContext *s, char *buf, int buf_size)
This function handles incoming binding request messages by responding to them.
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,...
static void handle_rtx_packet(AVFormatContext *s, uint16_t seq)
See https://datatracker.ietf.org/doc/html/rfc4588#section-4 Create RTX packet and send it out.
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.
static const AVClass whip_muxer_class
static int create_rtp_muxer(AVFormatContext *s)
Creates dedicated RTP muxers for each stream in the AVFormatContext to build RTP packets from the enc...
#define DTLS_SRTP_CHECKSUM_LEN
The maximum size of the Secure Real-time Transport Protocol (SRTP) HMAC checksum and padding that is ...