cea608overlay: Handle errors when rendering captions more gracefully

Just don't output anything and log an error instead of panicking.
This commit is contained in:
Sebastian Dröge 2021-01-31 11:18:37 +02:00
parent 78c0ea6a4c
commit 1a826caf75

View file

@ -138,7 +138,7 @@ impl Cea608Overlay {
Ok(gst::FlowSuccess::Ok) Ok(gst::FlowSuccess::Ok)
} }
fn overlay_text(&self, text: &str, state: &mut State) { fn overlay_text(&self, element: &super::Cea608Overlay, text: &str, state: &mut State) {
let video_info = state.video_info.as_ref().unwrap(); let video_info = state.video_info.as_ref().unwrap();
let layout = state.layout.as_ref().unwrap(); let layout = state.layout.as_ref().unwrap();
layout.set_text(text); layout.set_text(text);
@ -152,7 +152,8 @@ impl Cea608Overlay {
return; return;
} }
let mut buffer = gst::Buffer::with_size((width * height) as usize * 4).unwrap(); let render_buffer = || -> Option<gst::Buffer> {
let mut buffer = gst::Buffer::with_size((width * height) as usize * 4).ok()?;
gst_video::VideoMeta::add( gst_video::VideoMeta::add(
buffer.get_mut().unwrap(), buffer.get_mut().unwrap(),
@ -164,18 +165,21 @@ impl Cea608Overlay {
width as u32, width as u32,
height as u32, height as u32,
) )
.unwrap(); .ok()?;
let buffer = buffer.into_mapped_buffer_writable().unwrap(); let buffer = buffer.into_mapped_buffer_writable().unwrap();
let buffer = {
// Pass ownership of the buffer to the cairo surface but keep around
// a raw pointer so we can later retrieve it again when the surface
// is done
let buffer_ptr = unsafe { buffer.get_buffer().as_ptr() }; let buffer_ptr = unsafe { buffer.get_buffer().as_ptr() };
let surface = cairo::ImageSurface::create_for_data( let surface = cairo::ImageSurface::create_for_data(
buffer, buffer,
cairo::Format::ARgb32, cairo::Format::ARgb32,
width as i32, width,
height, height,
width as i32 * 4, width * 4,
) )
.unwrap(); .ok()?;
let cr = cairo::Context::new(&surface); let cr = cairo::Context::new(&surface);
@ -185,22 +189,22 @@ impl Cea608Overlay {
cr.paint(); cr.paint();
// Render text outline // Render text outline
cr.save(); cr.save().ok()?;
cr.set_operator(cairo::Operator::Over); cr.set_operator(cairo::Operator::Over);
cr.set_source_rgba(0.0, 0.0, 0.0, 1.0); cr.set_source_rgba(0.0, 0.0, 0.0, 1.0);
pangocairo::functions::layout_path(&cr, &layout); pangocairo::functions::layout_path(&cr, &layout);
cr.stroke(); cr.stroke();
cr.restore(); cr.restore().ok()?;
// Render text // Render text
cr.save(); cr.save().ok()?;
cr.set_source_rgba(255.0, 255.0, 255.0, 1.0); cr.set_source_rgba(255.0, 255.0, 255.0, 1.0);
pangocairo::functions::show_layout(&cr, &layout); pangocairo::functions::show_layout(&cr, &layout);
cr.restore(); cr.restore().ok()?;
drop(cr); drop(cr);
// Safety: The surface still owns a mutable reference to the buffer but our reference // Safety: The surface still owns a mutable reference to the buffer but our reference
@ -219,6 +223,15 @@ impl Cea608Overlay {
} }
}; };
let buffer = match render_buffer() {
Some(buffer) => buffer,
None => {
gst_error!(CAT, obj: element, "Failed to render buffer");
state.composition = None;
return;
}
};
let rect = gst_video::VideoOverlayRectangle::new_raw( let rect = gst_video::VideoOverlayRectangle::new_raw(
&buffer, &buffer,
state.left_alignment, state.left_alignment,
@ -320,7 +333,7 @@ impl Cea608Overlay {
} }
}; };
self.overlay_text(&text, &mut state); self.overlay_text(element, &text, &mut state);
} }
_ => (), _ => (),
} }