From cfe660ae8232d0e7bbfe9b949319189820546e2a Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Wed, 1 May 2019 16:39:16 +0530 Subject: [PATCH] cdg: add cdgdec element CDG video decoder used to render karaoke videos. Acting as a parser for now as we don't have cdgparse yet. I'll probably implement it at some point once we have GstBaseParse bindings. --- Cargo.toml | 1 + gst-plugin-cdg/Cargo.toml | 23 +++ gst-plugin-cdg/src/cdgdec.rs | 256 +++++++++++++++++++++++++++ gst-plugin-cdg/src/lib.rs | 32 ++++ gst-plugin-cdg/tests/BrotherJohn.cdg | Bin 0 -> 583200 bytes gst-plugin-cdg/tests/cdgdec.rs | 107 +++++++++++ 6 files changed, 419 insertions(+) create mode 100644 gst-plugin-cdg/Cargo.toml create mode 100644 gst-plugin-cdg/src/cdgdec.rs create mode 100644 gst-plugin-cdg/src/lib.rs create mode 100644 gst-plugin-cdg/tests/BrotherJohn.cdg create mode 100644 gst-plugin-cdg/tests/cdgdec.rs diff --git a/Cargo.toml b/Cargo.toml index 9cbabbd6..1d937706 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ members = [ "gst-plugin-tutorial", "gst-plugin-closedcaption", "gst-plugin-sodium", + "gst-plugin-cdg", ] [profile.release] diff --git a/gst-plugin-cdg/Cargo.toml b/gst-plugin-cdg/Cargo.toml new file mode 100644 index 00000000..d570f1c9 --- /dev/null +++ b/gst-plugin-cdg/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "gst-plugin-cdg" +version = "0.5.0" +authors = ["Guillaume Desmottes "] +repository = "https://gitlab.freedesktop.org/gstreamer/gst-plugin-rs" +license = "MIT/Apache-2.0" +edition = "2018" + +[dependencies] +glib = { git = "https://github.com/gtk-rs/glib" } +gstreamer = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["subclassing", "v1_12"] } +gstreamer-base = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["subclassing", "v1_12"] } +gstreamer-video = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs", features = ["subclassing", "v1_12"] } +gstreamer-app = { git = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" } +cdg = "0.1.0" +cdg_renderer = "0.1.1" +image = "0.10" +muldiv = "0.2" + +[lib] +name = "gstrscdg" +crate-type = ["cdylib", "rlib"] +path = "src/lib.rs" diff --git a/gst-plugin-cdg/src/cdgdec.rs b/gst-plugin-cdg/src/cdgdec.rs new file mode 100644 index 00000000..7e48d4ec --- /dev/null +++ b/gst-plugin-cdg/src/cdgdec.rs @@ -0,0 +1,256 @@ +// Copyright (C) 2019 Guillaume Desmottes +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use cdg; +use cdg_renderer; +use glib; +use glib::subclass; +use glib::subclass::prelude::*; +use glib::Cast; +use gst; +use gst::subclass::prelude::*; +use gst::{ClockTime, SECOND_VAL}; +use gst_video::prelude::VideoDecoderExtManual; +use gst_video::prelude::*; +use gst_video::subclass::prelude::*; +use gstreamer_base as gst_base; +use gstreamer_video as gst_video; +use image::GenericImage; +use muldiv::MulDiv; +use std::sync::Mutex; + +const CDG_PACKET_SIZE: i32 = 24; +// 75 sectors/sec * 4 packets/sector = 300 packets/sec +const CDG_PACKET_PERIOD: u64 = 300; + +const CDG_WIDTH: u32 = 300; +const CDG_HEIGHT: u32 = 216; + +struct CdgDec { + cat: gst::DebugCategory, + cdg_inter: Mutex, + output_info: Mutex>, +} + +impl ObjectSubclass for CdgDec { + const NAME: &'static str = "CdgDec"; + type ParentType = gst_video::VideoDecoder; + type Instance = gst::subclass::ElementInstanceStruct; + type Class = subclass::simple::ClassStruct; + + glib_object_subclass!(); + + fn new() -> Self { + Self { + cat: gst::DebugCategory::new("cdgdec", gst::DebugColorFlags::empty(), "CDG decoder"), + cdg_inter: Mutex::new(cdg_renderer::CdgInterpreter::new()), + output_info: Mutex::new(None), + } + } + + fn class_init(klass: &mut subclass::simple::ClassStruct) { + klass.set_metadata( + "CDG decoder", + "Decoder/Video", + "CDG decoder", + "Guillaume Desmottes ", + ); + + let sink_caps = gst::Caps::new_simple("video/x-cdg", &[]); + let sink_pad_template = gst::PadTemplate::new( + "sink", + gst::PadDirection::Sink, + gst::PadPresence::Always, + &sink_caps, + ) + .unwrap(); + klass.add_pad_template(sink_pad_template); + + let src_caps = gst::Caps::new_simple( + "video/x-raw", + &[ + ("format", &gst_video::VideoFormat::Rgba.to_string()), + ("width", &(CDG_WIDTH as i32)), + ("height", &(CDG_HEIGHT as i32)), + ("framerate", &gst::Fraction::new(0, 1)), + ], + ); + let src_pad_template = gst::PadTemplate::new( + "src", + gst::PadDirection::Src, + gst::PadPresence::Always, + &src_caps, + ) + .unwrap(); + klass.add_pad_template(src_pad_template); + } +} + +impl ObjectImpl for CdgDec { + glib_object_impl!(); + + fn constructed(&self, obj: &glib::Object) { + self.parent_constructed(obj); + + let dec = obj.downcast_ref::().unwrap(); + dec.set_packetized(false); + } +} + +impl ElementImpl for CdgDec {} + +impl VideoDecoderImpl for CdgDec { + fn start(&self, element: &gst_video::VideoDecoder) -> Result<(), gst::ErrorMessage> { + let mut out_info = self.output_info.lock().unwrap(); + *out_info = None; + + self.parent_start(element) + } + + fn parse( + &self, + element: &gst_video::VideoDecoder, + _frame: &gst_video::VideoCodecFrame, + adapter: &gst_base::Adapter, + _at_eos: bool, + ) -> Result { + // FIXME: scan for CDG header + if adapter.available() >= CDG_PACKET_SIZE as usize { + element.add_to_frame(CDG_PACKET_SIZE); + element.have_frame() + } else { + Ok(gst::FlowSuccess::CustomSuccess) + } + } + + fn handle_frame( + &self, + element: &gst_video::VideoDecoder, + frame: gst_video::VideoCodecFrame, + ) -> Result { + { + let mut out_info = self.output_info.lock().unwrap(); + if out_info.is_none() { + let output_state = element.set_output_state( + gst_video::VideoFormat::Rgba, + CDG_WIDTH, + CDG_HEIGHT, + None, + )?; + + element.negotiate(output_state)?; + + let out_state = element.get_output_state().unwrap(); + *out_info = Some(out_state.get_info()); + } + } + + let cmd = { + let input = frame.get_input_buffer().unwrap(); + let map = input.map_readable().ok_or_else(|| { + gst_element_error!( + element, + gst::CoreError::Failed, + ["Failed to map input buffer readable"] + ); + gst::FlowError::Error + })?; + let data = map.as_slice(); + + cdg::decode_subchannel_cmd(&data) + }; + + let cmd = match cmd { + Some(cmd) => cmd, + None => { + // Not a CDG command + element.release_frame(frame); + return Ok(gst::FlowSuccess::Ok); + } + }; + + let mut cdg_inter = self.cdg_inter.lock().unwrap(); + cdg_inter.handle_cmd(cmd); + + element.allocate_output_frame(&frame, None)?; + { + let output = frame.get_output_buffer().unwrap(); + let info = self.output_info.lock().unwrap(); + + let mut out_frame = + gst_video::VideoFrameRef::from_buffer_ref_writable(output, info.as_ref().unwrap()) + .ok_or_else(|| { + gst_element_error!( + element, + gst::CoreError::Failed, + ["Failed to map output buffer writable"] + ); + gst::FlowError::Error + })?; + + let out_stride = out_frame.plane_stride()[0] as usize; + + for (y, line) in out_frame + .plane_data_mut(0) + .unwrap() + .chunks_exact_mut(out_stride) + .take(CDG_HEIGHT as usize) + .enumerate() + { + for (x, pixel) in line + .chunks_exact_mut(4) + .take(CDG_WIDTH as usize) + .enumerate() + { + let p = cdg_inter.get_pixel(x as u32, y as u32); + pixel[0] = p.data[0]; + pixel[1] = p.data[1]; + pixel[2] = p.data[2]; + pixel[3] = p.data[3]; + } + } + } + + let pts = { + // FIXME: this won't work when seeking + let nb = frame.get_decode_frame_number() as u64; + let ns = nb.mul_div_round(SECOND_VAL, CDG_PACKET_PERIOD).unwrap(); + ClockTime::from_nseconds(ns) + }; + + gst_debug!(self.cat, obj: element, "Finish frame pts={}", pts); + + frame.set_pts(pts); + element.finish_frame(frame) + } + + fn decide_allocation( + &self, + element: &gst_video::VideoDecoder, + query: &mut gst::QueryRef, + ) -> Result<(), gst::ErrorMessage> { + self.parent_decide_allocation(element, query)?; + + if let gst::query::QueryView::Allocation(allocation) = query.view() { + let pools = allocation.get_allocation_pools(); + if let Some((ref pool, _, _, _)) = pools.first() { + if let Some(pool) = pool { + let mut config = pool.get_config(); + config.add_option(&gst_video::BUFFER_POOL_OPTION_VIDEO_META); + pool.set_config(config).unwrap(); + } + } + } + + Ok(()) + } +} + +pub fn register(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { + gst::Element::register(Some(plugin), "cdgdec", 0, CdgDec::get_type()) +} diff --git a/gst-plugin-cdg/src/lib.rs b/gst-plugin-cdg/src/lib.rs new file mode 100644 index 00000000..b6fbd64e --- /dev/null +++ b/gst-plugin-cdg/src/lib.rs @@ -0,0 +1,32 @@ +// Copyright (C) 2019 Guillaume Desmottes +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "cdylib"] + +#[macro_use] +extern crate glib; +#[macro_use] +extern crate gstreamer as gst; + +mod cdgdec; + +fn plugin_init(plugin: &gst::Plugin) -> Result<(), glib::BoolError> { + cdgdec::register(plugin) +} + +gst_plugin_define!( + "cdg", + "CDG Plugin", + plugin_init, + "1.0", + "MIT/X11", + "cdg", + "cdg", + "https://gitlab.freedesktop.org/gstreamer/gst-plugin-rs", + "2019-05-01" +); diff --git a/gst-plugin-cdg/tests/BrotherJohn.cdg b/gst-plugin-cdg/tests/BrotherJohn.cdg new file mode 100644 index 0000000000000000000000000000000000000000..9ec6ec15359764512a97e011d107c6f78987b91c GIT binary patch literal 583200 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 literal 0 HcmV?d00001 diff --git a/gst-plugin-cdg/tests/cdgdec.rs b/gst-plugin-cdg/tests/cdgdec.rs new file mode 100644 index 00000000..3059f14c --- /dev/null +++ b/gst-plugin-cdg/tests/cdgdec.rs @@ -0,0 +1,107 @@ +// Copyright (C) 2019 Guillaume Desmottes +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use gst_app::prelude::*; +use gstreamer as gst; +use gstreamer_app as gst_app; +use std::path::PathBuf; + +use gstrscdg; + +fn init() { + use std::sync::{Once, ONCE_INIT}; + static INIT: Once = ONCE_INIT; + + INIT.call_once(|| { + gst::init().unwrap(); + gstrscdg::plugin_register_static().expect("cdgdec tests"); + }); +} + +#[test] +fn test_cdgdec() { + init(); + + let pipeline = gst::Pipeline::new(Some("cdgdec-test")); + + let input_path = { + let mut r = PathBuf::new(); + r.push(env!("CARGO_MANIFEST_DIR")); + r.push("tests"); + r.push("BrotherJohn"); + r.set_extension("cdg"); + r + }; + + let filesrc = gst::ElementFactory::make("filesrc", None).unwrap(); + filesrc + .set_property("location", &input_path.to_str().unwrap()) + .expect("failed to set 'location' property"); + filesrc + .set_property("num-buffers", &1) + .expect("failed to set 'num-buffers' property"); + let blocksize: u32 = 24; // One CDG instruction + filesrc + .set_property("blocksize", &blocksize) + .expect("failed to set 'blocksize' property"); + + let dec = gst::ElementFactory::make("cdgdec", None).unwrap(); + let sink = gst::ElementFactory::make("appsink", None).unwrap(); + + pipeline + .add_many(&[&filesrc, &dec, &sink]) + .expect("failed to add elements to the pipeline"); + gst::Element::link_many(&[&filesrc, &dec, &sink]).expect("failed to link the elements"); + + let sink = sink.downcast::().unwrap(); + sink.set_callbacks( + gst_app::AppSinkCallbacks::new() + // Add a handler to the "new-sample" signal. + .new_sample(move |appsink| { + // Pull the sample in question out of the appsink's buffer. + let sample = appsink.pull_sample().ok_or(gst::FlowError::Eos)?; + let buffer = sample.get_buffer().ok_or(gst::FlowError::Error)?; + let map = buffer.map_readable().ok_or(gst::FlowError::Error)?; + + // First frame fully blue + map.as_slice() + .chunks_exact(4) + .for_each(|p| assert_eq!(p, [0, 0, 136, 255])); + + Ok(gst::FlowSuccess::Ok) + }) + .build(), + ); + + pipeline + .set_state(gst::State::Playing) + .expect("Unable to set the pipeline to the `Playing` state"); + + let bus = pipeline.get_bus().unwrap(); + for msg in bus.iter_timed(gst::CLOCK_TIME_NONE) { + use gst::MessageView; + match msg.view() { + MessageView::Error(err) => { + eprintln!( + "Error received from element {:?}: {}", + err.get_src().map(|s| s.get_path_string()), + err.get_error() + ); + eprintln!("Debugging information: {:?}", err.get_debug()); + assert!(true); + break; + } + MessageView::Eos(..) => break, + _ => (), + } + } + + pipeline + .set_state(gst::State::Null) + .expect("Unable to set the pipeline to the `Null` state"); +}