dav1ddec: add properties for film grain synthesis and in-loop filters

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1763>
This commit is contained in:
Jerome Colle 2024-09-03 15:07:31 +02:00 committed by GStreamer Marge Bot
parent 24003a79f6
commit fef6601094
3 changed files with 108 additions and 1 deletions

View file

@ -1603,6 +1603,30 @@
} }
}, },
"properties": { "properties": {
"apply-grain": {
"blurb": "Enable out-of-loop normative film grain filter",
"conditionally-available": false,
"construct": false,
"construct-only": false,
"controllable": false,
"default": "false",
"mutable": "ready",
"readable": true,
"type": "gboolean",
"writable": true
},
"inloop-filters": {
"blurb": "Flags to enable in-loop post processing filters",
"conditionally-available": false,
"construct": false,
"construct-only": false,
"controllable": false,
"default": "(none)",
"mutable": "ready",
"readable": true,
"type": "GstDav1dInloopFilterType",
"writable": true
},
"max-frame-delay": { "max-frame-delay": {
"blurb": "Maximum delay in frames for the decoder (set to 1 for low latency, 0 to be equal to the number of logical cores. -1 to choose between these two based on pipeline liveness)", "blurb": "Maximum delay in frames for the decoder (set to 1 for low latency, 0 to be equal to the number of logical cores. -1 to choose between these two based on pipeline liveness)",
"conditionally-available": false, "conditionally-available": false,
@ -1637,7 +1661,28 @@
}, },
"filename": "gstdav1d", "filename": "gstdav1d",
"license": "MIT/X11", "license": "MIT/X11",
"other-types": {}, "other-types": {
"GstDav1dInloopFilterType": {
"kind": "flags",
"values": [
{
"desc": "Enable deblocking filter",
"name": "deblock",
"value": "0x00000001"
},
{
"desc": "Enable Constrained Directional Enhancement Filter",
"name": "cdef",
"value": "0x00000002"
},
{
"desc": "Enable loop restoration filter",
"name": "restoration",
"value": "0x00000004"
}
]
}
},
"package": "gst-plugin-dav1d", "package": "gst-plugin-dav1d",
"source": "gst-plugin-dav1d", "source": "gst-plugin-dav1d",
"tracers": {}, "tracers": {},

View file

@ -18,8 +18,40 @@ use once_cell::sync::Lazy;
use std::sync::{Mutex, MutexGuard}; use std::sync::{Mutex, MutexGuard};
#[glib::flags(name = "GstDav1dInloopFilterType")]
pub(crate) enum InloopFilterType {
#[flags_value(name = "Enable deblocking filter", nick = "deblock")]
DEBLOCK = dav1d::InloopFilterType::DEBLOCK.bits(),
#[flags_value(
name = "Enable Constrained Directional Enhancement Filter",
nick = "cdef"
)]
CDEF = dav1d::InloopFilterType::CDEF.bits(),
#[flags_value(name = "Enable loop restoration filter", nick = "restoration")]
RESTORATION = dav1d::InloopFilterType::RESTORATION.bits(),
}
impl From<InloopFilterType> for dav1d::InloopFilterType {
fn from(inloop_filter_type: InloopFilterType) -> Self {
let mut dav1d_inloop_filter_type = dav1d::InloopFilterType::empty();
if inloop_filter_type.contains(InloopFilterType::DEBLOCK) {
dav1d_inloop_filter_type.set(dav1d::InloopFilterType::DEBLOCK, true);
}
if inloop_filter_type.contains(InloopFilterType::CDEF) {
dav1d_inloop_filter_type.set(dav1d::InloopFilterType::CDEF, true);
}
if inloop_filter_type.contains(InloopFilterType::RESTORATION) {
dav1d_inloop_filter_type.set(dav1d::InloopFilterType::RESTORATION, true);
}
dav1d_inloop_filter_type
}
}
const DEFAULT_N_THREADS: u32 = 0; const DEFAULT_N_THREADS: u32 = 0;
const DEFAULT_MAX_FRAME_DELAY: i64 = -1; const DEFAULT_MAX_FRAME_DELAY: i64 = -1;
const DEFAULT_APPLY_GRAIN: bool = false;
const DEFAULT_INLOOP_FILTERS: InloopFilterType = InloopFilterType::empty();
struct State { struct State {
decoder: dav1d::Decoder, decoder: dav1d::Decoder,
@ -33,6 +65,8 @@ struct State {
struct Settings { struct Settings {
n_threads: u32, n_threads: u32,
max_frame_delay: i64, max_frame_delay: i64,
apply_grain: bool,
inloop_filters: InloopFilterType,
} }
impl Default for Settings { impl Default for Settings {
@ -40,6 +74,8 @@ impl Default for Settings {
Settings { Settings {
n_threads: DEFAULT_N_THREADS, n_threads: DEFAULT_N_THREADS,
max_frame_delay: DEFAULT_MAX_FRAME_DELAY, max_frame_delay: DEFAULT_MAX_FRAME_DELAY,
apply_grain: DEFAULT_APPLY_GRAIN,
inloop_filters: DEFAULT_INLOOP_FILTERS,
} }
} }
} }
@ -656,6 +692,19 @@ impl ObjectImpl for Dav1dDec {
.default_value(DEFAULT_MAX_FRAME_DELAY) .default_value(DEFAULT_MAX_FRAME_DELAY)
.mutable_ready() .mutable_ready()
.build(), .build(),
glib::ParamSpecBoolean::builder("apply-grain")
.nick("Enable film grain synthesis")
.blurb("Enable out-of-loop normative film grain filter")
.default_value(DEFAULT_APPLY_GRAIN)
.mutable_ready()
.build(),
glib::ParamSpecFlags::builder("inloop-filters")
.nick("Inloop filters")
.blurb("Flags to enable in-loop post processing filters")
.default_value(DEFAULT_INLOOP_FILTERS)
.mutable_ready()
.build()
] ]
}); });
@ -672,6 +721,12 @@ impl ObjectImpl for Dav1dDec {
"max-frame-delay" => { "max-frame-delay" => {
settings.max_frame_delay = value.get().expect("type checked upstream"); settings.max_frame_delay = value.get().expect("type checked upstream");
} }
"apply-grain" => {
settings.apply_grain = value.get().expect("type checked upstream");
}
"inloop-filters" => {
settings.inloop_filters = value.get().expect("type checked upstream");
}
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
@ -682,6 +737,8 @@ impl ObjectImpl for Dav1dDec {
match pspec.name() { match pspec.name() {
"n-threads" => settings.n_threads.to_value(), "n-threads" => settings.n_threads.to_value(),
"max-frame-delay" => settings.max_frame_delay.to_value(), "max-frame-delay" => settings.max_frame_delay.to_value(),
"apply-grain" => settings.apply_grain.to_value(),
"inloop-filters" => settings.inloop_filters.to_value(),
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
@ -841,6 +898,8 @@ impl VideoDecoderImpl for Dav1dDec {
); );
decoder_settings.set_n_threads(settings.n_threads); decoder_settings.set_n_threads(settings.n_threads);
decoder_settings.set_max_frame_delay(max_frame_delay); decoder_settings.set_max_frame_delay(max_frame_delay);
decoder_settings.set_apply_grain(settings.apply_grain);
decoder_settings.set_inloop_filters(dav1d::InloopFilterType::from(settings.inloop_filters));
let decoder = dav1d::Decoder::with_settings(&decoder_settings).map_err(|err| { let decoder = dav1d::Decoder::with_settings(&decoder_settings).map_err(|err| {
gst::loggable_error!(CAT, "Failed to create decoder instance: {}", err) gst::loggable_error!(CAT, "Failed to create decoder instance: {}", err)

View file

@ -18,6 +18,9 @@ glib::wrapper! {
} }
pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> {
#[cfg(feature = "doc")]
imp::InloopFilterType::static_type().mark_as_plugin_api(gst::PluginAPIFlags::empty());
let rank = if gst::version() >= (1, 21, 2, 1) { let rank = if gst::version() >= (1, 21, 2, 1) {
// AOM av1dec rank was demoted in 1.22 dev cycle // AOM av1dec rank was demoted in 1.22 dev cycle
// https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3287 // https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3287