Skip to main content

arcly_stream/codec/
parser.rs

1//! Codec-agnostic parsing contracts shared by every codec module.
2
3use crate::CodecId;
4use bytes::Bytes;
5
6/// Video metadata extracted from a parameter set / sequence header.
7///
8/// Fields are `0` when unknown — matching the convention in
9/// [`StreamMetadata`](crate::StreamMetadata).
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
11pub struct VideoParams {
12    /// Coded luma width in pixels (after any conformance cropping).
13    pub width: u32,
14    /// Coded luma height in pixels (after any conformance cropping).
15    pub height: u32,
16    /// Codec profile (`profile_idc` / `seq_profile`).
17    pub profile: u8,
18    /// Codec level (e.g. `general_level_idc`, `seq_level_idx`).
19    pub level: u8,
20    /// Tier (HEVC/VVC `general_tier_flag`; `0` elsewhere).
21    pub tier: u8,
22    /// Luma bit depth (`8`, `10`, `12`); `0` when not parsed.
23    pub bit_depth: u8,
24}
25
26/// Decoder configuration handed to a [`Muxer`](crate::packager::Muxer) so it can
27/// build an fMP4 init segment and the HLS `CODECS` attribute.
28#[derive(Debug, Clone)]
29pub struct CodecConfig {
30    /// Which codec this configuration describes.
31    pub codec: CodecId,
32    /// Parsed video parameters.
33    pub params: VideoParams,
34    /// Raw decoder-configuration record bytes (`avcC`/`hvcC`/`av1C`/`vvcC`), or
35    /// the codec's config access unit when no boxed record is available.
36    pub config_record: Bytes,
37}
38
39/// One parser per codec. Pure, allocation-light, `&[u8]`-in.
40///
41/// The engine never calls these directly — protocol handlers do, at the ingest
42/// boundary, to classify frames ([`FrameType`](crate::FrameType)) and populate
43/// metadata. The kernel's GOP cache, segmenter, eviction, and recorder all key
44/// on [`is_keyframe`](crate::MediaFrame::is_keyframe), so a correct
45/// [`is_random_access_point`] is all that's needed to make a codec "work".
46///
47/// [`is_random_access_point`]: CodecParser::is_random_access_point
48pub trait CodecParser {
49    /// The codec this parser handles.
50    const CODEC: CodecId;
51
52    /// Parse the parameter set(s) / sequence header into [`VideoParams`].
53    /// Returns `None` if no usable header is present or it cannot be decoded.
54    fn parse_config(data: &[u8]) -> Option<VideoParams>;
55
56    /// Whether this access unit is a random-access point (IDR/CRA/KEY_FRAME) —
57    /// the signal the engine anchors GOP caching and segmentation on.
58    fn is_random_access_point(data: &[u8]) -> bool;
59
60    /// Whether this access unit carries decoder configuration (parameter sets /
61    /// sequence header) that should be cached for late joiners.
62    fn carries_config(data: &[u8]) -> bool;
63
64    /// The HLS `CODECS` attribute for these parameters
65    /// (e.g. `"hvc1.1.6.L93.B0"`, `"av01.0.04M.08"`).
66    fn hls_codec_string(params: &VideoParams) -> String;
67}