#pragma once #include "screencast/network/rtp_packet.h" #include #include #include #include namespace sc { struct EncodedFrame; // Smallest usable MTU: 12-byte RTP header + 2-byte FU-A prefix + 1 data byte. inline constexpr std::size_t kMinimumRtpMtu = 15; struct RtpPacketizerConfig { // Zero values ask the packetizer to choose random values, as recommended // by RFC 3550 for SSRC and the initial sequence number. std::uint32_t ssrc = 0; std::uint16_t initial_sequence_number = 0; std::uint8_t payload_type = 96; // dynamic payload type range std::size_t mtu = 1200; // maximum size of a serialized RTP packet }; // Splits Annex-B encoded frames into RFC 6184 RTP packets using single NAL // unit packets and FU-A fragmentation. STAP-A is never emitted. class H264Packetizer { public: explicit H264Packetizer(const RtpPacketizerConfig& config = RtpPacketizerConfig{}); // One encoded frame becomes one or more packets sharing the frame's RTP // timestamp; the final packet carries the marker bit. Returns an empty // vector for frames without NAL units or for an unusable MTU. std::vector packetize(const EncodedFrame& frame); private: RtpPacket next_packet(uint32_t timestamp); void append_fu_a_packets(std::span nal, uint32_t timestamp, std::vector& out); RtpPacketizerConfig config_; std::uint16_t next_sequence_number_ = 0; }; // Result of feeding one packet to the depacketizer. struct DepacketizeResult { // The completed access unit (Annex-B with 3-byte start codes) when the // packet closed an undamaged frame. std::optional> access_unit; // True when this call discarded a frame as damaged (packet loss or an // unsupported packetization). Pipelines use it to request a keyframe. bool frame_dropped = false; }; // Reassembles RFC 6184 packet streams (single NAL unit packets and FU-A) // into Annex-B access units. Packets must arrive in order; frames damaged by // sequence gaps or missing fragments are reported via DepacketizeResult. class H264Depacketizer { public: // Feed one packet. DepacketizeResult depacketize(const RtpPacket& packet); private: void drop_frame(); std::optional last_sequence_number_; bool frame_started_ = false; bool frame_damaged_ = false; std::uint32_t frame_timestamp_ = 0; std::vector access_unit_; bool fu_active_ = false; std::vector fu_nal_; }; } // namespace sc