mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-12-20 00:56:30 +00:00
cea708overlay: support changing the safe title area
By default it is 80% of the output size as recommended by CEA-708/608. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1985>
This commit is contained in:
parent
b367b38633
commit
497b1e58bd
5 changed files with 220 additions and 47 deletions
|
@ -7984,6 +7984,34 @@
|
||||||
"type": "gint",
|
"type": "gint",
|
||||||
"writable": true
|
"writable": true
|
||||||
},
|
},
|
||||||
|
"safe-title-height": {
|
||||||
|
"blurb": "Ratio of the video height to use as the safe area for caption display",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "0.8",
|
||||||
|
"max": "1",
|
||||||
|
"min": "0",
|
||||||
|
"mutable": "playing",
|
||||||
|
"readable": true,
|
||||||
|
"type": "gfloat",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
|
"safe-title-width": {
|
||||||
|
"blurb": "Ratio of the video width to use as the safe area for caption display",
|
||||||
|
"conditionally-available": false,
|
||||||
|
"construct": false,
|
||||||
|
"construct-only": false,
|
||||||
|
"controllable": false,
|
||||||
|
"default": "0.8",
|
||||||
|
"max": "1",
|
||||||
|
"min": "0",
|
||||||
|
"mutable": "playing",
|
||||||
|
"readable": true,
|
||||||
|
"type": "gfloat",
|
||||||
|
"writable": true
|
||||||
|
},
|
||||||
"service": {
|
"service": {
|
||||||
"blurb": "The service to render the caption for when available, (-1=automatic, 0=disabled)",
|
"blurb": "The service to render the caption for when available, (-1=automatic, 0=disabled)",
|
||||||
"conditionally-available": false,
|
"conditionally-available": false,
|
||||||
|
|
|
@ -157,8 +157,6 @@ pub(crate) fn recalculate_pango_layout(
|
||||||
video_height: u32,
|
video_height: u32,
|
||||||
) -> (i32, i32) {
|
) -> (i32, i32) {
|
||||||
let mut font_desc = pango::FontDescription::from_string("monospace");
|
let mut font_desc = pango::FontDescription::from_string("monospace");
|
||||||
let video_width = video_width * 80 / 100;
|
|
||||||
let video_height = video_height * 80 / 100;
|
|
||||||
|
|
||||||
let mut font_size = 1;
|
let mut font_size = 1;
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -494,6 +494,11 @@ pub struct Cea608Renderer {
|
||||||
video_height: u32,
|
video_height: u32,
|
||||||
left_alignment: i32,
|
left_alignment: i32,
|
||||||
black_background: bool,
|
black_background: bool,
|
||||||
|
|
||||||
|
safe_width: f32,
|
||||||
|
safe_height: f32,
|
||||||
|
max_layout_width: i32,
|
||||||
|
max_layout_height: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cea608Renderer {
|
impl Cea608Renderer {
|
||||||
|
@ -506,7 +511,8 @@ impl Cea608Renderer {
|
||||||
context.set_base_dir(pango::Direction::Ltr);
|
context.set_base_dir(pango::Direction::Ltr);
|
||||||
let layout = pango::Layout::new(&context);
|
let layout = pango::Layout::new(&context);
|
||||||
layout.set_alignment(pango::Alignment::Left);
|
layout.set_alignment(pango::Alignment::Left);
|
||||||
recalculate_pango_layout(&layout, video_width, video_height);
|
let (max_layout_width, max_layout_height) =
|
||||||
|
recalculate_pango_layout(&layout, video_width, video_height);
|
||||||
Self {
|
Self {
|
||||||
frame: Cea608Frame::new(),
|
frame: Cea608Frame::new(),
|
||||||
state: Cea608State::default(),
|
state: Cea608State::default(),
|
||||||
|
@ -517,6 +523,10 @@ impl Cea608Renderer {
|
||||||
video_height,
|
video_height,
|
||||||
left_alignment: 0,
|
left_alignment: 0,
|
||||||
black_background: false,
|
black_background: false,
|
||||||
|
safe_width: 0.8,
|
||||||
|
safe_height: 0.8,
|
||||||
|
max_layout_width,
|
||||||
|
max_layout_height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,15 +556,31 @@ impl Cea608Renderer {
|
||||||
if width != self.video_width || height != self.video_height {
|
if width != self.video_width || height != self.video_height {
|
||||||
self.video_width = width;
|
self.video_width = width;
|
||||||
self.video_height = height;
|
self.video_height = height;
|
||||||
self.layout = pango::Layout::new(&self.context);
|
self.recalculate_window_position();
|
||||||
self.layout.set_alignment(pango::Alignment::Left);
|
|
||||||
let (max_layout_width, _max_layout_height) =
|
|
||||||
recalculate_pango_layout(&self.layout, width, height);
|
|
||||||
self.left_alignment = (width as i32 - max_layout_width) / 2;
|
|
||||||
self.rectangle.take();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_safe_title_area(&mut self, safe_width: f32, safe_height: f32) {
|
||||||
|
if safe_width != self.safe_width || safe_height != self.safe_height {
|
||||||
|
self.safe_width = safe_width;
|
||||||
|
self.safe_height = safe_height;
|
||||||
|
self.recalculate_window_position();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recalculate_window_position(&mut self) {
|
||||||
|
self.layout = pango::Layout::new(&self.context);
|
||||||
|
self.layout.set_alignment(pango::Alignment::Left);
|
||||||
|
let width = (self.video_width as f32 * self.safe_width) as u32;
|
||||||
|
let height = (self.video_height as f32 * self.safe_height) as u32;
|
||||||
|
let (max_layout_width, max_layout_height) =
|
||||||
|
recalculate_pango_layout(&self.layout, width, height);
|
||||||
|
self.left_alignment = (self.video_width as i32 - max_layout_width) / 2;
|
||||||
|
self.max_layout_width = max_layout_width;
|
||||||
|
self.max_layout_height = max_layout_height;
|
||||||
|
self.rectangle.take();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_black_background(&mut self, bg: bool) {
|
pub fn set_black_background(&mut self, bg: bool) {
|
||||||
self.black_background = bg;
|
self.black_background = bg;
|
||||||
self.rectangle.take();
|
self.rectangle.take();
|
||||||
|
@ -670,7 +696,6 @@ impl Cea608Renderer {
|
||||||
let (_ink_rect, logical_rect) = self.layout.extents();
|
let (_ink_rect, logical_rect) = self.layout.extents();
|
||||||
let height = logical_rect.height() / pango::SCALE;
|
let height = logical_rect.height() / pango::SCALE;
|
||||||
let width = logical_rect.width() / pango::SCALE;
|
let width = logical_rect.width() / pango::SCALE;
|
||||||
gst::debug!(CAT, "overlaying size {width}x{height}, text {text}");
|
|
||||||
|
|
||||||
// No text actually needs rendering
|
// No text actually needs rendering
|
||||||
if width == 0 || height == 0 {
|
if width == 0 || height == 0 {
|
||||||
|
@ -756,16 +781,24 @@ impl Cea608Renderer {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let vertical_padding = self.video_height / 10;
|
let safe_height = (self.video_height as f32 * self.safe_height) as i32;
|
||||||
let safe_height = self.video_height.mul_div_floor(80, 100).unwrap();
|
let vertical_padding =
|
||||||
let first_row_position = (safe_height as i32)
|
(2 * self.video_height as i32 - safe_height - self.max_layout_height) / 2;
|
||||||
|
let first_row_position = self
|
||||||
|
.max_layout_height
|
||||||
.mul_div_round(first_row as i32, MAX_ROW as i32 + 1)
|
.mul_div_round(first_row as i32, MAX_ROW as i32 + 1)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
gst::debug!(
|
||||||
|
CAT,
|
||||||
|
"overlay size {width}x{height} at {}x{}, text {text}",
|
||||||
|
self.left_alignment,
|
||||||
|
first_row_position + vertical_padding
|
||||||
|
);
|
||||||
let rect = gst_video::VideoOverlayRectangle::new_raw(
|
let rect = gst_video::VideoOverlayRectangle::new_raw(
|
||||||
&buffer,
|
&buffer,
|
||||||
self.left_alignment,
|
self.left_alignment,
|
||||||
first_row_position + vertical_padding as i32,
|
first_row_position + vertical_padding,
|
||||||
width as u32,
|
width as u32,
|
||||||
height as u32,
|
height as u32,
|
||||||
gst_video::VideoOverlayFormatFlags::PREMULTIPLIED_ALPHA,
|
gst_video::VideoOverlayFormatFlags::PREMULTIPLIED_ALPHA,
|
||||||
|
|
|
@ -28,6 +28,8 @@ static CAT: LazyLock<gst::DebugCategory> = LazyLock::new(|| {
|
||||||
|
|
||||||
const DEFAULT_CEA608_CHANNEL: i32 = -1;
|
const DEFAULT_CEA608_CHANNEL: i32 = -1;
|
||||||
const DEFAULT_SERVICE: i32 = 1;
|
const DEFAULT_SERVICE: i32 = 1;
|
||||||
|
const DEFAULT_SAFE_WIDTH: f32 = 0.8;
|
||||||
|
const DEFAULT_SAFE_HEIGHT: f32 = 0.8;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct Settings {
|
struct Settings {
|
||||||
|
@ -35,6 +37,8 @@ struct Settings {
|
||||||
cea608_channel: i32,
|
cea608_channel: i32,
|
||||||
service: i32,
|
service: i32,
|
||||||
timeout: Option<gst::ClockTime>,
|
timeout: Option<gst::ClockTime>,
|
||||||
|
safe_width: f32,
|
||||||
|
safe_height: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Settings {
|
impl Default for Settings {
|
||||||
|
@ -44,6 +48,8 @@ impl Default for Settings {
|
||||||
cea608_channel: DEFAULT_CEA608_CHANNEL,
|
cea608_channel: DEFAULT_CEA608_CHANNEL,
|
||||||
service: DEFAULT_SERVICE,
|
service: DEFAULT_SERVICE,
|
||||||
timeout: gst::ClockTime::NONE,
|
timeout: gst::ClockTime::NONE,
|
||||||
|
safe_width: DEFAULT_SAFE_WIDTH,
|
||||||
|
safe_height: DEFAULT_SAFE_HEIGHT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,6 +137,9 @@ impl Cea708Overlay {
|
||||||
);
|
);
|
||||||
|
|
||||||
state.cea708_renderer.set_service_channel(state.selected);
|
state.cea708_renderer.set_service_channel(state.selected);
|
||||||
|
state
|
||||||
|
.cea708_renderer
|
||||||
|
.set_safe_title_area(settings.safe_width, settings.safe_height);
|
||||||
settings.changed = false;
|
settings.changed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,9 +446,12 @@ impl Cea708Overlay {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
EventView::FlushStop(..) => {
|
EventView::FlushStop(..) => {
|
||||||
|
let settings = self.settings.lock().unwrap().clone();
|
||||||
let mut state = self.state.lock().unwrap();
|
let mut state = self.state.lock().unwrap();
|
||||||
state.cea708_renderer = Cea708Renderer::new();
|
state.cea708_renderer = Cea708Renderer::new();
|
||||||
//state.cea608_renderer.set_black_background(settings.black_background);
|
state
|
||||||
|
.cea708_renderer
|
||||||
|
.set_safe_title_area(settings.safe_width, settings.safe_height);
|
||||||
drop(state);
|
drop(state);
|
||||||
|
|
||||||
gst::Pad::event_default(pad, Some(&*self.obj()), event)
|
gst::Pad::event_default(pad, Some(&*self.obj()), event)
|
||||||
|
@ -518,6 +530,22 @@ impl ObjectImpl for Cea708Overlay {
|
||||||
.default_value(u64::MAX)
|
.default_value(u64::MAX)
|
||||||
.mutable_playing()
|
.mutable_playing()
|
||||||
.build(),
|
.build(),
|
||||||
|
glib::ParamSpecFloat::builder("safe-title-height")
|
||||||
|
.nick("Safe Title Height")
|
||||||
|
.blurb("Ratio of the video height to use as the safe area for caption display")
|
||||||
|
.minimum(0.0)
|
||||||
|
.maximum(1.0)
|
||||||
|
.default_value(0.8)
|
||||||
|
.mutable_playing()
|
||||||
|
.build(),
|
||||||
|
glib::ParamSpecFloat::builder("safe-title-width")
|
||||||
|
.nick("Safe Title Width")
|
||||||
|
.blurb("Ratio of the video width to use as the safe area for caption display")
|
||||||
|
.minimum(0.0)
|
||||||
|
.maximum(1.0)
|
||||||
|
.default_value(0.8)
|
||||||
|
.mutable_playing()
|
||||||
|
.build(),
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -554,28 +582,42 @@ impl ObjectImpl for Cea708Overlay {
|
||||||
_ => Some(timeout.nseconds()),
|
_ => Some(timeout.nseconds()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
"safe-title-width" => {
|
||||||
|
let mut settings = self.settings.lock().unwrap();
|
||||||
|
|
||||||
|
let new = value.get().expect("type checked upstream");
|
||||||
|
if new != settings.safe_width {
|
||||||
|
settings.safe_width = new;
|
||||||
|
settings.changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"safe-title-height" => {
|
||||||
|
let mut settings = self.settings.lock().unwrap();
|
||||||
|
|
||||||
|
let new = value.get().expect("type checked upstream");
|
||||||
|
if new != settings.safe_height {
|
||||||
|
settings.safe_height = new;
|
||||||
|
settings.changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
|
fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
|
||||||
|
let settings = self.settings.lock().unwrap();
|
||||||
match pspec.name() {
|
match pspec.name() {
|
||||||
"cea608-channel" => {
|
"cea608-channel" => settings.cea608_channel.to_value(),
|
||||||
let settings = self.settings.lock().unwrap();
|
"service" => settings.service.to_value(),
|
||||||
settings.cea608_channel.to_value()
|
|
||||||
}
|
|
||||||
"service" => {
|
|
||||||
let settings = self.settings.lock().unwrap();
|
|
||||||
settings.service.to_value()
|
|
||||||
}
|
|
||||||
"timeout" => {
|
"timeout" => {
|
||||||
let settings = self.settings.lock().unwrap();
|
|
||||||
if let Some(timeout) = settings.timeout {
|
if let Some(timeout) = settings.timeout {
|
||||||
timeout.nseconds().to_value()
|
timeout.nseconds().to_value()
|
||||||
} else {
|
} else {
|
||||||
u64::MAX.to_value()
|
u64::MAX.to_value()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"safe-title-width" => settings.safe_width.to_value(),
|
||||||
|
"safe-title-height" => settings.safe_height.to_value(),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -309,6 +309,9 @@ pub struct Cea708Renderer {
|
||||||
video_width: u32,
|
video_width: u32,
|
||||||
video_height: u32,
|
video_height: u32,
|
||||||
composition: Option<gst_video::VideoOverlayComposition>,
|
composition: Option<gst_video::VideoOverlayComposition>,
|
||||||
|
|
||||||
|
safe_width: f32,
|
||||||
|
safe_height: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cea708Renderer {
|
impl Cea708Renderer {
|
||||||
|
@ -322,6 +325,8 @@ impl Cea708Renderer {
|
||||||
video_width: 0,
|
video_width: 0,
|
||||||
video_height: 0,
|
video_height: 0,
|
||||||
composition: None,
|
composition: None,
|
||||||
|
safe_width: 0.8,
|
||||||
|
safe_height: 0.8,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,6 +342,18 @@ impl Cea708Renderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_safe_title_area(&mut self, safe_width: f32, safe_height: f32) {
|
||||||
|
if safe_width != self.safe_width || safe_height != self.safe_height {
|
||||||
|
self.safe_width = safe_width;
|
||||||
|
self.safe_height = safe_height;
|
||||||
|
self.cea608.set_safe_title_area(safe_width, safe_height);
|
||||||
|
if let Some(service) = self.service.as_mut() {
|
||||||
|
service.set_safe_title_area(safe_width, safe_height);
|
||||||
|
}
|
||||||
|
self.composition.take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_service_channel(&mut self, service_channel: Option<ServiceOrChannel>) {
|
pub fn set_service_channel(&mut self, service_channel: Option<ServiceOrChannel>) {
|
||||||
if self.selected != service_channel {
|
if self.selected != service_channel {
|
||||||
self.selected = service_channel;
|
self.selected = service_channel;
|
||||||
|
@ -353,6 +370,7 @@ impl Cea708Renderer {
|
||||||
let overlay_service = self.service.get_or_insert_with(|| {
|
let overlay_service = self.service.get_or_insert_with(|| {
|
||||||
let mut service = ServiceState::new();
|
let mut service = ServiceState::new();
|
||||||
service.set_video_size(self.video_width, self.video_height);
|
service.set_video_size(self.video_width, self.video_height);
|
||||||
|
service.set_safe_title_area(self.safe_width, self.safe_height);
|
||||||
service
|
service
|
||||||
});
|
});
|
||||||
overlay_service.handle_code(code);
|
overlay_service.handle_code(code);
|
||||||
|
@ -446,6 +464,8 @@ struct ServiceState {
|
||||||
pango_context: pango::Context,
|
pango_context: pango::Context,
|
||||||
video_width: u32,
|
video_width: u32,
|
||||||
video_height: u32,
|
video_height: u32,
|
||||||
|
width_ratio: f32,
|
||||||
|
height_ratio: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceState {
|
impl ServiceState {
|
||||||
|
@ -462,6 +482,8 @@ impl ServiceState {
|
||||||
pango_context: context,
|
pango_context: context,
|
||||||
video_width: 0,
|
video_width: 0,
|
||||||
video_height: 0,
|
video_height: 0,
|
||||||
|
width_ratio: 0.8,
|
||||||
|
height_ratio: 0.8,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,23 +508,20 @@ impl ServiceState {
|
||||||
let layout = pango::Layout::new(&self.pango_context);
|
let layout = pango::Layout::new(&self.pango_context);
|
||||||
// XXX: May need a different alignment
|
// XXX: May need a different alignment
|
||||||
layout.set_alignment(pango::Alignment::Left);
|
layout.set_alignment(pango::Alignment::Left);
|
||||||
let mut window = Window {
|
self.windows.push_back(Window::new(
|
||||||
visible: args.visible,
|
args.visible,
|
||||||
attrs: args.window_attributes(),
|
*args,
|
||||||
pen_attrs: args.pen_attributes(),
|
args.window_attributes(),
|
||||||
pen_color: args.pen_color(),
|
args.pen_attributes(),
|
||||||
define: *args,
|
args.pen_color(),
|
||||||
pen_location: SetPenLocationArgs::default(),
|
|
||||||
lines: VecDeque::new(),
|
|
||||||
rectangle: None,
|
|
||||||
layout,
|
layout,
|
||||||
video_dims: Dimensions::default(),
|
Dimensions {
|
||||||
window_position: Dimensions::default(),
|
w: self.video_width,
|
||||||
window_dims: Dimensions::default(),
|
h: self.video_height,
|
||||||
max_layout_dims: Dimensions::default(),
|
},
|
||||||
};
|
self.width_ratio,
|
||||||
window.set_video_size(self.video_width, self.video_height);
|
self.height_ratio,
|
||||||
self.windows.push_back(window);
|
));
|
||||||
};
|
};
|
||||||
self.current_window = args.window_id as usize;
|
self.current_window = args.window_id as usize;
|
||||||
}
|
}
|
||||||
|
@ -667,6 +686,14 @@ impl ServiceState {
|
||||||
self.video_width = video_width;
|
self.video_width = video_width;
|
||||||
self.video_height = video_height;
|
self.video_height = video_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_safe_title_area(&mut self, width_ratio: f32, height_ratio: f32) {
|
||||||
|
for window in self.windows.iter_mut() {
|
||||||
|
window.set_safe_title_area(width_ratio, height_ratio);
|
||||||
|
}
|
||||||
|
self.width_ratio = width_ratio;
|
||||||
|
self.height_ratio = height_ratio;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn color_value_as_u16(val: ColorValue) -> u16 {
|
fn color_value_as_u16(val: ColorValue) -> u16 {
|
||||||
|
@ -753,6 +780,8 @@ struct Window {
|
||||||
pen_location: SetPenLocationArgs,
|
pen_location: SetPenLocationArgs,
|
||||||
lines: VecDeque<WindowLine>,
|
lines: VecDeque<WindowLine>,
|
||||||
|
|
||||||
|
safe_width: f32,
|
||||||
|
safe_height: f32,
|
||||||
window_position: Dimensions,
|
window_position: Dimensions,
|
||||||
video_dims: Dimensions,
|
video_dims: Dimensions,
|
||||||
window_dims: Dimensions,
|
window_dims: Dimensions,
|
||||||
|
@ -762,6 +791,39 @@ struct Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn new(
|
||||||
|
visible: bool,
|
||||||
|
define: DefineWindowArgs,
|
||||||
|
attrs: SetWindowAttributesArgs,
|
||||||
|
pen_attrs: SetPenAttributesArgs,
|
||||||
|
pen_color: SetPenColorArgs,
|
||||||
|
layout: pango::Layout,
|
||||||
|
video_dims: Dimensions,
|
||||||
|
width_ratio: f32,
|
||||||
|
height_ratio: f32,
|
||||||
|
) -> Self {
|
||||||
|
let mut ret = Self {
|
||||||
|
visible,
|
||||||
|
define,
|
||||||
|
attrs,
|
||||||
|
pen_attrs,
|
||||||
|
pen_color,
|
||||||
|
pen_location: SetPenLocationArgs::default(),
|
||||||
|
lines: VecDeque::new(),
|
||||||
|
rectangle: None,
|
||||||
|
layout,
|
||||||
|
video_dims: Dimensions::default(),
|
||||||
|
window_position: Dimensions::default(),
|
||||||
|
window_dims: Dimensions::default(),
|
||||||
|
max_layout_dims: Dimensions::default(),
|
||||||
|
safe_width: width_ratio,
|
||||||
|
safe_height: height_ratio,
|
||||||
|
};
|
||||||
|
ret.set_video_size(video_dims.w, video_dims.h);
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
fn dump(&self) {
|
fn dump(&self) {
|
||||||
for line in self.lines.iter() {
|
for line in self.lines.iter() {
|
||||||
let mut string = line.no.to_string();
|
let mut string = line.no.to_string();
|
||||||
|
@ -1050,8 +1112,12 @@ impl Window {
|
||||||
// XXX: may need a better implementation for 'skinny' (horizontal or vertical) output
|
// XXX: may need a better implementation for 'skinny' (horizontal or vertical) output
|
||||||
// sizes.
|
// sizes.
|
||||||
|
|
||||||
|
let safe_area = Dimensions {
|
||||||
|
w: (self.video_dims.w as f32 * self.safe_width) as u32,
|
||||||
|
h: (self.video_dims.h as f32 * self.safe_height) as u32,
|
||||||
|
};
|
||||||
let (max_layout_width, max_layout_height) =
|
let (max_layout_width, max_layout_height) =
|
||||||
recalculate_pango_layout(&self.layout, self.video_dims.w, self.video_dims.h);
|
recalculate_pango_layout(&self.layout, safe_area.w, safe_area.h);
|
||||||
self.max_layout_dims = Dimensions {
|
self.max_layout_dims = Dimensions {
|
||||||
w: max_layout_width as u32,
|
w: max_layout_width as u32,
|
||||||
h: max_layout_height as u32,
|
h: max_layout_height as u32,
|
||||||
|
@ -1067,12 +1133,8 @@ impl Window {
|
||||||
};
|
};
|
||||||
|
|
||||||
let padding = Dimensions {
|
let padding = Dimensions {
|
||||||
w: self.video_dims.w / 10,
|
w: (self.video_dims.w - safe_area.w) / 2,
|
||||||
h: self.video_dims.h / 10,
|
h: (self.video_dims.h - safe_area.h) / 2,
|
||||||
};
|
|
||||||
let safe_area = Dimensions {
|
|
||||||
w: self.video_dims.w - self.video_dims.w / 5,
|
|
||||||
h: self.video_dims.h - self.video_dims.h / 5,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.window_position = if self.define.relative_positioning {
|
self.window_position = if self.define.relative_positioning {
|
||||||
|
@ -1131,6 +1193,16 @@ impl Window {
|
||||||
self.recalculate_window_position();
|
self.recalculate_window_position();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_safe_title_area(&mut self, width_ratio: f32, height_ratio: f32) {
|
||||||
|
if self.safe_width == width_ratio && self.safe_height == height_ratio {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.safe_width = width_ratio;
|
||||||
|
self.safe_height = height_ratio;
|
||||||
|
|
||||||
|
self.recalculate_window_position();
|
||||||
|
}
|
||||||
|
|
||||||
fn generate_rectangle(&mut self) -> Option<gst_video::VideoOverlayRectangle> {
|
fn generate_rectangle(&mut self) -> Option<gst_video::VideoOverlayRectangle> {
|
||||||
if !self.visible {
|
if !self.visible {
|
||||||
return None;
|
return None;
|
||||||
|
|
Loading…
Reference in a new issue