Coverage Report

Created: 2026-01-19 07:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/av-scenechange-0.14.1/src/y4m.rs
Line
Count
Source
1
use std::io::Read;
2
3
use num_rational::Rational32;
4
use v_frame::{
5
    frame::Frame,
6
    pixel::{ChromaSampling, Pixel},
7
};
8
9
use crate::decoder::VideoDetails;
10
11
0
pub fn get_video_details<R: Read>(dec: &y4m::Decoder<R>) -> VideoDetails {
12
0
    let width = dec.get_width();
13
0
    let height = dec.get_height();
14
0
    let color_space = dec.get_colorspace();
15
0
    let bit_depth = color_space.get_bit_depth();
16
0
    let chroma_sampling = map_y4m_color_space(color_space);
17
0
    let framerate = dec.get_framerate();
18
0
    let time_base = Rational32::new(framerate.den as i32, framerate.num as i32);
19
20
0
    VideoDetails {
21
0
        width,
22
0
        height,
23
0
        bit_depth,
24
0
        chroma_sampling,
25
0
        time_base,
26
0
    }
27
0
}
28
29
0
const fn map_y4m_color_space(color_space: y4m::Colorspace) -> ChromaSampling {
30
    use y4m::Colorspace::{
31
        C420jpeg,
32
        C420mpeg2,
33
        C420p10,
34
        C420p12,
35
        C420paldv,
36
        C422p10,
37
        C422p12,
38
        C444p10,
39
        C444p12,
40
        Cmono,
41
        Cmono12,
42
        C420,
43
        C422,
44
        C444,
45
    };
46
    use ChromaSampling::{Cs400, Cs420, Cs422, Cs444};
47
0
    match color_space {
48
0
        Cmono | Cmono12 => Cs400,
49
0
        C420jpeg | C420paldv => Cs420,
50
0
        C420mpeg2 => Cs420,
51
0
        C420 | C420p10 | C420p12 => Cs420,
52
0
        C422 | C422p10 | C422p12 => Cs422,
53
0
        C444 | C444p10 | C444p12 => Cs444,
54
0
        _ => unimplemented!(),
55
    }
56
0
}
57
58
0
pub fn read_video_frame<R: Read, T: Pixel>(
59
0
    dec: &mut y4m::Decoder<R>,
60
0
    cfg: &VideoDetails,
61
0
) -> anyhow::Result<Frame<T>> {
62
    const SB_SIZE_LOG2: usize = 6;
63
    const SB_SIZE: usize = 1 << SB_SIZE_LOG2;
64
    const SUBPEL_FILTER_SIZE: usize = 8;
65
    const FRAME_MARGIN: usize = 16 + SUBPEL_FILTER_SIZE;
66
    const LUMA_PADDING: usize = SB_SIZE + FRAME_MARGIN;
67
68
0
    let bytes = dec.get_bytes_per_sample();
69
0
    dec.read_frame()
70
0
        .map(|frame| {
71
0
            let mut f: Frame<T> =
72
0
                Frame::new_with_padding(cfg.width, cfg.height, cfg.chroma_sampling, LUMA_PADDING);
73
74
0
            let (chroma_width, _) = cfg
75
0
                .chroma_sampling
76
0
                .get_chroma_dimensions(cfg.width, cfg.height);
77
78
0
            f.planes[0].copy_from_raw_u8(frame.get_y_plane(), cfg.width * bytes, bytes);
79
0
            f.planes[1].copy_from_raw_u8(frame.get_u_plane(), chroma_width * bytes, bytes);
80
0
            f.planes[2].copy_from_raw_u8(frame.get_v_plane(), chroma_width * bytes, bytes);
81
0
            f
82
0
        })
83
0
        .map_err(|e| e.into())
84
0
}