1use muldiv::MulDiv;
15
16mod packet;
17mod parser;
18pub mod tables;
19mod writer;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum Cea608 {
24 Field1(u8, u8),
25 Field2(u8, u8),
26}
27
28#[derive(Debug, Copy, Clone)]
30pub struct Framerate {
31 numer: u32,
32 denom: u32,
33}
34
35impl Framerate {
36 pub const fn new(numer: u32, denom: u32) -> Self {
38 Self { numer, denom }
39 }
40
41 pub fn numer(&self) -> u32 {
43 self.numer
44 }
45
46 pub fn denom(&self) -> u32 {
48 self.denom
49 }
50
51 fn cea608_pairs_per_frame(&self) -> usize {
52 60.mul_div_round(self.denom, self.numer).unwrap() as usize
55 }
56
57 fn max_cc_count(&self) -> usize {
58 600.mul_div_round(self.denom, self.numer).unwrap() as usize
60 }
61}
62
63pub use packet::{DTVCCPacket, Service};
64pub use parser::{CCDataParser, ParserError};
65pub use writer::{CCDataWriter, WriterError};
66
67#[cfg(test)]
68mod test {
69 use super::*;
70 use crate::tests::*;
71
72 #[test]
73 fn framerate_cea608_pairs_per_frame() {
74 test_init_log();
75 assert_eq!(Framerate::new(60, 1).cea608_pairs_per_frame(), 1);
76 assert_eq!(Framerate::new(30, 1).cea608_pairs_per_frame(), 2);
77 }
78
79 #[test]
80 fn framerate_max_cc_count() {
81 test_init_log();
82 assert_eq!(Framerate::new(60, 1).max_cc_count(), 10);
83 assert_eq!(Framerate::new(30, 1).max_cc_count(), 20);
84 }
85
86 #[test]
87 fn framerate_new() {
88 test_init_log();
89 let fps = Framerate::new(30, 8);
90 assert_eq!(fps.numer(), 30);
91 assert_eq!(fps.denom(), 8);
92 }
93}
94
95#[cfg(test)]
96pub(crate) mod tests {
97 use std::sync::OnceLock;
98
99 static TRACING: OnceLock<()> = OnceLock::new();
100
101 pub fn test_init_log() {
102 TRACING.get_or_init(|| {
103 env_logger::init();
104 });
105 }
106}