Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/video
diff options
context:
space:
mode:
authorMatthew Waters <matthew@centricular.com>2023-11-06 16:25:20 +0300
committerMatthew Waters <matthew@centricular.com>2023-11-21 16:12:50 +0300
commit5739a3d86ffbda3b62be8bf57172db499f276ff8 (patch)
tree1c129d5e757137668873bdd59f2e18024da8c08b /video
parentded42619718e3ea838f53b0216d6215278b5d426 (diff)
cea608tocea708: create service's as requested
Allows the ability to push multiple Service blocks of the same service into the same packet if necessary (unlikely but possible). Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1398>
Diffstat (limited to 'video')
-rw-r--r--video/closedcaption/src/cea608tocea708/imp.rs64
-rw-r--r--video/closedcaption/src/cea708utils.rs91
2 files changed, 70 insertions, 85 deletions
diff --git a/video/closedcaption/src/cea608tocea708/imp.rs b/video/closedcaption/src/cea608tocea708/imp.rs
index 0461a635a..d8e3478ef 100644
--- a/video/closedcaption/src/cea608tocea708/imp.rs
+++ b/video/closedcaption/src/cea608tocea708/imp.rs
@@ -101,11 +101,11 @@ impl Cea708ServiceState {
0
};
match cea608_mode {
- Cea608Mode::PopOn => self.writer.popon_preamble().unwrap(),
- Cea608Mode::PaintOn => self.writer.paint_on_preamble().unwrap(),
- Cea608Mode::RollUp2 => self.writer.rollup_preamble(2, base_row).unwrap(),
- Cea608Mode::RollUp3 => self.writer.rollup_preamble(3, base_row).unwrap(),
- Cea608Mode::RollUp4 => self.writer.rollup_preamble(4, base_row).unwrap(),
+ Cea608Mode::PopOn => self.writer.popon_preamble(),
+ Cea608Mode::PaintOn => self.writer.paint_on_preamble(),
+ Cea608Mode::RollUp2 => self.writer.rollup_preamble(2, base_row),
+ Cea608Mode::RollUp3 => self.writer.rollup_preamble(3, base_row),
+ Cea608Mode::RollUp4 => self.writer.rollup_preamble(4, base_row),
};
// we have redefined then window so all the attributes have been reset
self.pen_location.row = new_row;
@@ -117,20 +117,20 @@ impl Cea708ServiceState {
fn handle_text(&mut self, text: Cea608Text) {
if text.code_space == CodeSpace::WestEU {
- self.writer.push_codes(&[Code::BS]).unwrap();
+ self.writer.push_codes(&[Code::BS]);
}
if let Some(c) = text.char1 {
if self.pen_location.column > 31 {
- self.writer.push_codes(&[Code::BS]).unwrap();
+ self.writer.push_codes(&[Code::BS]);
}
- self.writer.write_char(c).unwrap();
+ self.writer.write_char(c);
self.pen_location.column = std::cmp::min(self.pen_location.column + 1, 32);
}
if let Some(c) = text.char2 {
if self.pen_location.column > 31 {
- self.writer.push_codes(&[Code::BS]).unwrap();
+ self.writer.push_codes(&[Code::BS]);
}
- self.writer.write_char(c).unwrap();
+ self.writer.write_char(c);
self.pen_location.column = std::cmp::min(self.pen_location.column + 1, 32);
}
}
@@ -150,7 +150,7 @@ impl Cea708ServiceState {
}
if need_pen_location {
- self.writer.set_pen_location(self.pen_location).unwrap();
+ self.writer.set_pen_location(self.pen_location);
}
let mut need_pen_attributes = false;
@@ -165,20 +165,20 @@ impl Cea708ServiceState {
}
if need_pen_attributes {
- self.writer.set_pen_attributes(self.pen_attributes).unwrap();
+ self.writer.set_pen_attributes(self.pen_attributes);
}
if self.pen_color.foreground_color != textstyle_foreground_color(preamble.style) {
self.pen_color.foreground_color = textstyle_foreground_color(preamble.style);
- self.writer.set_pen_color(self.pen_color).unwrap();
+ self.writer.set_pen_color(self.pen_color);
}
}
fn handle_midrowchange(&mut self, midrowchange: MidRowChange) {
- self.writer.write_char(' ').unwrap();
+ self.writer.write_char(' ');
if self.pen_color.foreground_color != textstyle_foreground_color(midrowchange.style) {
self.pen_color.foreground_color = textstyle_foreground_color(midrowchange.style);
- self.writer.set_pen_color(self.pen_color).unwrap();
+ self.writer.set_pen_color(self.pen_color);
}
let mut need_pen_attributes = false;
@@ -214,7 +214,7 @@ impl Cea708State {
self.packet_counter &= 0x3;
for state in self.service_state.iter_mut() {
- if let Some(service) = state.writer.take_service() {
+ while let Some(service) = state.writer.take_service(packet.free_space()) {
if let Err(e) = packet.push_service(service.clone()) {
gst::warning!(
CAT,
@@ -307,14 +307,8 @@ impl State {
{
// https://www.law.cornell.edu/cfr/text/47/79.101 (f)(1)(x)
gst::trace!(CAT, "change to rollup from pop/paint-on");
- self.cea708.service_state[idx]
- .writer
- .clear_hidden_window()
- .unwrap();
- self.cea708.service_state[idx]
- .writer
- .clear_current_window()
- .unwrap();
+ self.cea708.service_state[idx].writer.clear_hidden_window();
+ self.cea708.service_state[idx].writer.clear_current_window();
self.cea608.service[idx].base_row = 15;
}
if old_mode.is_rollup() && cea608_mode.is_rollup() {
@@ -331,8 +325,7 @@ impl State {
for _ in new_count..old_count {
self.cea708.service_state[idx]
.writer
- .push_codes(&[Code::CR])
- .unwrap();
+ .push_codes(&[Code::CR]);
}
}
}
@@ -371,8 +364,8 @@ impl State {
}
Cea608::EndOfCaption(chan) => {
let state = self.service_state_from_608_field_channel(field, chan);
- state.writer.end_of_caption().unwrap();
- state.writer.etx().unwrap();
+ state.writer.end_of_caption();
+ state.writer.etx();
}
Cea608::Preamble(mut preamble) => {
let idx = self.field_channel_to_index(field, preamble.chan);
@@ -394,8 +387,7 @@ impl State {
if old_base_row != preamble.row as u8 {
state
.writer
- .rollup_preamble(rollup_count, preamble.row as u8)
- .unwrap();
+ .rollup_preamble(rollup_count, preamble.row as u8);
}
state.pen_location.row = rollup_count - 1;
preamble.row = rollup_count as i32 - 1;
@@ -411,10 +403,7 @@ impl State {
let state = self.service_state_from_608_field_channel(field, chan);
// TODO: handle removing a midrowchange
state.pen_location.column = std::cmp::max(state.pen_location.column - 1, 0);
- state
- .writer
- .push_codes(&[cea708_types::tables::Code::BS])
- .unwrap();
+ state.writer.push_codes(&[cea708_types::tables::Code::BS]);
}
Cea608::CarriageReturn(chan) => {
if let Some(mode) =
@@ -428,11 +417,11 @@ impl State {
}
Cea608::EraseDisplay(chan) => {
let state = self.service_state_from_608_field_channel(field, chan);
- state.writer.clear_current_window().unwrap();
+ state.writer.clear_current_window();
}
Cea608::EraseNonDisplay(chan) => {
let state = self.service_state_from_608_field_channel(field, chan);
- state.writer.clear_hidden_window().unwrap();
+ state.writer.clear_hidden_window();
}
Cea608::TabOffset(chan, count) => {
let state = self.service_state_from_608_field_channel(field, chan);
@@ -453,8 +442,7 @@ impl State {
// and we need to send ETX
self.cea708.service_state[idx]
.writer
- .push_codes(&[cea708_types::tables::Code::ETX])
- .unwrap();
+ .push_codes(&[cea708_types::tables::Code::ETX]);
}
}
}
diff --git a/video/closedcaption/src/cea708utils.rs b/video/closedcaption/src/cea708utils.rs
index 577d2a01b..2bc0abf38 100644
--- a/video/closedcaption/src/cea708utils.rs
+++ b/video/closedcaption/src/cea708utils.rs
@@ -88,14 +88,8 @@ pub fn textstyle_to_pen_color(style: TextStyle) -> SetPenColorArgs {
}
}
-#[derive(Debug)]
-pub enum WriteError {
- // returns the number of characters/bytes written
- WouldOverflow(usize),
-}
-
pub(crate) struct Cea708ServiceWriter {
- service: Option<Service>,
+ codes: Vec<Code>,
service_no: u8,
active_window: WindowBits,
hidden_window: WindowBits,
@@ -104,24 +98,44 @@ pub(crate) struct Cea708ServiceWriter {
impl Cea708ServiceWriter {
pub fn new(service_no: u8) -> Self {
Self {
- service: None,
+ codes: vec![],
service_no,
active_window: WindowBits::ZERO,
hidden_window: WindowBits::ONE,
}
}
- fn ensure_service(&mut self) {
- if self.service.is_none() {
- self.service = Some(Service::new(self.service_no));
+ pub fn take_service(&mut self, available_bytes: usize) -> Option<Service> {
+ if self.codes.is_empty() {
+ return None;
}
- }
- pub fn take_service(&mut self) -> Option<Service> {
- self.service.take()
+ gst::trace!(CAT, "New service block {}", self.service_no);
+ let mut service = Service::new(self.service_no);
+ let mut i = 0;
+ for code in self.codes.iter() {
+ if code.byte_len() > service.free_space() {
+ gst::trace!(CAT, "service is full");
+ break;
+ }
+ if service.len() + code.byte_len() > available_bytes {
+ gst::trace!(CAT, "packet is full");
+ break;
+ }
+ gst::trace!(CAT, "Adding code {code:?} to service");
+ match service.push_code(code) {
+ Ok(_) => i += 1,
+ Err(_) => break,
+ }
+ }
+ if i == 0 {
+ return None;
+ }
+ self.codes = self.codes.split_off(i);
+ Some(service)
}
- pub fn popon_preamble(&mut self) -> Result<usize, WriteError> {
+ pub fn popon_preamble(&mut self) {
gst::trace!(CAT, "popon_preamble");
let window = match self.hidden_window {
// switch up the newly defined window
@@ -152,26 +166,24 @@ impl Cea708ServiceWriter {
self.push_codes(&codes)
}
- pub fn clear_current_window(&mut self) -> Result<usize, WriteError> {
+ pub fn clear_current_window(&mut self) {
gst::trace!(CAT, "clear_current_window {:?}", self.active_window);
self.push_codes(&[Code::ClearWindows(self.active_window)])
}
- pub fn clear_hidden_window(&mut self) -> Result<usize, WriteError> {
+ pub fn clear_hidden_window(&mut self) {
gst::trace!(CAT, "clear_hidden_window");
self.push_codes(&[Code::ClearWindows(self.hidden_window)])
}
- pub fn end_of_caption(&mut self) -> Result<usize, WriteError> {
+ pub fn end_of_caption(&mut self) {
gst::trace!(CAT, "end_of_caption");
- let ret =
- self.push_codes(&[Code::ToggleWindows(self.active_window | self.hidden_window)])?;
+ self.push_codes(&[Code::ToggleWindows(self.active_window | self.hidden_window)]);
std::mem::swap(&mut self.active_window, &mut self.hidden_window);
gst::trace!(CAT, "active window {:?}", self.active_window);
- Ok(ret)
}
- pub fn paint_on_preamble(&mut self) -> Result<usize, WriteError> {
+ pub fn paint_on_preamble(&mut self) {
gst::trace!(CAT, "paint_on_preamble");
let window = match self.active_window {
WindowBits::ZERO => 0,
@@ -198,7 +210,7 @@ impl Cea708ServiceWriter {
])
}
- pub fn rollup_preamble(&mut self, rollup_count: u8, base_row: u8) -> Result<usize, WriteError> {
+ pub fn rollup_preamble(&mut self, rollup_count: u8, base_row: u8) {
let base_row = std::cmp::max(rollup_count, base_row);
let anchor_vertical = (base_row as u32 * 100 / 15) as u8;
gst::trace!(
@@ -229,49 +241,34 @@ impl Cea708ServiceWriter {
self.push_codes(&codes)
}
- pub fn write_char(&mut self, c: char) -> Result<usize, WriteError> {
+ pub fn write_char(&mut self, c: char) {
if let Some(code) = Code::from_char(c) {
self.push_codes(&[code])
- } else {
- Ok(0)
}
}
- pub fn push_codes(&mut self, codes: &[Code]) -> Result<usize, WriteError> {
- self.ensure_service();
- let service = self.service.as_mut().unwrap();
- let start_len = service.len();
- if service.free_space() < codes.iter().map(|c| c.byte_len()).sum::<usize>() {
- return Err(WriteError::WouldOverflow(0));
- }
- for code in codes.iter() {
- gst::trace!(
- CAT,
- "pushing for service:{} code: {code:?}",
- service.number()
- );
- service.push_code(code).unwrap();
- }
- Ok(service.len() - start_len)
+ pub fn push_codes(&mut self, codes: &[Code]) {
+ gst::log!(CAT, "pushing codes: {codes:?}");
+ self.codes.extend(codes.iter().cloned());
}
- pub fn etx(&mut self) -> Result<usize, WriteError> {
+ pub fn etx(&mut self) {
self.push_codes(&[Code::ETX])
}
- pub fn carriage_return(&mut self) -> Result<usize, WriteError> {
+ pub fn carriage_return(&mut self) {
self.push_codes(&[Code::CR])
}
- pub fn set_pen_attributes(&mut self, args: SetPenAttributesArgs) -> Result<usize, WriteError> {
+ pub fn set_pen_attributes(&mut self, args: SetPenAttributesArgs) {
self.push_codes(&[Code::SetPenAttributes(args)])
}
- pub fn set_pen_location(&mut self, args: SetPenLocationArgs) -> Result<usize, WriteError> {
+ pub fn set_pen_location(&mut self, args: SetPenLocationArgs) {
self.push_codes(&[Code::SetPenLocation(args)])
}
- pub fn set_pen_color(&mut self, args: SetPenColorArgs) -> Result<usize, WriteError> {
+ pub fn set_pen_color(&mut self, args: SetPenColorArgs) {
self.push_codes(&[Code::SetPenColor(args)])
}
}