mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-12 05:11:32 +00:00
7d3ab342d2
Audio decoder element structure is based in `gst-plugin-lewton` (a lewton based Vorbis decoder created by @slomo) The element assumes correctly parsed input from `flacparse`. Implementation details: * Claxon returned frames does not contain audio channels interleaved, the reorganization of the channels is done by the element. * Claxon output buffers are always Vec<i32>, mapping to the correct type (depending on the audio format) is also done by the element. Mono s16 and stereo_s32 test are provided. Complete pipelines to test are: ``` gst-launch-1.0 -v souphttpsrc location=https://archive.org/download/MLKDream/MLKDream.flac ! queue2 ! flacparse ! flacdec ! audioconvert ! autoaudiosink gst-launch-1.0 -v audiotestsrc ! audio/x-raw, format=S16LE, layout=interleaved, rate=44100, channels=1 ! audioconvert ! flacenc ! flacparse ! claxondec ! autoaudiosink ``` Fixes #71
116 lines
3.2 KiB
Rust
116 lines
3.2 KiB
Rust
// Copyright (C) 2019 Ruben Gonzalez <rgonzalez@fluendo.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.
|
|
|
|
extern crate glib;
|
|
extern crate gstreamer as gst;
|
|
use gst::prelude::*;
|
|
extern crate gstreamer_audio as gst_audio;
|
|
extern crate gstreamer_check as gst_check;
|
|
|
|
extern crate gstclaxon;
|
|
|
|
fn init() {
|
|
use std::sync::Once;
|
|
static INIT: Once = Once::new();
|
|
|
|
INIT.call_once(|| {
|
|
gst::init().unwrap();
|
|
gstclaxon::plugin_register_static().expect("claxon test");
|
|
});
|
|
}
|
|
|
|
#[test]
|
|
fn test_mono_s16() {
|
|
let data = include_bytes!("test_mono_s16.flac");
|
|
// 4 fLaC header, 38 streaminfo_header, 66 other header, 18 data
|
|
let packet_sizes = [4, 38, 66, 18];
|
|
let decoded_samples = [0usize, 0usize, 0usize, 2];
|
|
|
|
let caps = do_test(data, &packet_sizes, &decoded_samples);
|
|
|
|
assert_eq!(
|
|
caps,
|
|
gst::Caps::builder("audio/x-raw")
|
|
.field("format", &gst_audio::AUDIO_FORMAT_S16.to_str())
|
|
.field("rate", &44_100i32)
|
|
.field("channels", &1i32)
|
|
.field("layout", &"interleaved")
|
|
.build()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_stereo_s32() {
|
|
let data = include_bytes!("test_stereo_s32.flac");
|
|
// 4 fLaC header, 38 streaminfo_header, 17465 data
|
|
let packet_sizes = [4, 38, 17465];
|
|
let decoded_samples = [0usize, 0usize, 8192];
|
|
|
|
let caps = do_test(data, &packet_sizes, &decoded_samples);
|
|
|
|
assert_eq!(
|
|
caps,
|
|
gst::Caps::builder("audio/x-raw")
|
|
.field("format", &gst_audio::AUDIO_FORMAT_S2432.to_str())
|
|
.field("rate", &44_100i32)
|
|
.field("channels", &2i32)
|
|
.field("layout", &"interleaved")
|
|
.field("channel-mask", &gst::Bitmask::new(0x3))
|
|
.build()
|
|
);
|
|
}
|
|
|
|
fn do_test(data: &'static [u8], packet_sizes: &[usize], decoded_samples: &[usize]) -> gst::Caps {
|
|
let packet_offsets = packet_sizes
|
|
.iter()
|
|
.scan(0, |state, &size| {
|
|
*state += size;
|
|
Some(*state)
|
|
})
|
|
.collect::<Vec<usize>>();
|
|
|
|
init();
|
|
|
|
let mut h = gst_check::Harness::new("claxondec");
|
|
h.play();
|
|
|
|
let caps = gst::Caps::builder("audio/x-flac")
|
|
.field("framed", &true)
|
|
.build();
|
|
h.set_src_caps(caps);
|
|
|
|
let packet_offsets_iter = std::iter::once(&0).chain(packet_offsets.iter());
|
|
let skip = 0;
|
|
|
|
for (offset_start, offset_end) in packet_offsets_iter
|
|
.clone()
|
|
.skip(skip)
|
|
.zip(packet_offsets_iter.clone().skip(skip + 1))
|
|
{
|
|
let buffer = gst::Buffer::from_slice(&data[*offset_start..*offset_end]);
|
|
h.push(buffer).unwrap();
|
|
}
|
|
|
|
h.push_event(gst::Event::new_eos().build());
|
|
|
|
for samples in decoded_samples {
|
|
if *samples == 0 {
|
|
continue;
|
|
}
|
|
let buffer = h.pull().unwrap();
|
|
assert_eq!(buffer.get_size(), 4 * samples);
|
|
}
|
|
|
|
let caps = h
|
|
.get_sinkpad()
|
|
.expect("harness has no sinkpad")
|
|
.get_current_caps()
|
|
.expect("pad has no caps");
|
|
|
|
caps
|
|
}
|