mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-12-27 12:30:28 +00:00
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>
This commit is contained in:
parent
ded4261971
commit
5739a3d86f
2 changed files with 71 additions and 86 deletions
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
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 take_service(&mut self) -> Option<Service> {
|
||||
self.service.take()
|
||||
}
|
||||
|
||||
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)])
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue