mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-02-16 21:05:15 +00:00
closedcaption: update to cea708-types 0.3
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1398>
This commit is contained in:
parent
5739a3d86f
commit
d644bcd79a
4 changed files with 37 additions and 27 deletions
9
Cargo.lock
generated
9
Cargo.lock
generated
|
@ -992,13 +992,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cea708-types"
|
name = "cea708-types"
|
||||||
version = "0.1.0"
|
version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3a23ec736ab2aafb861ef6f22c662cbc18c85e73945f86bd9e936a20be7cc958"
|
checksum = "ab4d26b125a97b4fdd73c45b64ec8d1c7e0d0dd12a25acec5ca98a38c400b66b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"env_logger 0.10.1",
|
||||||
|
"log",
|
||||||
|
"muldiv",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"tracing",
|
|
||||||
"tracing-subscriber",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -21,7 +21,7 @@ pangocairo = { git = "https://github.com/gtk-rs/gtk-rs-core" }
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = { version = "1.0", features = ["raw_value"] }
|
serde_json = { version = "1.0", features = ["raw_value"] }
|
||||||
cea708-types = "0.1"
|
cea708-types = "0.3"
|
||||||
|
|
||||||
[dependencies.gst]
|
[dependencies.gst]
|
||||||
git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs"
|
git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs"
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use cea708_types::{tables::*, DTVCCPacket};
|
use cea708_types::{tables::*, DTVCCPacket};
|
||||||
|
use cea708_types::{CCDataWriter, Framerate};
|
||||||
use gst::glib;
|
use gst::glib;
|
||||||
use gst::prelude::*;
|
use gst::prelude::*;
|
||||||
use gst::subclass::prelude::*;
|
use gst::subclass::prelude::*;
|
||||||
|
@ -14,7 +15,7 @@ use gst::subclass::prelude::*;
|
||||||
use atomic_refcell::AtomicRefCell;
|
use atomic_refcell::AtomicRefCell;
|
||||||
|
|
||||||
use crate::cea608utils::*;
|
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;
|
use gst::glib::once_cell::sync::Lazy;
|
||||||
|
|
||||||
|
@ -193,17 +194,19 @@ impl Cea708ServiceState {
|
||||||
}
|
}
|
||||||
|
|
||||||
if need_pen_attributes {
|
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) {
|
fn carriage_return(&mut self) {
|
||||||
self.writer.carriage_return().unwrap();
|
self.writer.carriage_return();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Cea708State {
|
struct Cea708State {
|
||||||
packet_counter: u8,
|
packet_counter: u8,
|
||||||
|
writer: CCDataWriter,
|
||||||
|
framerate: Framerate,
|
||||||
service_state: [Cea708ServiceState; 4],
|
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);
|
assert!(s334_1a_data.len() % 3 == 0);
|
||||||
for triple in s334_1a_data.chunks(3) {
|
for triple in s334_1a_data.chunks(3) {
|
||||||
if (triple[0] & 0x80) > 0 {
|
if (triple[0] & 0x80) > 0 {
|
||||||
cc_data.push(0xfd);
|
self.writer
|
||||||
|
.push_cea608(cea708_types::Cea608::Field1(triple[1], triple[2]))
|
||||||
} else {
|
} 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);
|
let mut cc_data = Vec::with_capacity(128);
|
||||||
packet.write_cc_data(&mut ccp_data).ok()?;
|
self.writer.write(self.framerate, &mut cc_data).unwrap();
|
||||||
gst::trace!(
|
gst::trace!(
|
||||||
CAT,
|
CAT,
|
||||||
"take_buffer produced cc_data_len:{} cc_data:{cc_data:?}",
|
"take_buffer produced cc_data_len:{} cc_data:{cc_data:?}",
|
||||||
cc_data.len()
|
cc_data.len()
|
||||||
);
|
);
|
||||||
// ignore the 2 byte cc_data header that is unused in GStreamer
|
if cc_data.len() > 2 {
|
||||||
if ccp_data.len() > 2 {
|
// ignore the 2 byte cc_data header that is unused in GStreamer
|
||||||
cc_data.extend(&ccp_data[2..]);
|
let cc_data = cc_data.split_off(2);
|
||||||
} else if cc_data.is_empty() {
|
Some(gst::Buffer::from_slice(cc_data))
|
||||||
return None;
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
Some(gst::Buffer::from_slice(cc_data))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,6 +268,8 @@ impl Default for State {
|
||||||
cea608: Cea608State::default(),
|
cea608: Cea608State::default(),
|
||||||
cea708: Cea708State {
|
cea708: Cea708State {
|
||||||
packet_counter: 0,
|
packet_counter: 0,
|
||||||
|
writer: CCDataWriter::default(),
|
||||||
|
framerate: Framerate::new(30, 1),
|
||||||
service_state: [
|
service_state: [
|
||||||
Cea708ServiceState::new(1),
|
Cea708ServiceState::new(1),
|
||||||
Cea708ServiceState::new(2),
|
Cea708ServiceState::new(2),
|
||||||
|
@ -618,14 +624,16 @@ impl Cea608ToCea708 {
|
||||||
return false;
|
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);
|
drop(state);
|
||||||
|
|
||||||
let mut caps_builder =
|
let caps = gst::Caps::builder("closedcaption/x-cea-708")
|
||||||
gst::Caps::builder("closedcaption/x-cea-708").field("format", "cc_data");
|
.field("format", "cc_data")
|
||||||
if let Some(framerate) = framerate {
|
.field("framerate", framerate)
|
||||||
caps_builder = caps_builder.field("framerate", framerate);
|
.build();
|
||||||
}
|
let new_event = gst::event::Caps::new(&caps);
|
||||||
let new_event = gst::event::Caps::new(&caps_builder.build());
|
|
||||||
|
|
||||||
return self.srcpad.push_event(new_event);
|
return self.srcpad.push_event(new_event);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ struct TestState {
|
||||||
impl TestState {
|
impl TestState {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
let mut h = gst_check::Harness::new_parse("cea608tocea708");
|
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");
|
h.set_sink_caps_str("closedcaption/x-cea-708,format=cc_data");
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
@ -98,6 +98,7 @@ fn test_single_char() {
|
||||||
caps,
|
caps,
|
||||||
gst::Caps::builder("closedcaption/x-cea-708")
|
gst::Caps::builder("closedcaption/x-cea-708")
|
||||||
.field("format", "cc_data")
|
.field("format", "cc_data")
|
||||||
|
.field("framerate", gst::Fraction::new(25, 1))
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue