Skip to main content

rtp_packet/
lib.rs

1//! RTP fixed header + CSRC list + generic header extension — RFC 3550 §5.1 /
2//! §5.3.1, spec-complete (not just a happy-path subset).
3//!
4//! This crate implements exactly the wire structures described in the curated
5//! spec transcription at `rtp-packet/docs/rtp-header.md` (fetched directly
6//! from [RFC 3550](https://www.rfc-editor.org/rfc/rfc3550.txt)) — cite that
7//! file, not this doc comment, as the field-semantics oracle.
8//!
9//! - [`RtpPacket`] — the §5.1 fixed header (version/padding/extension bit/
10//!   CSRC-count/marker/payload-type/sequence-number/timestamp/SSRC), the CSRC
11//!   identifier list (0–15 entries), the optional §5.3.1 header extension, an
12//!   optional trailing padding region, and the payload.
13//! - [`HeaderExtension`] — the §5.3.1 generic header extension: a 16-bit
14//!   profile-specific identifier + opaque profile-specific data.
15//!
16//! `version`/`P`/`X`/`CC` are never stored as independent fields that could
17//! disagree with the typed data: `version` is fixed at 2 by the spec (checked
18//! on parse, always written on serialize), and `P`/`X`/`CC` are derived from
19//! `padding.is_some()` / `extension.is_some()` / `csrc.len()` respectively —
20//! see [`RtpPacket`]'s doc for the reasoning.
21//!
22//! Depends only on `broadcast-common`. `#![no_std]` (+ `alloc`) when the
23//! `std` feature is disabled.
24//!
25//! The optional `rfc8285` feature adds [`rfc8285`], a decoder for [RFC
26//! 8285](https://www.rfc-editor.org/rfc/rfc8285.txt)'s one-byte/two-byte
27//! multiplexed extension elements that a profile may pack into
28//! [`HeaderExtension::data`] — see `rtp-packet/docs/rfc8285_header_ext.md`
29//! for the curated transcription. It is additive and off by default: most
30//! RTP consumers only need the RFC 3550 fixed header.
31//!
32//! # Examples
33//!
34//! Build a simple packet (no padding/CSRC/extension) and round-trip it:
35//!
36//! ```
37//! use broadcast_common::{Parse, Serialize};
38//! use rtp_packet::RtpPacket;
39//!
40//! let pkt = RtpPacket {
41//!     marker: true,
42//!     payload_type: 96,
43//!     sequence_number: 1,
44//!     timestamp: 3600,
45//!     ssrc: 0x1234_5678,
46//!     csrc: vec![],
47//!     extension: None,
48//!     padding: None,
49//!     payload: &[0xDE, 0xAD, 0xBE, 0xEF],
50//! };
51//! let mut bytes = vec![0u8; pkt.serialized_len()];
52//! pkt.serialize_into(&mut bytes).unwrap();
53//! assert_eq!(RtpPacket::parse(&bytes).unwrap(), pkt);
54//! ```
55#![cfg_attr(not(feature = "std"), no_std)]
56#![cfg_attr(docsrs, feature(doc_cfg))]
57#![warn(missing_docs)]
58// Runnable examples, embedded so they render on docs.rs and stay in sync with
59// the actual `examples/*.rs` files (shown, not compiled).
60#![doc = "\n## Runnable examples\n"]
61#![doc = "Run with `cargo run -p rtp-packet --example <name>`.\n"]
62#![doc = "\n### `build_packet`\n\n```rust,ignore"]
63#![doc = include_str!("../examples/build_packet.rs")]
64#![doc = "```\n\n### `parse_packet`\n\n```rust,ignore"]
65#![doc = include_str!("../examples/parse_packet.rs")]
66#![doc = "```\n\n### `rfc8285_extensions` (requires `--features rfc8285`)\n\n```rust,ignore"]
67#![doc = include_str!("../examples/rfc8285_extensions.rs")]
68#![doc = "```"]
69
70extern crate alloc;
71
72mod error;
73mod header;
74#[cfg(feature = "rfc8285")]
75pub mod rfc8285;
76
77pub use error::{Error, Result};
78pub use header::{
79    FIXED_HEADER_LEN, HeaderExtension, MAX_CSRC_COUNT, MAX_PADDING_COUNT, MAX_PAYLOAD_TYPE,
80    RTP_VERSION, RtpPacket,
81};