diff --git a/Cargo.lock b/Cargo.lock index 2b185852..13330335 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -992,13 +992,14 @@ dependencies = [ [[package]] name = "cea708-types" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a23ec736ab2aafb861ef6f22c662cbc18c85e73945f86bd9e936a20be7cc958" +checksum = "ab4d26b125a97b4fdd73c45b64ec8d1c7e0d0dd12a25acec5ca98a38c400b66b" dependencies = [ + "env_logger 0.10.1", + "log", + "muldiv", "once_cell", - "tracing", - "tracing-subscriber", ] [[package]] diff --git a/video/closedcaption/Cargo.toml b/video/closedcaption/Cargo.toml index 48bf406b..e1e84ca8 100644 --- a/video/closedcaption/Cargo.toml +++ b/video/closedcaption/Cargo.toml @@ -21,7 +21,7 @@ pangocairo = { git = "https://github.com/gtk-rs/gtk-rs-core" } byteorder = "1" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["raw_value"] } -cea708-types = "0.1" +cea708-types = "0.3" [dependencies.gst] git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" diff --git a/video/closedcaption/src/cea608tocea708/imp.rs b/video/closedcaption/src/cea608tocea708/imp.rs index d8e3478e..1d7b3aa4 100644 --- a/video/closedcaption/src/cea608tocea708/imp.rs +++ b/video/closedcaption/src/cea608tocea708/imp.rs @@ -7,6 +7,7 @@ // SPDX-License-Identifier: MPL-2.0 use cea708_types::{tables::*, DTVCCPacket}; +use cea708_types::{CCDataWriter, Framerate}; use gst::glib; use gst::prelude::*; use gst::subclass::prelude::*; @@ -14,7 +15,7 @@ use gst::subclass::prelude::*; use atomic_refcell::AtomicRefCell; use crate::cea608utils::*; -use crate::cea708utils::{Cea708ServiceWriter, textstyle_foreground_color, textstyle_to_pen_color, Cea708ServiceWriter}; +use crate::cea708utils::{textstyle_foreground_color, textstyle_to_pen_color, Cea708ServiceWriter}; use gst::glib::once_cell::sync::Lazy; @@ -193,17 +194,19 @@ impl Cea708ServiceState { } if need_pen_attributes { - self.writer.set_pen_attributes(self.pen_attributes).unwrap(); + self.writer.set_pen_attributes(self.pen_attributes); } } fn carriage_return(&mut self) { - self.writer.carriage_return().unwrap(); + self.writer.carriage_return(); } } struct Cea708State { packet_counter: u8, + writer: CCDataWriter, + framerate: Framerate, service_state: [Cea708ServiceState; 4], } @@ -225,31 +228,32 @@ impl Cea708State { } } } + self.writer.push_packet(packet); - let mut cc_data = Vec::with_capacity(64); assert!(s334_1a_data.len() % 3 == 0); for triple in s334_1a_data.chunks(3) { if (triple[0] & 0x80) > 0 { - cc_data.push(0xfd); + self.writer + .push_cea608(cea708_types::Cea608::Field1(triple[1], triple[2])) } else { - cc_data.push(0xfc); + self.writer + .push_cea608(cea708_types::Cea608::Field2(triple[1], triple[2])) } - cc_data.extend(&triple[1..]); } - let mut ccp_data = Vec::with_capacity(128); - packet.write_cc_data(&mut ccp_data).ok()?; + let mut cc_data = Vec::with_capacity(128); + self.writer.write(self.framerate, &mut cc_data).unwrap(); gst::trace!( CAT, "take_buffer produced cc_data_len:{} cc_data:{cc_data:?}", cc_data.len() ); - // ignore the 2 byte cc_data header that is unused in GStreamer - if ccp_data.len() > 2 { - cc_data.extend(&ccp_data[2..]); - } else if cc_data.is_empty() { - return None; + if cc_data.len() > 2 { + // ignore the 2 byte cc_data header that is unused in GStreamer + let cc_data = cc_data.split_off(2); + Some(gst::Buffer::from_slice(cc_data)) + } else { + None } - Some(gst::Buffer::from_slice(cc_data)) } } @@ -264,6 +268,8 @@ impl Default for State { cea608: Cea608State::default(), cea708: Cea708State { packet_counter: 0, + writer: CCDataWriter::default(), + framerate: Framerate::new(30, 1), service_state: [ Cea708ServiceState::new(1), Cea708ServiceState::new(2), @@ -618,14 +624,16 @@ impl Cea608ToCea708 { return false; } }; + let framerate = framerate.unwrap_or(gst::Fraction::new(30, 1)); + state.cea708.framerate = + Framerate::new(framerate.numer() as u32, framerate.denom() as u32); drop(state); - let mut caps_builder = - gst::Caps::builder("closedcaption/x-cea-708").field("format", "cc_data"); - if let Some(framerate) = framerate { - caps_builder = caps_builder.field("framerate", framerate); - } - let new_event = gst::event::Caps::new(&caps_builder.build()); + let caps = gst::Caps::builder("closedcaption/x-cea-708") + .field("format", "cc_data") + .field("framerate", framerate) + .build(); + let new_event = gst::event::Caps::new(&caps); return self.srcpad.push_event(new_event); } diff --git a/video/closedcaption/tests/cea608tocea708.rs b/video/closedcaption/tests/cea608tocea708.rs index 44cebecc..4a50cf3c 100644 --- a/video/closedcaption/tests/cea608tocea708.rs +++ b/video/closedcaption/tests/cea608tocea708.rs @@ -31,7 +31,7 @@ struct TestState { impl TestState { fn new() -> Self { let mut h = gst_check::Harness::new_parse("cea608tocea708"); - h.set_src_caps_str("closedcaption/x-cea-608,format=raw,field=0"); + h.set_src_caps_str("closedcaption/x-cea-608,format=raw,field=0,framerate=25/1"); h.set_sink_caps_str("closedcaption/x-cea-708,format=cc_data"); Self { @@ -98,6 +98,7 @@ fn test_single_char() { caps, gst::Caps::builder("closedcaption/x-cea-708") .field("format", "cc_data") + .field("framerate", gst::Fraction::new(25, 1)) .build() ); }