Failing push buffers to appsrc

Hi!

I’ve been working with GStreamer to integrate it into my app, but I haven’t been able to resolve the issue with the (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION) error when trying to push buffers to GStreamer and then save them as a video file.

My code is in Rust, but it’s quite small, so I think you’ll be able to understand it. I’ve included a link to similar code in C for reference: StackOverflow

Here’s my code:

use gstreamer as gst;
use gstreamer::prelude::*;
use gstreamer::{Buffer, BufferRef, Caps, FlowReturn, Format};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    // Initialize GStreamer
    gst::init()?;

    // Create GStreamer elements
    let pipeline = gst::Pipeline::new();

    let appsrc = gst::ElementFactory::make_with_name("appsrc", Some("mysource"))
        .expect("Couldn't create appsrc element.");
    let videoconvert = gst::ElementFactory::make_with_name("videoconvert", Some("myconvert"))
        .expect("Couldn't create videoconvert element.");
    let x264enc = gst::ElementFactory::make_with_name("x264enc", Some("myencoder"))
        .expect("Couldn't create x264enc element.");
    let mp4mux = gst::ElementFactory::make_with_name("mp4mux", Some("mymux"))
        .expect("Couldn't create mp4mux element.");
    let filesink = gst::ElementFactory::make_with_name("filesink", Some("myfileoutput"))
        .expect("Couldn't create filesink element.");

    // Set the properties for filesink
    filesink.set_property_from_str("location", &"output.mp4");

    // Add elements to the pipeline
    pipeline.add_many(&[&appsrc, &videoconvert, &x264enc, &mp4mux, &filesink])?;

    // Link the elements
    appsrc.link(&videoconvert)?;
    videoconvert.link(&x264enc)?;
    x264enc.link(&mp4mux)?;
    mp4mux.link(&filesink)?;

    // Set the caps for appsrc
    let caps = Caps::builder("video/x-raw")
        .field("format", &"BGR")
        .field("width", &800)
        .field("height", &600)
        .field("framerate", &gstreamer::Fraction::new(30, 1))
        .build();
    appsrc.set_property("caps", &caps);
    appsrc.set_property("format", &Format::Time);

    // Set the pipeline to the playing state
    pipeline.set_state(gstreamer::State::Playing)?;

    // Push buffers into the appsrc
    for i in 0..10 {
        let mut buffer = Buffer::with_size(800 * 600 * 3).expect("Failed to allocate buffer");
        {
            let mut map = buffer.get_mut().unwrap().map_writable().expect("Failed to map buffer writable");
            assert_eq!(map.size(), 800 * 600 * 3);
            for byte in map.as_mut_slice().iter_mut() {
                *byte = (i % 255) as u8; // Filling with dummy data
            }
        }

        {
            let buffer_ref: &mut BufferRef = buffer.get_mut().unwrap();
            buffer_ref.set_pts(gstreamer::ClockTime::from_mseconds(30 * i));
            buffer_ref.set_dts(Some(gstreamer::ClockTime::from_mseconds(30 * i)));
            buffer_ref.set_duration(gstreamer::ClockTime::from_mseconds(33));
        }
        // appsrc.dynamic_cast::<gst::Element>().unwrap();
        let _ = appsrc.emit_by_name::<FlowReturn>("push-buffer", &[&buffer]);
    }

    // Signal the end of stream
    // let appsrc = appsrc.dynamic_cast::<gst::Element>().unwrap();
    let _ = appsrc.emit_by_name::<FlowReturn>("end-of-stream", &[&""]);

    // Wait for EOS or error
    let bus = pipeline.bus().unwrap();
    for msg in bus.iter_timed(gst::ClockTime::NONE) {
        use gstreamer::MessageView;
        match msg.view() {
            MessageView::Eos(..) => break,
            MessageView::Error(err) => {
                eprintln!(
                    "Error received from element {:?}: {}",
                    err.src().map(|s| s.path_string()),
                    err.error()
                );
                break;
            }
            _ => (),
        }
    }

    // Cleanup
    pipeline.set_state(gstreamer::State::Null)?;

    Ok(())
}

Logs looks like:

cargo run --bin frames
   Compiling GStreamer v0.1.0 (C:\Langs\Rust\GStreamer)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.26s                                                                     
     Running `target\debug\frames.exe`
error: process didn't exit successfully: `target\debug\frames.exe` (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)

I’m not sure if the issue lies in the Rust bindings or elsewhere. Any ideas on how to resolve this?

Thank you!