diff options
author | Sebastian Dröge <sebastian@centricular.com> | 2020-11-15 16:50:12 +0300 |
---|---|---|
committer | Sebastian Dröge <sebastian@centricular.com> | 2020-11-15 19:50:31 +0300 |
commit | 717477fd36f00c5f1b8dbb64ec4dadc602d5fc22 (patch) | |
tree | 7387cf91d55c71afa125a6891579045fa6de5197 /video/cdg | |
parent | b021a8bf100bbd7bbb35c28a7fc9fff78afad28f (diff) |
video: Update for subclassing API changes
Diffstat (limited to 'video/cdg')
-rw-r--r-- | video/cdg/src/cdgdec/imp.rs (renamed from video/cdg/src/cdgdec.rs) | 32 | ||||
-rw-r--r-- | video/cdg/src/cdgdec/mod.rs | 29 | ||||
-rw-r--r-- | video/cdg/src/cdgparse/imp.rs (renamed from video/cdg/src/cdgparse.rs) | 20 | ||||
-rw-r--r-- | video/cdg/src/cdgparse/mod.rs | 29 | ||||
-rw-r--r-- | video/cdg/src/lib.rs | 83 | ||||
-rw-r--r-- | video/cdg/src/typefind.rs | 87 |
6 files changed, 165 insertions, 115 deletions
diff --git a/video/cdg/src/cdgdec.rs b/video/cdg/src/cdgdec/imp.rs index 92d1a34ad..2a2365d1c 100644 --- a/video/cdg/src/cdgdec.rs +++ b/video/cdg/src/cdgdec/imp.rs @@ -17,18 +17,19 @@ use std::sync::Mutex; use crate::constants::{CDG_HEIGHT, CDG_WIDTH}; -struct CdgDec { - cdg_inter: Mutex<Box<cdg_renderer::CdgInterpreter>>, - output_info: Mutex<Option<gst_video::VideoInfo>>, -} - lazy_static! { static ref CAT: gst::DebugCategory = gst::DebugCategory::new("cdgdec", gst::DebugColorFlags::empty(), Some("CDG decoder"),); } +pub struct CdgDec { + cdg_inter: Mutex<Box<cdg_renderer::CdgInterpreter>>, + output_info: Mutex<Option<gst_video::VideoInfo>>, +} + impl ObjectSubclass for CdgDec { const NAME: &'static str = "CdgDec"; + type Type = super::CdgDec; type ParentType = gst_video::VideoDecoder; type Instance = gst::subclass::ElementInstanceStruct<Self>; type Class = subclass::simple::ClassStruct<Self>; @@ -42,7 +43,7 @@ impl ObjectSubclass for CdgDec { } } - fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) { + fn class_init(klass: &mut Self::Class) { klass.set_metadata( "CDG decoder", "Decoder/Video", @@ -85,14 +86,14 @@ impl ObjectImpl for CdgDec {} impl ElementImpl for CdgDec {} impl VideoDecoderImpl for CdgDec { - fn start(&self, element: &gst_video::VideoDecoder) -> Result<(), gst::ErrorMessage> { + fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> { let mut out_info = self.output_info.lock().unwrap(); *out_info = None; self.parent_start(element) } - fn stop(&self, element: &gst_video::VideoDecoder) -> Result<(), gst::ErrorMessage> { + fn stop(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> { { let mut cdg_inter = self.cdg_inter.lock().unwrap(); cdg_inter.reset(true); @@ -102,7 +103,7 @@ impl VideoDecoderImpl for CdgDec { fn handle_frame( &self, - element: &gst_video::VideoDecoder, + element: &Self::Type, mut frame: gst_video::VideoCodecFrame, ) -> Result<gst::FlowSuccess, gst::FlowError> { { @@ -192,7 +193,7 @@ impl VideoDecoderImpl for CdgDec { fn decide_allocation( &self, - element: &gst_video::VideoDecoder, + element: &Self::Type, query: &mut gst::QueryRef, ) -> Result<(), gst::ErrorMessage> { if let gst::query::QueryView::Allocation(allocation) = query.view() { @@ -216,7 +217,7 @@ impl VideoDecoderImpl for CdgDec { self.parent_decide_allocation(element, query) } - fn flush(&self, element: &gst_video::VideoDecoder) -> bool { + fn flush(&self, element: &Self::Type) -> bool { gst_debug!(CAT, obj: element, "flushing, reset CDG interpreter"); let mut cdg_inter = self.cdg_inter.lock().unwrap(); @@ -224,12 +225,3 @@ impl VideoDecoderImpl for CdgDec { true } } - -pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { - gst::Element::register( - Some(plugin), - "cdgdec", - gst::Rank::Primary, - CdgDec::get_type(), - ) -} diff --git a/video/cdg/src/cdgdec/mod.rs b/video/cdg/src/cdgdec/mod.rs new file mode 100644 index 000000000..daf17cb42 --- /dev/null +++ b/video/cdg/src/cdgdec/mod.rs @@ -0,0 +1,29 @@ +// Copyright (C) 2019 Guillaume Desmottes <guillaume.desmottes@collabora.com> +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use glib::prelude::*; + +mod imp; + +glib_wrapper! { + pub struct CdgDec(ObjectSubclass<imp::CdgDec>) @extends gst_video::VideoDecoder, gst::Element, gst::Object; +} + +// GStreamer elements need to be thread-safe. For the private implementation this is automatically +// enforced but for the public wrapper type we need to specify this manually. +unsafe impl Send for CdgDec {} +unsafe impl Sync for CdgDec {} + +pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { + gst::Element::register( + Some(plugin), + "cdgdec", + gst::Rank::Primary, + CdgDec::static_type(), + ) +} diff --git a/video/cdg/src/cdgparse.rs b/video/cdg/src/cdgparse/imp.rs index 50b46072b..7b564a5a1 100644 --- a/video/cdg/src/cdgparse.rs +++ b/video/cdg/src/cdgparse/imp.rs @@ -23,7 +23,7 @@ const CDG_CMD_MEMORY_PRESET: u8 = 1; const CDG_CMD_MEMORY_LOAD_COLOR_TABLE_1: u8 = 30; const CDG_CMD_MEMORY_LOAD_COLOR_TABLE_2: u8 = 31; -struct CdgParse; +pub struct CdgParse; lazy_static! { static ref CAT: gst::DebugCategory = gst::DebugCategory::new( @@ -35,6 +35,7 @@ lazy_static! { impl ObjectSubclass for CdgParse { const NAME: &'static str = "CdgParse"; + type Type = super::CdgParse; type ParentType = gst_base::BaseParse; type Instance = gst::subclass::ElementInstanceStruct<Self>; type Class = subclass::simple::ClassStruct<Self>; @@ -45,7 +46,7 @@ impl ObjectSubclass for CdgParse { Self } - fn class_init(klass: &mut subclass::simple::ClassStruct<Self>) { + fn class_init(klass: &mut Self::Class) { klass.set_metadata( "CDG parser", "Codec/Parser/Video", @@ -108,7 +109,7 @@ fn time_to_bytes(time: gst::ClockTime) -> Bytes { } impl BaseParseImpl for CdgParse { - fn start(&self, element: &gst_base::BaseParse) -> Result<(), gst::ErrorMessage> { + fn start(&self, element: &Self::Type) -> Result<(), gst::ErrorMessage> { element.set_min_frame_size(CDG_PACKET_SIZE as u32); /* Set duration */ @@ -125,7 +126,7 @@ impl BaseParseImpl for CdgParse { fn handle_frame( &self, - element: &gst_base::BaseParse, + element: &Self::Type, mut frame: gst_base::BaseParseFrame, ) -> Result<(gst::FlowSuccess, u32), gst::FlowError> { let pad = element.get_src_pad(); @@ -212,7 +213,7 @@ impl BaseParseImpl for CdgParse { fn convert<V: Into<gst::GenericFormattedValue>>( &self, - _element: &gst_base::BaseParse, + _element: &Self::Type, src_val: V, dest_format: gst::Format, ) -> Option<gst::GenericFormattedValue> { @@ -229,12 +230,3 @@ impl BaseParseImpl for CdgParse { } } } - -pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { - gst::Element::register( - Some(plugin), - "cdgparse", - gst::Rank::Primary, - CdgParse::get_type(), - ) -} diff --git a/video/cdg/src/cdgparse/mod.rs b/video/cdg/src/cdgparse/mod.rs new file mode 100644 index 000000000..10cac351f --- /dev/null +++ b/video/cdg/src/cdgparse/mod.rs @@ -0,0 +1,29 @@ +// Copyright (C) 2019 Guillaume Desmottes <guillaume.desmottes@collabora.com> +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use glib::prelude::*; + +mod imp; + +glib_wrapper! { + pub struct CdgParse(ObjectSubclass<imp::CdgParse>) @extends gst_base::BaseParse, gst::Element, gst::Object; +} + +// GStreamer elements need to be thread-safe. For the private implementation this is automatically +// enforced but for the public wrapper type we need to specify this manually. +unsafe impl Send for CdgParse {} +unsafe impl Sync for CdgParse {} + +pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { + gst::Element::register( + Some(plugin), + "cdgparse", + gst::Rank::Primary, + CdgParse::static_type(), + ) +} diff --git a/video/cdg/src/lib.rs b/video/cdg/src/lib.rs index 4083adc7b..c5e5bb513 100644 --- a/video/cdg/src/lib.rs +++ b/video/cdg/src/lib.rs @@ -18,91 +18,12 @@ extern crate lazy_static; mod cdgdec; mod cdgparse; mod constants; - -use constants::{CDG_COMMAND, CDG_MASK, CDG_PACKET_PERIOD, CDG_PACKET_SIZE}; -use gst::{Caps, TypeFind, TypeFindProbability}; -use std::cmp; - -const NB_WINDOWS: u64 = 8; -const TYPEFIND_SEARCH_WINDOW_SEC: i64 = 4; -const TYPEFIND_SEARCH_WINDOW: i64 = - TYPEFIND_SEARCH_WINDOW_SEC * (CDG_PACKET_SIZE as i64 * CDG_PACKET_PERIOD as i64); /* in bytes */ - -/* Return the percentage of CDG packets in the first @len bytes of @typefind */ -fn cdg_packets_ratio(typefind: &mut TypeFind, start: i64, len: i64) -> i64 { - let mut count = 0; - let total = len / CDG_PACKET_SIZE as i64; - - for offset in (0..len).step_by(CDG_PACKET_SIZE as usize) { - match typefind.peek(start + offset, CDG_PACKET_SIZE as u32) { - Some(data) => { - if data[0] & CDG_MASK == CDG_COMMAND { - count += 1; - } - } - None => break, - } - } - (count * 100) / total -} - -/* Some CDG files starts drawing right away and then pause for a while - * (typically because of the song intro) while other wait for a few - * seconds before starting to draw. - * In order to support all variants, scan through all the file per block - * of size TYPEFIND_SEARCH_WINDOW and keep the highest ratio of CDG packets - * detected. */ -fn compute_probability(typefind: &mut TypeFind) -> TypeFindProbability { - let mut best = TypeFindProbability::None; - // Try looking at the start of the file if its length isn't available - let len = typefind - .get_length() - .unwrap_or(TYPEFIND_SEARCH_WINDOW as u64 * NB_WINDOWS); - let step = len / NB_WINDOWS; - - // Too short file - if step == 0 { - return TypeFindProbability::None; - } - - for offset in (0..len).step_by(step as usize) { - let proba = match cdg_packets_ratio(typefind, offset as i64, TYPEFIND_SEARCH_WINDOW) { - 0..=5 => TypeFindProbability::None, - 6..=10 => TypeFindProbability::Possible, - _ => TypeFindProbability::Likely, - }; - - if proba == TypeFindProbability::Likely { - return proba; - } - - best = cmp::max(best, proba); - } - - best -} - -fn typefind_register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { - TypeFind::register( - Some(plugin), - "cdg_typefind", - gst::Rank::None, - Some("cdg"), - Some(&Caps::new_simple("video/x-cdg", &[])), - |mut typefind| { - let proba = compute_probability(&mut typefind); - - if proba != gst::TypeFindProbability::None { - typefind.suggest(proba, &Caps::new_simple("video/x-cdg", &[])); - } - }, - ) -} +mod typefind; fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { cdgdec::register(plugin)?; cdgparse::register(plugin)?; - typefind_register(plugin)?; + typefind::register(plugin)?; Ok(()) } diff --git a/video/cdg/src/typefind.rs b/video/cdg/src/typefind.rs new file mode 100644 index 000000000..e81438497 --- /dev/null +++ b/video/cdg/src/typefind.rs @@ -0,0 +1,87 @@ +// Copyright (C) 2019 Guillaume Desmottes <guillaume.desmottes@collabora.com> +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::constants::{CDG_COMMAND, CDG_MASK, CDG_PACKET_PERIOD, CDG_PACKET_SIZE}; +use gst::{Caps, TypeFind, TypeFindProbability}; +use std::cmp; + +const NB_WINDOWS: u64 = 8; +const TYPEFIND_SEARCH_WINDOW_SEC: i64 = 4; +const TYPEFIND_SEARCH_WINDOW: i64 = + TYPEFIND_SEARCH_WINDOW_SEC * (CDG_PACKET_SIZE as i64 * CDG_PACKET_PERIOD as i64); /* in bytes */ + +/* Return the percentage of CDG packets in the first @len bytes of @typefind */ +fn cdg_packets_ratio(typefind: &mut TypeFind, start: i64, len: i64) -> i64 { + let mut count = 0; + let total = len / CDG_PACKET_SIZE as i64; + + for offset in (0..len).step_by(CDG_PACKET_SIZE as usize) { + match typefind.peek(start + offset, CDG_PACKET_SIZE as u32) { + Some(data) => { + if data[0] & CDG_MASK == CDG_COMMAND { + count += 1; + } + } + None => break, + } + } + (count * 100) / total +} + +/* Some CDG files starts drawing right away and then pause for a while + * (typically because of the song intro) while other wait for a few + * seconds before starting to draw. + * In order to support all variants, scan through all the file per block + * of size TYPEFIND_SEARCH_WINDOW and keep the highest ratio of CDG packets + * detected. */ +fn compute_probability(typefind: &mut TypeFind) -> TypeFindProbability { + let mut best = TypeFindProbability::None; + // Try looking at the start of the file if its length isn't available + let len = typefind + .get_length() + .unwrap_or(TYPEFIND_SEARCH_WINDOW as u64 * NB_WINDOWS); + let step = len / NB_WINDOWS; + + // Too short file + if step == 0 { + return TypeFindProbability::None; + } + + for offset in (0..len).step_by(step as usize) { + let proba = match cdg_packets_ratio(typefind, offset as i64, TYPEFIND_SEARCH_WINDOW) { + 0..=5 => TypeFindProbability::None, + 6..=10 => TypeFindProbability::Possible, + _ => TypeFindProbability::Likely, + }; + + if proba == TypeFindProbability::Likely { + return proba; + } + + best = cmp::max(best, proba); + } + + best +} + +pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { + TypeFind::register( + Some(plugin), + "cdg_typefind", + gst::Rank::None, + Some("cdg"), + Some(&Caps::new_simple("video/x-cdg", &[])), + |mut typefind| { + let proba = compute_probability(&mut typefind); + + if proba != gst::TypeFindProbability::None { + typefind.suggest(proba, &Caps::new_simple("video/x-cdg", &[])); + } + }, + ) +} |