FFmpeg
|
#include "libavcodec/avcodec.h"
#include "libavcodec/codec_desc.h"
#include "libavcodec/h264.h"
#include "libavcodec/startcode.h"
#include "libavutil/base64.h"
#include "libavutil/bprint.h"
#include "libavutil/crc.h"
#include "libavutil/hmac.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/lfg.h"
#include "libavutil/opt.h"
#include "libavutil/mem.h"
#include "libavutil/random_seed.h"
#include "libavutil/time.h"
#include "avc.h"
#include "nal.h"
#include "avio_internal.h"
#include "http.h"
#include "internal.h"
#include "mux.h"
#include "network.h"
#include "srtp.h"
#include "tls.h"
Go to the source code of this file.
Data Structures | |
struct | WHIPContext |
Macros | |
#define | MAX_SDP_SIZE 8192 |
Maximum size limit of a Session Description Protocol (SDP), be it an offer or answer. More... | |
#define | DTLS_SRTP_KEY_LEN 16 |
The size of the Secure Real-time Transport Protocol (SRTP) master key material that is exported by Secure Sockets Layer (SSL) after a successful Datagram Transport Layer Security (DTLS) handshake. More... | |
#define | DTLS_SRTP_SALT_LEN 14 |
#define | DTLS_SRTP_CHECKSUM_LEN 16 |
The maximum size of the Secure Real-time Transport Protocol (SRTP) HMAC checksum and padding that is appended to the end of the packet. More... | |
#define | ICE_DTLS_READ_INTERVAL 50 |
When sending ICE or DTLS messages, responses are received via UDP. More... | |
#define | STUN_MAGIC_COOKIE 0x2112A442 |
#define | DTLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC 20 |
The DTLS content type. More... | |
#define | DTLS_RECORD_LAYER_HEADER_LEN 13 |
The DTLS record layer header has a total size of 13 bytes, consisting of ContentType (1 byte), ProtocolVersion (2 bytes), Epoch (2 bytes), SequenceNumber (6 bytes), and Length (2 bytes). More... | |
#define | DTLS_VERSION_10 0xfeff |
The DTLS version number, which is 0xfeff for DTLS 1.0, or 0xfefd for DTLS 1.2. More... | |
#define | DTLS_VERSION_12 0xfefd |
#define | MAX_UDP_BUFFER_SIZE 4096 |
Maximum size of the buffer for sending and receiving UDP packets. More... | |
#define | WHIP_RTP_PAYLOAD_TYPE_H264 106 |
#define | WHIP_RTP_PAYLOAD_TYPE_OPUS 111 |
#define | ICE_STUN_HEADER_SIZE 20 |
The STUN message header, which is 20 bytes long, comprises the STUNMessageType (1B), MessageLength (2B), MagicCookie (4B), and TransactionID (12B). More... | |
#define | WHIP_RTP_HEADER_SIZE 12 |
The RTP header is 12 bytes long, comprising the Version(1B), PT(1B), SequenceNumber(2B), Timestamp(4B), and SSRC(4B). More... | |
#define | WHIP_RTCP_PT_START 192 |
For RTCP, PT is [128, 223] (or without marker [0, 95]). More... | |
#define | WHIP_RTCP_PT_END 223 |
#define | WHIP_SDP_SESSION_ID "4489045141692799359" |
In the case of ICE-LITE, these fields are not used; instead, they are defined as constant values. More... | |
#define | WHIP_SDP_CREATOR_IP "127.0.0.1" |
#define | ELAPSED(starttime, endtime) ((int)(endtime - starttime) / 1000) |
#define | OFFSET(x) offsetof(WHIPContext, x) |
#define | ENC AV_OPT_FLAG_ENCODING_PARAM |
Enumerations | |
enum | STUNAttr { STUN_ATTR_USERNAME = 0x0006, STUN_ATTR_USE_CANDIDATE = 0x0025, STUN_ATTR_MESSAGE_INTEGRITY = 0x0008, STUN_ATTR_FINGERPRINT = 0x8028 } |
enum | WHIPState { WHIP_STATE_NONE, WHIP_STATE_INIT, WHIP_STATE_OFFER, WHIP_STATE_ANSWER, WHIP_STATE_NEGOTIATED, WHIP_STATE_UDP_CONNECTED, WHIP_STATE_ICE_CONNECTING, WHIP_STATE_ICE_CONNECTED, WHIP_STATE_DTLS_CONNECTING, WHIP_STATE_DTLS_FINISHED, WHIP_STATE_SRTP_FINISHED, WHIP_STATE_READY, WHIP_STATE_FAILED } |
Functions | |
static int | is_dtls_packet (uint8_t *b, int size) |
Whether the packet is a DTLS packet. More... | |
static av_cold int | certificate_key_init (AVFormatContext *s) |
Get or Generate a self-signed certificate and private key for DTLS, fingerprint for SDP. More... | |
static int | dtls_context_on_state (AVFormatContext *s, const char *type, const char *desc) |
When DTLS state change. More... | |
static av_cold int | dtls_initialize (AVFormatContext *s) |
static av_cold int | initialize (AVFormatContext *s) |
Initialize and check the options for the WebRTC muxer. More... | |
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. More... | |
static int | parse_codec (AVFormatContext *s) |
Parses video SPS/PPS from the extradata of codecpar and checks the codec. More... | |
static int | generate_sdp_offer (AVFormatContext *s) |
Generate SDP offer according to the codec parameters, DTLS and ICE information. More... | |
static int | exchange_sdp (AVFormatContext *s) |
Exchange SDP offer with WebRTC peer to get the answer. More... | |
static int | parse_answer (AVFormatContext *s) |
Parses the ICE ufrag, pwd, and candidates from the SDP answer. More... | |
static int | ice_create_request (AVFormatContext *s, uint8_t *buf, int buf_size, int *request_size) |
Creates and marshals an ICE binding request packet. More... | |
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. More... | |
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 the first 16 bits as 0x0001. More... | |
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 the first 16 bits as 0x0101. More... | |
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) indicate the RTP version, see https://www.rfc-editor.org/rfc/rfc3550#section-5.1 The RTCP packet header is similar to RTP, see https://www.rfc-editor.org/rfc/rfc3550#section-6.4.1. More... | |
static int | media_is_rtcp (const uint8_t *b, int size) |
static int | ice_handle_binding_request (AVFormatContext *s, char *buf, int buf_size) |
This function handles incoming binding request messages by responding to them. More... | |
static int | udp_connect (AVFormatContext *s) |
To establish a connection with the UDP server, we utilize ICE-LITE in a Client-Server mode. More... | |
static int | ice_dtls_handshake (AVFormatContext *s) |
static int | setup_srtp (AVFormatContext *s) |
Establish the SRTP context using the keying material exported from DTLS. More... | |
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. More... | |
static int | create_rtp_muxer (AVFormatContext *s) |
Creates dedicated RTP muxers for each stream in the AVFormatContext to build RTP packets from the encoded frames. More... | |
static int | dispose_session (AVFormatContext *s) |
RTC is connectionless, for it's based on UDP, so it check whether sesison is timeout. More... | |
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, it is necessary to manually insert encoder metadata before each IDR when dealing with annexb format packets. More... | |
static av_cold int | whip_init (AVFormatContext *s) |
static int | whip_write_packet (AVFormatContext *s, AVPacket *pkt) |
static av_cold void | whip_deinit (AVFormatContext *s) |
static int | whip_check_bitstream (AVFormatContext *s, AVStream *st, const AVPacket *pkt) |
Variables | |
static const AVOption | options [] |
static const AVClass | whip_muxer_class |
const FFOutputFormat | ff_whip_muxer |
#define MAX_SDP_SIZE 8192 |
#define DTLS_SRTP_KEY_LEN 16 |
The size of the Secure Real-time Transport Protocol (SRTP) master key material that is exported by Secure Sockets Layer (SSL) after a successful Datagram Transport Layer Security (DTLS) handshake.
This material consists of a key of 16 bytes and a salt of 14 bytes.
#define DTLS_SRTP_CHECKSUM_LEN 16 |
The maximum size of the Secure Real-time Transport Protocol (SRTP) HMAC checksum and padding that is appended to the end of the packet.
To calculate the maximum size of the User Datagram Protocol (UDP) packet that can be sent out, subtract this size from the pkt_size
.
#define ICE_DTLS_READ_INTERVAL 50 |
When sending ICE or DTLS messages, responses are received via UDP.
However, the peer may not be ready and return EAGAIN, in which case we should wait for a short duration and retry reading. For instance, if we try to read from UDP and get EAGAIN, we sleep for 5ms and retry. This macro is used to limit the total duration in milliseconds (e.g., 50ms), so we will try at most 5 times. Keep in mind that this macro should have a minimum duration of 5 ms.
#define DTLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC 20 |
The DTLS content type.
See https://tools.ietf.org/html/rfc2246#section-6.2.1 change_cipher_spec(20), alert(21), handshake(22), application_data(23)
#define DTLS_RECORD_LAYER_HEADER_LEN 13 |
The DTLS record layer header has a total size of 13 bytes, consisting of ContentType (1 byte), ProtocolVersion (2 bytes), Epoch (2 bytes), SequenceNumber (6 bytes), and Length (2 bytes).
#define DTLS_VERSION_10 0xfeff |
The DTLS version number, which is 0xfeff for DTLS 1.0, or 0xfefd for DTLS 1.2.
See https://datatracker.ietf.org/doc/html/rfc9147#name-the-dtls-record-layer
#define MAX_UDP_BUFFER_SIZE 4096 |
Maximum size of the buffer for sending and receiving UDP packets.
Please note that this size does not limit the size of the UDP packet that can be sent. To set the limit for packet size, modify the pkt_size
parameter. For instance, it is possible to set the UDP buffer to 4096 to send or receive packets, but please keep in mind that the pkt_size
option limits the packet size to 1400.
#define ICE_STUN_HEADER_SIZE 20 |
The STUN message header, which is 20 bytes long, comprises the STUNMessageType (1B), MessageLength (2B), MagicCookie (4B), and TransactionID (12B).
#define WHIP_RTP_HEADER_SIZE 12 |
The RTP header is 12 bytes long, comprising the Version(1B), PT(1B), SequenceNumber(2B), Timestamp(4B), and SSRC(4B).
#define WHIP_RTCP_PT_START 192 |
For RTCP, PT is [128, 223] (or without marker [0, 95]).
Literally, RTCP starts from 64 not 0, so PT is [192, 223] (or without marker [64, 95]), see "RTCP Control Packet Types (PT)" at https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-4
For RTP, the PT is [96, 127], or [224, 255] with marker. See "RTP Payload Types (PT) for standard audio and video encodings" at https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-1
#define WHIP_SDP_SESSION_ID "4489045141692799359" |
#define ELAPSED | ( | starttime, | |
endtime | |||
) | ((int)(endtime - starttime) / 1000) |
#define OFFSET | ( | x | ) | offsetof(WHIPContext, x) |
#define ENC AV_OPT_FLAG_ENCODING_PARAM |
enum STUNAttr |
enum WHIPState |
|
static |
Whether the packet is a DTLS packet.
Definition at line 311 of file whip.c.
Referenced by ice_dtls_handshake(), and whip_write_packet().
|
static |
Get or Generate a self-signed certificate and private key for DTLS, fingerprint for SDP.
Definition at line 323 of file whip.c.
Referenced by initialize().
|
static |
|
static |
Definition at line 386 of file whip.c.
Referenced by ice_dtls_handshake().
|
static |
Initialize and check the options for the WebRTC muxer.
Definition at line 397 of file whip.c.
Referenced by whip_init().
|
static |
When duplicating a stream, the demuxer has already set the extradata, profile, and level of the par.
Keep in mind that this function will not be invoked since the profile and level are set.
When utilizing an encoder, such as libx264, to encode a stream, the extradata in par->extradata contains the SPS, which includes profile and level information. However, the profile and level of par remain unspecified. Therefore, it is necessary to extract the profile and level data from the extradata and assign it to the par's profile and level. Keep in mind that AVFMT_GLOBALHEADER must be enabled; otherwise, the extradata will remain empty.
Definition at line 440 of file whip.c.
Referenced by parse_codec().
|
static |
Parses video SPS/PPS from the extradata of codecpar and checks the codec.
Currently only supports video(h264) and audio(opus). Note that only baseline and constrained baseline profiles of h264 are supported.
If the profile is less than 0, the function considers the profile as baseline. It may need to parse the profile from SPS/PPS. This situation occurs when ingesting desktop and transcoding.
s | Pointer to the AVFormatContext |
TODO: FIXME: There is an issue with the timestamp of OPUS audio, especially when the input is an MP4 file. The timestamp deviates from the expected value of 960, causing Chrome to play the audio stream with noise. This problem can be replicated by transcoding a specific file into MP4 format and publishing it using the WHIP muxer. However, when directly transcoding and publishing through the WHIP muxer, the issue is not present, and the audio timestamp remains consistent. The root cause is still unknown, and this comment has been added to address this issue in the future. Further research is needed to resolve the problem.
Definition at line 507 of file whip.c.
Referenced by whip_init().
|
static |
Generate SDP offer according to the codec parameters, DTLS and ICE information.
Note that we don't use av_sdp_create to generate SDP offer because it doesn't support DTLS and ICE information.
Definition at line 590 of file whip.c.
Referenced by whip_init().
|
static |
Exchange SDP offer with WebRTC peer to get the answer.
Definition at line 725 of file whip.c.
Referenced by whip_init().
|
static |
Parses the ICE ufrag, pwd, and candidates from the SDP answer.
This function is used to extract the ICE ufrag, pwd, and candidates from the SDP answer. It returns an error if any of these fields is NULL. The function only uses the first candidate if there are multiple candidates. However, support for multiple candidates will be added in the future.
s | Pointer to the AVFormatContext |
Definition at line 844 of file whip.c.
Referenced by whip_init().
|
static |
Creates and marshals an ICE binding request packet.
This function creates and marshals an ICE binding request packet. The function only generates the username attribute and does not include goog-network-info, ice-controlling, use-candidate, and priority. However, some of these attributes may be added in the future.
s | Pointer to the AVFormatContext |
buf | Pointer to memory buffer to store the request packet |
buf_size | Size of the memory buffer |
request_size | Pointer to an integer that receives the size of the request packet |
Definition at line 951 of file whip.c.
Referenced by ice_dtls_handshake().
|
static |
Create an ICE binding response.
This function generates an ICE binding response and writes it to the provided buffer. The response is signed using the local password for message integrity.
s | Pointer to the AVFormatContext structure. |
tid | Pointer to the transaction ID of the binding request. The tid_size should be 12. |
tid_size | The size of the transaction ID, should be 12. |
buf | Pointer to the buffer where the response will be written. |
buf_size | The size of the buffer provided for the response. |
response_size | Pointer to an integer that will store the size of the generated response. |
Definition at line 1041 of file whip.c.
Referenced by ice_handle_binding_request().
|
static |
A Binding request has class=0b00 (request) and method=0b000000000001 (Binding) and is encoded into the first 16 bits as 0x0001.
See https://datatracker.ietf.org/doc/html/rfc5389#section-6
Definition at line 1105 of file whip.c.
Referenced by ice_dtls_handshake(), and ice_handle_binding_request().
|
static |
A Binding response has class=0b10 (success response) and method=0b000000000001, and is encoded into the first 16 bits as 0x0101.
Definition at line 1114 of file whip.c.
Referenced by ice_dtls_handshake().
|
static |
In RTP packets, the first byte is represented as 0b10xxxxxx, where the initial two bits (0b10) indicate the RTP version, see https://www.rfc-editor.org/rfc/rfc3550#section-5.1 The RTCP packet header is similar to RTP, see https://www.rfc-editor.org/rfc/rfc3550#section-6.4.1.
Definition at line 1126 of file whip.c.
Referenced by on_rtp_write_packet().
|
static |
Definition at line 1132 of file whip.c.
Referenced by on_rtp_write_packet().
|
static |
This function handles incoming binding request messages by responding to them.
If the message is not a binding request, it will be ignored.
Definition at line 1141 of file whip.c.
Referenced by ice_dtls_handshake().
|
static |
To establish a connection with the UDP server, we utilize ICE-LITE in a Client-Server mode.
In this setup, FFmpeg acts as the UDP client, while the peer functions as the UDP server.
Definition at line 1181 of file whip.c.
Referenced by whip_init().
|
static |
Definition at line 1218 of file whip.c.
Referenced by whip_init().
|
static |
Establish the SRTP context using the keying material exported from DTLS.
Create separate SRTP contexts for sending video and audio, as their sequences differ and should not share a single context. Generate a single SRTP context for receiving RTCP only.
The profile for OpenSSL's SRTP is SRTP_AES128_CM_SHA1_80, see ssl/d1_srtp.c. The profile for FFmpeg's SRTP is SRTP_AES128_CM_HMAC_SHA1_80, see libavformat/srtp.c.
This represents the material used to build the SRTP master key. It is generated by DTLS and has the following layout: 16B 16B 14B 14B client_key | server_key | client_salt | server_salt
Definition at line 1350 of file whip.c.
Referenced by whip_init().
|
static |
Callback triggered by the RTP muxer when it creates and sends out an RTP packet.
This function modifies the video STAP packet, removing the markers, and updating the NRI of the first NALU. Additionally, it uses the corresponding SRTP context to encrypt the RTP packet, where the video packet is handled by the video SRTP context.
Definition at line 1439 of file whip.c.
Referenced by create_rtp_muxer().
|
static |
Creates dedicated RTP muxers for each stream in the AVFormatContext to build RTP packets from the encoded frames.
The corresponding SRTP context is utilized to encrypt each stream's RTP packets. For example, a video SRTP context is used for the video stream. Additionally, the "on_rtp_write_packet" callback function is set as the write function for each RTP muxer to send out encrypted RTP packets.
For H.264, consistently utilize the annexb format through the Bitstream Filter (BSF); therefore, we deactivate the extradata detection for the RTP muxer.
Definition at line 1488 of file whip.c.
Referenced by whip_init().
|
static |
RTC is connectionless, for it's based on UDP, so it check whether sesison is timeout.
In such case, publishers can't republish the stream util the session is timeout. This function is called to notify the server that the stream is ended, server should expire and close the session immediately, so that publishers can republish the stream quickly.
Definition at line 1606 of file whip.c.
Referenced by whip_deinit().
|
static |
Since the h264_mp4toannexb filter only processes the MP4 ISOM format and bypasses the annexb format, it is necessary to manually insert encoder metadata before each IDR when dealing with annexb format packets.
For instance, in the case of H.264, we must insert SPS and PPS before the IDR frame.
Definition at line 1662 of file whip.c.
Referenced by whip_write_packet().
|
static |
|
static |
|
static |
|
static |
|
static |
const FFOutputFormat ff_whip_muxer |