appsink.rs 3.28 KB
Newer Older
Sebastian Dröge's avatar
Sebastian Dröge committed
1
extern crate gstreamer as gst;
2
use gst::prelude::*;
Sebastian Dröge's avatar
Sebastian Dröge committed
3
extern crate gstreamer_app as gst_app;
4
extern crate gstreamer_audio as gst_audio;
Sebastian Dröge's avatar
Sebastian Dröge committed
5

6
7
8
extern crate byte_slice_cast;
use byte_slice_cast::*;

Sebastian Dröge's avatar
Sebastian Dröge committed
9
10
11
12
use std::u64;
use std::i16;
use std::i32;

13
pub mod utils;
14

15
fn create_pipeline() -> Result<gst::Pipeline, utils::ExampleError> {
16
    gst::init().map_err(utils::ExampleError::InitFailed)?;
Sebastian Dröge's avatar
Sebastian Dröge committed
17
    let pipeline = gst::Pipeline::new(None);
18
19
    let src = utils::create_element("audiotestsrc")?;
    let sink = utils::create_element("appsink")?;
20
21
22
23

    pipeline
        .add_many(&[&src, &sink])
        .expect("Unable to add elements in the pipeline");
Sebastian Dröge's avatar
Sebastian Dröge committed
24

25
    utils::link_elements(&src, &sink)?;
26
27

    let appsink = sink.clone()
28
        .dynamic_cast::<gst_app::AppSink>()
29
        .expect("Sink element is expected to be an appsink!");
Sebastian Dröge's avatar
Sebastian Dröge committed
30

31
    appsink.set_caps(&gst::Caps::new_simple(
Sebastian Dröge's avatar
Sebastian Dröge committed
32
33
        "audio/x-raw",
        &[
34
            ("format", &gst_audio::AUDIO_FORMAT_S16.to_string()),
35
36
            ("layout", &"interleaved"),
            ("channels", &(1i32)),
37
            ("rate", &gst::IntRange::<i32>::new(1, i32::MAX)),
Sebastian Dröge's avatar
Sebastian Dröge committed
38
39
40
        ],
    ));

41
    appsink.set_callbacks(gst_app::AppSinkCallbacks::new(
Sebastian Dröge's avatar
Sebastian Dröge committed
42
43
44
        /* eos */
        |_| {},
        /* new_preroll */
45
        |_| gst::FlowReturn::Ok,
Sebastian Dröge's avatar
Sebastian Dröge committed
46
47
48
        /* new_samples */
        |appsink| {
            let sample = match appsink.pull_sample() {
49
                None => return gst::FlowReturn::Eos,
Sebastian Dröge's avatar
Sebastian Dröge committed
50
51
52
                Some(sample) => sample,
            };

53
54
55
            let buffer = sample
                .get_buffer()
                .expect("Unable to extract buffer from the sample");
56

57
58
59
            let map = buffer
                .map_readable()
                .expect("Unable to map buffer for reading");
60

61
            let samples = if let Ok(samples) = map.as_slice().as_slice_of::<i16>() {
62
63
                samples
            } else {
64
                return gst::FlowReturn::Error;
65
66
67
68
            };

            let sum: f64 = samples
                .iter()
Sebastian Dröge's avatar
Sebastian Dröge committed
69
                .map(|sample| {
70
                    let f = f64::from(*sample) / f64::from(i16::MAX);
Sebastian Dröge's avatar
Sebastian Dröge committed
71
72
73
                    f * f
                })
                .sum();
74
            let rms = (sum / (samples.len() as f64)).sqrt();
Sebastian Dröge's avatar
Sebastian Dröge committed
75
76
            println!("rms: {}", rms);

77
            gst::FlowReturn::Ok
Sebastian Dröge's avatar
Sebastian Dröge committed
78
79
80
        },
    ));

81
82
83
    Ok(pipeline)
}

84
fn main_loop() -> Result<(), utils::ExampleError> {
85
    let pipeline = create_pipeline()?;
Sebastian Dröge's avatar
Sebastian Dröge committed
86

87
    utils::set_state(&pipeline, gst::State::Playing)?;
88
89
90
91

    let bus = pipeline
        .get_bus()
        .expect("Pipeline without bus. Shouldn't happen!");
Sebastian Dröge's avatar
Sebastian Dröge committed
92
93

    loop {
94
95
        use gst::MessageView;

Sebastian Dröge's avatar
Sebastian Dröge committed
96
97
98
99
100
101
102
103
        let msg = match bus.timed_pop(u64::MAX) {
            None => break,
            Some(msg) => msg,
        };

        match msg.view() {
            MessageView::Eos(..) => break,
            MessageView::Error(err) => {
104
105
                utils::set_state(&pipeline, gst::State::Null)?;
                return Err(utils::ExampleError::ElementError(
Sebastian Dröge's avatar
Sebastian Dröge committed
106
107
                    msg.get_src().get_path_string(),
                    err.get_error(),
108
109
                    err.get_debug().unwrap(),
                ));
Sebastian Dröge's avatar
Sebastian Dröge committed
110
111
112
113
114
            }
            _ => (),
        }
    }

115
    utils::set_state(&pipeline, gst::State::Null)?;
116
117
118
119
120
121
122
123
124

    Ok(())
}

fn main() {
    match main_loop() {
        Ok(r) => r,
        Err(e) => eprintln!("Error! {}", e),
    }
Sebastian Dröge's avatar
Sebastian Dröge committed
125
}