Display h264 stream received via usb using gstreamer

Hello all,

I am very new to gstreamer, so sorry if I ask dumb questions or don’t use the correct terms.
What I want is to receive a h.264 stream from a usb device and display it (using rust).
I am already able to do the usb stuff and now have the stream in single NAL-units. When I write these into a file, I am able to open and view it.

I found the topic by min, but I think my usecase is a bit different.
If I understand gstreamer correctly, I need a quite similar pipeline as min(maybe sth easier such as {appsrc} - {decodebin} - {autovideosink} would also work?)
But my problem is, that I don’t have a file (and therefore a complete stream) that I can iter of BufRead on.
I receive NAL-units via usb and then currently store them in a Buffer (VecDeque<Vec<u8>>)

In my appsrc-Callback I now would like to do sth like

let buffer = gstreamer::Buffer::from_slice(recv_buffer.pop_front().as_slice());
let _ = appsrc.push_buffer(buffer);

However, I don’t really understand how to do this correcly (the slices aparently have to live for 'static?
I assume this can not be the correct way, because wouldn’t it create memory leaks to store the stream content statically?
Can I maybe instead of using the buffer-VecDeque and appsrc callbacks somehow directly push the received data into a (gst)buffer?

Thanks for your help and have a great new year,
Konrad

Use

let buffer = gstreamer::Buffer::from_mut_slice(recv_buffer.pop_front());
let _ = appsrc.push_buffer(buffer);

It can be created around anything that implements AsRef<[u8]> or AsMut<[u8]>, and Vec<u8> does both.

Make sure to configure the correct caps on your appsrc, you probably want video/x-h264,stream-format=byte-stream,alignment=nal in your case.


If a type T: 'static this only means that it must not contain any references to non-'static memory, e.g. not references to any stack memory. Most types are 'static, and e.g. Vec<u8> is. Examples for types that are not 'static are things like &T, Mutex guards, RefCell borrows, etc.

Thanks for the quick reply! I will try that later.
So, due to T: 'static, I assume there is no good way to receive the data in another thread than the one displaying it? Because MutexGuard is, as you said, not 'static, and also things like channels can’t be used for this use-case, I think?

You’re getting a Vec<u8> out of your channel, so that’s 'static and can be wrapped in a gst::Buffer just fine. I’m not sure I understand your problem :slight_smile: You’ll have to provide more context/code.

I tried your suggestions and now am able to run and show the video stream using my program. Thanks:)

In the last question, I considered populating the Buffer using a thread different from the thread in which gst runs.
So, instead of having one thread that runs my gst pipeline and also does the usb communication (populating the Vec<u8> with the received nal units), I would like to do the usb communication in a seperate thread, mainly for performance reasons. I think using appsrc, this would need a thread-safe alternative for my Vec<u8> that is ' static(which seems impossible for me, right?).

If I wanted to seperate gst and usb communication into 2 threads, I could also go with using a UdpSocket (Sender) and udpsrc. Is there a good way to used shared memory?

Vec<u8> is thread-safe (it’s Send and Sync), as is gst::Buffer.

Use an appsrc, then you get shared memory for free easily. If you want to do things complicated then you could use an UNIX domain socket and send memfds over them, for example, but if it’s all in the same process this is all not worth it.

Okay, I will stick to using an appsrc then.
I think, I also got the multithreaded scenario working.

Thanks for your help!

1 Like