colordetect: Change to videofilter base class

And also work in passthrough mode to not require all input buffers to be
writable unnecessarily.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/2131>
This commit is contained in:
Sebastian Dröge 2025-03-18 15:36:00 +02:00 committed by GStreamer Marge Bot
parent a34475fb60
commit 24536fef73
3 changed files with 20 additions and 22 deletions

View file

@ -12799,6 +12799,7 @@
"description": "Detects the dominant color of a video", "description": "Detects the dominant color of a video",
"hierarchy": [ "hierarchy": [
"GstColorDetect", "GstColorDetect",
"GstVideoFilter",
"GstBaseTransform", "GstBaseTransform",
"GstElement", "GstElement",
"GstObject", "GstObject",

View file

@ -44,7 +44,6 @@ impl Default for Settings {
struct State { struct State {
color_format: ColorFormat, color_format: ColorFormat,
out_info: gst_video::VideoInfo,
current_color: Option<String>, current_color: Option<String>,
} }
@ -57,7 +56,7 @@ pub struct ColorDetect {
impl ColorDetect { impl ColorDetect {
fn detect_color( fn detect_color(
&self, &self,
buf: &mut gst::BufferRef, frame: &gst_video::VideoFrameRef<&gst::BufferRef>,
) -> Result<Option<(String, Vec<Color>)>, gst::FlowError> { ) -> Result<Option<(String, Vec<Color>)>, gst::FlowError> {
let mut state_guard = self.state.borrow_mut(); let mut state_guard = self.state.borrow_mut();
let state = state_guard.as_mut().ok_or_else(|| { let state = state_guard.as_mut().ok_or_else(|| {
@ -66,8 +65,6 @@ impl ColorDetect {
})?; })?;
let settings = *self.settings.lock().unwrap(); let settings = *self.settings.lock().unwrap();
let frame =
gst_video::VideoFrameRef::from_buffer_ref_readable(buf, &state.out_info).unwrap();
let palette = get_palette( let palette = get_palette(
frame.plane_data(0).unwrap(), frame.plane_data(0).unwrap(),
state.color_format, state.color_format,
@ -119,7 +116,7 @@ impl ColorDetect {
impl ObjectSubclass for ColorDetect { impl ObjectSubclass for ColorDetect {
const NAME: &'static str = "GstColorDetect"; const NAME: &'static str = "GstColorDetect";
type Type = super::ColorDetect; type Type = super::ColorDetect;
type ParentType = gst_base::BaseTransform; type ParentType = gst_video::VideoFilter;
} }
impl ObjectImpl for ColorDetect { impl ObjectImpl for ColorDetect {
@ -249,26 +246,24 @@ impl ElementImpl for ColorDetect {
impl BaseTransformImpl for ColorDetect { impl BaseTransformImpl for ColorDetect {
const MODE: gst_base::subclass::BaseTransformMode = const MODE: gst_base::subclass::BaseTransformMode =
gst_base::subclass::BaseTransformMode::AlwaysInPlace; gst_base::subclass::BaseTransformMode::AlwaysInPlace;
const PASSTHROUGH_ON_SAME_CAPS: bool = false; const PASSTHROUGH_ON_SAME_CAPS: bool = true;
const TRANSFORM_IP_ON_PASSTHROUGH: bool = false; const TRANSFORM_IP_ON_PASSTHROUGH: bool = true;
fn stop(&self) -> Result<(), gst::ErrorMessage> { fn stop(&self) -> Result<(), gst::ErrorMessage> {
*self.state.borrow_mut() = None; *self.state.borrow_mut() = None;
gst::info!(CAT, imp = self, "Stopped"); gst::info!(CAT, imp = self, "Stopped");
Ok(()) Ok(())
} }
}
fn set_caps(&self, incaps: &gst::Caps, outcaps: &gst::Caps) -> Result<(), gst::LoggableError> { impl VideoFilterImpl for ColorDetect {
let in_info = match gst_video::VideoInfo::from_caps(incaps) { fn set_info(
Err(_) => return Err(gst::loggable_error!(CAT, "Failed to parse input caps")), &self,
Ok(info) => info, incaps: &gst::Caps,
}; in_info: &gst_video::VideoInfo,
outcaps: &gst::Caps,
let out_info = match gst_video::VideoInfo::from_caps(outcaps) { _out_info: &gst_video::VideoInfo,
Err(_) => return Err(gst::loggable_error!(CAT, "Failed to parse output caps")), ) -> Result<(), gst::LoggableError> {
Ok(info) => info,
};
gst::debug!( gst::debug!(
CAT, CAT,
imp = self, imp = self,
@ -292,15 +287,17 @@ impl BaseTransformImpl for ColorDetect {
}; };
*self.state.borrow_mut() = Some(State { *self.state.borrow_mut() = Some(State {
color_format, color_format,
out_info,
current_color: previous_color, current_color: previous_color,
}); });
Ok(()) Ok(())
} }
fn transform_ip(&self, buf: &mut gst::BufferRef) -> Result<gst::FlowSuccess, gst::FlowError> { fn transform_frame_ip_passthrough(
if let Some((dominant_color_name, palette)) = self.detect_color(buf)? { &self,
frame: &gst_video::VideoFrameRef<&gst::BufferRef>,
) -> Result<gst::FlowSuccess, gst::FlowError> {
if let Some((dominant_color_name, palette)) = self.detect_color(frame)? {
self.color_changed(&dominant_color_name, palette); self.color_changed(&dominant_color_name, palette);
} }

View file

@ -13,7 +13,7 @@ use gst::prelude::*;
pub mod imp; pub mod imp;
glib::wrapper! { glib::wrapper! {
pub struct ColorDetect(ObjectSubclass<imp::ColorDetect>) @extends gst_base::BaseTransform, gst::Element, gst::Object; pub struct ColorDetect(ObjectSubclass<imp::ColorDetect>) @extends gst_video::VideoFilter, gst_base::BaseTransform, gst::Element, gst::Object;
} }
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {