arcly-stream 0.1.7

An open-extensible live-media streaming kernel: lock-free zero-copy frame fan-out, instant-start GOP cache, a pluggable multi-protocol ingestion layer (RTMP, RTSP, SRT, WHIP/WHEP shipped), and a feature-gated pure-Rust media plane (MPEG-TS/HLS/fMP4) — runtime, config, and metrics free.
Documentation
//! VP9 bitstream helpers: uncompressed frame-header resolution extraction and
//! keyframe detection.
//!
//! VP9 carries no parameter sets — metadata lives in each frame's uncompressed
//! header, and a keyframe is fully self-describing. The leading frame's header
//! sits at offset 0 even inside a superframe (whose index is a trailer), so the
//! parsers read from the start of the access unit.
//!
//! Note: VP9 is a WebM/DASH codec; **Apple HLS does not carry VP9**. These
//! parsers exist so VP9 streams get correct GOP caching, eviction, and recording
//! via the codec-agnostic engine; HLS egress for VP9 is intentionally unsupported.

use super::bitreader::BitReader;
use super::parser::{CodecParser, VideoParams};
use crate::CodecId;

const CS_RGB: u32 = 7;
const VP9_SYNC_CODE: u32 = 0x498342;

/// Parse the uncompressed header. Returns `(params, is_keyframe)`; `params`
/// dimensions are only populated for keyframes.
fn parse_uncompressed_header(data: &[u8]) -> Option<(VideoParams, bool)> {
    let mut r = BitReader::new(data);
    if r.read_bits(2)? != 2 {
        return None; // frame_marker
    }
    let profile_low = r.read_bit()?;
    let profile_high = r.read_bit()?;
    let profile = ((profile_high << 1) | profile_low) as u8;
    if profile == 3 {
        let _reserved = r.read_bit()?;
    }
    if r.read_bit()? == 1 {
        return Some((VideoParams::default(), false)); // show_existing_frame
    }
    let frame_type = r.read_bit()?; // 0 = KEY_FRAME
    let _show_frame = r.read_bit()?;
    let _error_resilient = r.read_bit()?;
    if frame_type != 0 {
        return Some((
            VideoParams {
                profile,
                ..VideoParams::default()
            },
            false,
        ));
    }

    // Key frame: sync code, color config, then frame size.
    if r.read_bits(24)? != VP9_SYNC_CODE {
        return None;
    }
    let mut bit_depth = 8u8;
    if profile >= 2 {
        bit_depth = if r.read_bit()? == 1 { 12 } else { 10 };
    }
    let color_space = r.read_bits(3)?;
    if color_space != CS_RGB {
        let _color_range = r.read_bit()?;
        if profile == 1 || profile == 3 {
            let _subsampling_x = r.read_bit()?;
            let _subsampling_y = r.read_bit()?;
            let _reserved = r.read_bit()?;
        }
    } else if profile == 1 || profile == 3 {
        let _reserved = r.read_bit()?;
    }

    let width = r.read_bits(16)? + 1;
    let height = r.read_bits(16)? + 1;
    Some((
        VideoParams {
            width,
            height,
            profile,
            level: 0,
            tier: 0,
            bit_depth,
        },
        true,
    ))
}

/// [`CodecParser`] implementation for VP9.
pub struct Vp9;

impl CodecParser for Vp9 {
    const CODEC: CodecId = CodecId::VP9;

    fn parse_config(data: &[u8]) -> Option<VideoParams> {
        match parse_uncompressed_header(data) {
            Some((params, true)) => Some(params),
            _ => None,
        }
    }

    fn is_random_access_point(data: &[u8]) -> bool {
        matches!(parse_uncompressed_header(data), Some((_, true)))
    }

    fn carries_config(data: &[u8]) -> bool {
        // A VP9 keyframe is self-contained config.
        Self::is_random_access_point(data)
    }

    fn hls_codec_string(p: &VideoParams) -> String {
        // vp09.<profile>.<level>.<bit_depth> (level defaults to 1.0 → "10").
        let level = if p.level == 0 { 10 } else { p.level };
        format!("vp09.{:02}.{:02}.{:02}", p.profile, level, p.bit_depth)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::codec::testutil::BitWriter;

    fn keyframe_1920x1080() -> Vec<u8> {
        let mut w = BitWriter::default();
        w.bits(2, 2); // frame_marker
        w.bit(0); // profile_low_bit
        w.bit(0); // profile_high_bit → profile 0
        w.bit(0); // show_existing_frame
        w.bit(0); // frame_type = KEY_FRAME
        w.bit(1); // show_frame
        w.bit(0); // error_resilient_mode
        w.bits(VP9_SYNC_CODE, 24); // frame_sync_code
        w.bits(1, 3); // color_space = CS_BT_601
        w.bit(0); // color_range (profile 0 → no subsampling bits)
        w.bits(1919, 16); // frame_width_minus_1
        w.bits(1079, 16); // frame_height_minus_1
        w.bytes()
    }

    #[test]
    fn parse_keyframe_extracts_resolution() {
        let (p, is_key) = parse_uncompressed_header(&keyframe_1920x1080()).expect("parse");
        assert!(is_key);
        assert_eq!(
            (p.width, p.height, p.profile, p.bit_depth),
            (1920, 1080, 0, 8)
        );
    }

    #[test]
    fn classifies_keyframe_and_codec_string() {
        let kf = keyframe_1920x1080();
        assert!(Vp9::is_random_access_point(&kf));
        assert!(Vp9::carries_config(&kf));
        let p = Vp9::parse_config(&kf).expect("params");
        assert_eq!(Vp9::hls_codec_string(&p), "vp09.00.10.08");

        // Inter frame (frame_type = 1) is not a RAP.
        let mut w = BitWriter::default();
        w.bits(2, 2); // marker
        w.bit(0);
        w.bit(0); // profile 0
        w.bit(0); // show_existing_frame
        w.bit(1); // frame_type = NON_KEY
        let inter = w.bytes();
        assert!(!Vp9::is_random_access_point(&inter));
    }
}