Hello,
I am trying to build streaming WebRTC plugin for Janus Gateway.
The Janus Gateway itself is written in C and I would like to write the plugin in Rust.
So, my Rust code is going to interact with C.
I need to work with RTP. I got a test stream generated with ffmpeg.
The whole idea is as follows:
ffmpeg writes stream to a socket -> the plugin reads from the socket -> the plugin relays a data to Janus Gateway which passes it to WebRTC peer.
The problem is that I need to edit the data before relaying it to C code.
I got C plugin which works just fine. It looks like:
typedef struct rtp_header
{
uint16_t version:2;
uint16_t padding:1;
uint16_t extension:1;
uint16_t csrccount:4;
uint16_t markerbit:1;
uint16_t type:7;
uint16_t seq_number;
uint32_t timestamp;
uint32_t ssrc;
uint32_t csrc[16];
} rtp_header;
char buffer[1500];
bytes = recvfrom(audio_fd, buffer, 1500, 0, (struct sockaddr*)&remote, &addrlen);
rtp_header *rtp = (rtp_header *)buffer;
rtp->type = 100; // this is an important thing to do
// Then I should just pass buffer to relay-function.
The important thing is that I should set type
before passing the data.
In C this is done pretty easy. We just treat the data as pointer to rtp_header
and manipulate with struct's fields whatever we like.
I wonder how could I do the same thing in Rust?
For now I've just managed to poll on socket and read from it
// polling ...
let mut buf: [u8; 1500] = [0; 1500];
let (number_of_bytes, src_addr) = socket.recv_from(&mut buf).expect("Didn't receive data");
So, now I can pass buf
to C relay-function but I don't understand how could I edit the content of buf
?
As you can see rtp_header
use bitfields. As I understand Rust doesn't support bitfields for structs.
I found bitfield crate which seems to solve the issue.
I created a struct describing an RTP header and tried to use it like:
bitfield!{
struct RtpHeader(MSB0 [u8]);
impl Debug;
u8;
get_version, _: 1, 0;
get_padding, _: 2, 2;
get_extension, _: 3, 3;
get_csrc, _: 7, 4;
get_marker, set_marker: 8, 8;
get_payload_type, set_payload_type: 15, 9;
}
...
let mut header = RtpHeader(buf);
header.set_payload_type(100);
but here another problem comes in.
buf
is an array with size of 1500. I don't remember exactly but I read somewhere that Rust has some kind of special behaviour for arrays with size less than 32.
I got an error
= note: the method `set_payload_type` exists but the following trait bounds were not satisfied:
`[u8; 1500] : std::convert::AsRef<[u8]>`
`[u8; 1500] : std::convert::AsMut<[u8]>`
What is the way to solve this issue in Rust?
How can I edit the content of buf
before passing it to C function?
Thank you.