arcly-stream 0.1.0

A high-performance live-media streaming kernel: lock-free zero-copy frame fan-out, instant-start GOP cache, pluggable HLS/recording, and trait-driven protocol/storage/auth/observer extension points — runtime, config, and metrics free.
Documentation
//! Codec bitstream helpers — turning wire bytes into engine metadata and
//! [`MediaFrame`](crate::MediaFrame) classification.
//!
//! Gated behind the per-codec features (`codec-h264`, `codec-h265`, `codec-av1`,
//! `codec-vp9`, `codec-vvc`, `codec-aac`; `codec` = H.264 + AAC; `codecs-all` =
//! everything). Every parser is pure Rust with **no native dependencies**.
//!
//! All codecs share the [`CodecParser`] contract: extract [`VideoParams`] from a
//! config header, and classify random-access points so the kernel's GOP cache,
//! segmenter, eviction, and recorder — which key only on
//! [`MediaFrame::is_keyframe`](crate::MediaFrame::is_keyframe) — work unchanged.
//!
//! ```
//! # #[cfg(feature = "codec-h265")] {
//! use arcly_stream::codec::dispatch;
//! use arcly_stream::CodecId;
//!
//! let access_unit: &[u8] = &[/* … Annex-B HEVC bytes … */];
//! // Codec-erased dispatch by CodecId (used at the ingest boundary):
//! let is_rap = dispatch::is_random_access_point(CodecId::H265, access_unit);
//! # let _ = is_rap;
//! # }
//! ```

mod bitreader;
pub mod parser;

#[cfg(test)]
mod testutil;

pub use parser::{CodecConfig, CodecParser, VideoParams};

#[cfg(feature = "_nal")]
pub mod nal;

#[cfg(feature = "codec-h264")]
#[cfg_attr(docsrs, doc(cfg(feature = "codec-h264")))]
pub mod h264;

#[cfg(feature = "codec-h265")]
#[cfg_attr(docsrs, doc(cfg(feature = "codec-h265")))]
pub mod h265;

#[cfg(feature = "codec-vvc")]
#[cfg_attr(docsrs, doc(cfg(feature = "codec-vvc")))]
pub mod vvc;

#[cfg(feature = "codec-av1")]
#[cfg_attr(docsrs, doc(cfg(feature = "codec-av1")))]
pub mod av1;

#[cfg(feature = "codec-av1")]
mod obu;

#[cfg(feature = "codec-vp9")]
#[cfg_attr(docsrs, doc(cfg(feature = "codec-vp9")))]
pub mod vp9;

#[cfg(feature = "codec-aac")]
#[cfg_attr(docsrs, doc(cfg(feature = "codec-aac")))]
pub mod aac;

// ── Back-compat flat re-exports (pre-split public surface) ──────────────────
#[cfg(feature = "codec-aac")]
pub use aac::{parse_adts, AdtsHeader};
#[cfg(feature = "codec-h264")]
pub use h264::{annexb_to_avcc, avcc_to_annexb, iter_nals_annexb, parse_sps, SpsInfo};

/// Codec-erased dispatch over [`CodecId`](crate::CodecId).
///
/// Protocol handlers call these to classify an access unit without naming a
/// concrete parser. Each returns a conservative default (`false` / `None`) for a
/// codec whose feature is not enabled.
pub mod dispatch {
    use super::*;
    use crate::CodecId;

    /// Extract [`VideoParams`] from a config access unit for `codec`.
    #[allow(unused_variables)]
    pub fn parse_config(codec: CodecId, data: &[u8]) -> Option<VideoParams> {
        match codec {
            #[cfg(feature = "codec-h264")]
            CodecId::H264 => <h264::H264 as CodecParser>::parse_config(data),
            #[cfg(feature = "codec-h265")]
            CodecId::H265 => <h265::H265 as CodecParser>::parse_config(data),
            #[cfg(feature = "codec-vvc")]
            CodecId::VVC => <vvc::Vvc as CodecParser>::parse_config(data),
            #[cfg(feature = "codec-av1")]
            CodecId::AV1 => <av1::Av1 as CodecParser>::parse_config(data),
            #[cfg(feature = "codec-vp9")]
            CodecId::VP9 => <vp9::Vp9 as CodecParser>::parse_config(data),
            _ => None,
        }
    }

    /// Whether `data` is a random-access point under `codec`.
    #[allow(unused_variables)]
    pub fn is_random_access_point(codec: CodecId, data: &[u8]) -> bool {
        match codec {
            #[cfg(feature = "codec-h264")]
            CodecId::H264 => <h264::H264 as CodecParser>::is_random_access_point(data),
            #[cfg(feature = "codec-h265")]
            CodecId::H265 => <h265::H265 as CodecParser>::is_random_access_point(data),
            #[cfg(feature = "codec-vvc")]
            CodecId::VVC => <vvc::Vvc as CodecParser>::is_random_access_point(data),
            #[cfg(feature = "codec-av1")]
            CodecId::AV1 => <av1::Av1 as CodecParser>::is_random_access_point(data),
            #[cfg(feature = "codec-vp9")]
            CodecId::VP9 => <vp9::Vp9 as CodecParser>::is_random_access_point(data),
            _ => false,
        }
    }

    /// The HLS `CODECS` attribute for `codec` given parsed `params`.
    #[allow(unused_variables)]
    pub fn hls_codec_string(codec: CodecId, params: &VideoParams) -> Option<String> {
        match codec {
            #[cfg(feature = "codec-h264")]
            CodecId::H264 => Some(<h264::H264 as CodecParser>::hls_codec_string(params)),
            #[cfg(feature = "codec-h265")]
            CodecId::H265 => Some(<h265::H265 as CodecParser>::hls_codec_string(params)),
            #[cfg(feature = "codec-vvc")]
            CodecId::VVC => Some(<vvc::Vvc as CodecParser>::hls_codec_string(params)),
            #[cfg(feature = "codec-av1")]
            CodecId::AV1 => Some(<av1::Av1 as CodecParser>::hls_codec_string(params)),
            #[cfg(feature = "codec-vp9")]
            CodecId::VP9 => Some(<vp9::Vp9 as CodecParser>::hls_codec_string(params)),
            _ => None,
        }
    }
}