mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-06-06 15:38:58 +00:00
Add support for all other video formats
This commit is contained in:
parent
5022ff412c
commit
75eb959c80
2 changed files with 132 additions and 13 deletions
|
@ -101,12 +101,15 @@ pub enum NDIlib_recv_color_format_e {
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
pub enum NDIlib_FourCC_type_e {
|
pub enum NDIlib_FourCC_type_e {
|
||||||
NDIlib_FourCC_type_UYVY = 1_498_831_189,
|
NDIlib_FourCC_type_UYVY = 0x59_56_59_55,
|
||||||
NDIlib_FourCC_type_BGRA = 1_095_911_234,
|
NDIlib_FourCC_type_YV12 = 0x32_31_56_59,
|
||||||
NDIlib_FourCC_type_BGRX = 1_481_787_202,
|
NDIlib_FourCC_type_NV12 = 0x32_31_56_4e,
|
||||||
NDIlib_FourCC_type_RGBA = 1_094_862_674,
|
NDIlib_FourCC_type_I420 = 0x30_32_34_49,
|
||||||
NDIlib_FourCC_type_RGBX = 1_480_738_642,
|
NDIlib_FourCC_type_BGRA = 0x41_52_47_42,
|
||||||
NDIlib_FourCC_type_UYVA = 1_096_178_005,
|
NDIlib_FourCC_type_BGRX = 0x58_52_47_42,
|
||||||
|
NDIlib_FourCC_type_RGBA = 0x41_42_47_52,
|
||||||
|
NDIlib_FourCC_type_RGBX = 0x58_42_47_52,
|
||||||
|
NDIlib_FourCC_type_UYVA = 0x41_56_56_55,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
|
|
|
@ -126,10 +126,14 @@ impl ObjectSubclass for NdiVideoSrc {
|
||||||
(
|
(
|
||||||
"format",
|
"format",
|
||||||
&gst::List::new(&[
|
&gst::List::new(&[
|
||||||
//TODO add all formats
|
|
||||||
&gst_video::VideoFormat::Uyvy.to_string(),
|
&gst_video::VideoFormat::Uyvy.to_string(),
|
||||||
//&gst_video::VideoFormat::Rgb.to_string(),
|
&gst_video::VideoFormat::Yv12.to_string(),
|
||||||
//&gst_video::VideoFormat::Gray8.to_string(),
|
&gst_video::VideoFormat::Nv12.to_string(),
|
||||||
|
&gst_video::VideoFormat::I420.to_string(),
|
||||||
|
&gst_video::VideoFormat::Bgra.to_string(),
|
||||||
|
&gst_video::VideoFormat::Bgrx.to_string(),
|
||||||
|
&gst_video::VideoFormat::Rgba.to_string(),
|
||||||
|
&gst_video::VideoFormat::Rgbx.to_string(),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
("width", &gst::IntRange::<i32>::new(0, i32::MAX)),
|
("width", &gst::IntRange::<i32>::new(0, i32::MAX)),
|
||||||
|
@ -375,11 +379,24 @@ impl BaseSrcImpl for NdiVideoSrc {
|
||||||
video_frame
|
video_frame
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// YV12 and I420 are swapped in the NDI SDK compared to GStreamer
|
||||||
|
let format = match video_frame.fourcc() {
|
||||||
|
ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_UYVY => gst_video::VideoFormat::Uyvy,
|
||||||
|
ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_YV12 => gst_video::VideoFormat::I420,
|
||||||
|
ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_NV12 => gst_video::VideoFormat::Nv12,
|
||||||
|
ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_I420 => gst_video::VideoFormat::Yv12,
|
||||||
|
ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_BGRA => gst_video::VideoFormat::Bgra,
|
||||||
|
ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_BGRX => gst_video::VideoFormat::Bgrx,
|
||||||
|
ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_RGBA => gst_video::VideoFormat::Rgba,
|
||||||
|
ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_RGBX => gst_video::VideoFormat::Rgbx,
|
||||||
|
ndisys::NDIlib_FourCC_type_e::NDIlib_FourCC_type_UYVA => gst_video::VideoFormat::Uyvy,
|
||||||
|
};
|
||||||
|
|
||||||
let par = gst::Fraction::approximate_f32(video_frame.picture_aspect_ratio()).unwrap() *
|
let par = gst::Fraction::approximate_f32(video_frame.picture_aspect_ratio()).unwrap() *
|
||||||
gst::Fraction::new(video_frame.yres(), video_frame.xres());
|
gst::Fraction::new(video_frame.yres(), video_frame.xres());
|
||||||
|
|
||||||
let info = gst_video::VideoInfo::new(
|
let info = gst_video::VideoInfo::new(
|
||||||
gst_video::VideoFormat::Uyvy,
|
format,
|
||||||
video_frame.xres() as u32,
|
video_frame.xres() as u32,
|
||||||
video_frame.yres() as u32,
|
video_frame.yres() as u32,
|
||||||
)
|
)
|
||||||
|
@ -415,11 +432,110 @@ impl BaseSrcImpl for NdiVideoSrc {
|
||||||
let buffer = buffer.get_mut().unwrap();
|
let buffer = buffer.get_mut().unwrap();
|
||||||
buffer.set_pts(pts);
|
buffer.set_pts(pts);
|
||||||
buffer.set_duration(duration);
|
buffer.set_duration(duration);
|
||||||
|
|
||||||
// FIXME: This assumes that the strides match up
|
|
||||||
buffer.copy_from_slice(0, video_frame.data()).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let buffer = {
|
||||||
|
let mut vframe = gst_video::VideoFrame::from_buffer_writable(buffer, &state.info.as_ref().unwrap()).unwrap();
|
||||||
|
|
||||||
|
match format {
|
||||||
|
gst_video::VideoFormat::Uyvy |
|
||||||
|
gst_video::VideoFormat::Bgra |
|
||||||
|
gst_video::VideoFormat::Bgrx |
|
||||||
|
gst_video::VideoFormat::Rgba |
|
||||||
|
gst_video::VideoFormat::Rgbx => {
|
||||||
|
let line_bytes = if format == gst_video::VideoFormat::Uyvy {
|
||||||
|
2 * vframe.width() as usize
|
||||||
|
} else {
|
||||||
|
4 * vframe.width() as usize
|
||||||
|
};
|
||||||
|
let dest_stride = vframe.plane_stride()[0] as usize;
|
||||||
|
let dest = vframe.plane_data_mut(0).unwrap();
|
||||||
|
let src_stride = video_frame.line_stride_in_bytes() as usize;
|
||||||
|
let src = video_frame.data();
|
||||||
|
|
||||||
|
for (dest, src) in dest.chunks_exact_mut(dest_stride).zip(src.chunks_exact(src_stride)) {
|
||||||
|
dest.copy_from_slice(src);
|
||||||
|
dest.copy_from_slice(&src[..line_bytes]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
gst_video::VideoFormat::Nv12 => {
|
||||||
|
// First plane
|
||||||
|
{
|
||||||
|
let line_bytes = vframe.width() as usize;
|
||||||
|
let dest_stride = vframe.plane_stride()[0] as usize;
|
||||||
|
let dest = vframe.plane_data_mut(0).unwrap();
|
||||||
|
let src_stride = video_frame.line_stride_in_bytes() as usize;
|
||||||
|
let src = video_frame.data();
|
||||||
|
|
||||||
|
for (dest, src) in dest.chunks_exact_mut(dest_stride).zip(src.chunks_exact(src_stride)) {
|
||||||
|
dest.copy_from_slice(&src[..line_bytes]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second plane
|
||||||
|
{
|
||||||
|
let line_bytes = vframe.width() as usize;
|
||||||
|
let dest_stride = vframe.plane_stride()[1] as usize;
|
||||||
|
let dest = vframe.plane_data_mut(1).unwrap();
|
||||||
|
let src_stride = video_frame.line_stride_in_bytes() as usize;
|
||||||
|
let src = &video_frame.data()[(video_frame.yres() as usize * src_stride)..];
|
||||||
|
|
||||||
|
for (dest, src) in dest.chunks_exact_mut(dest_stride).zip(src.chunks_exact(src_stride)) {
|
||||||
|
dest.copy_from_slice(&src[..line_bytes]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
gst_video::VideoFormat::Yv12 |
|
||||||
|
gst_video::VideoFormat::I420 => {
|
||||||
|
// First plane
|
||||||
|
{
|
||||||
|
let line_bytes = vframe.width() as usize;
|
||||||
|
let dest_stride = vframe.plane_stride()[0] as usize;
|
||||||
|
let dest = vframe.plane_data_mut(0).unwrap();
|
||||||
|
let src_stride = video_frame.line_stride_in_bytes() as usize;
|
||||||
|
let src = video_frame.data();
|
||||||
|
|
||||||
|
for (dest, src) in dest.chunks_exact_mut(dest_stride).zip(src.chunks_exact(src_stride)) {
|
||||||
|
dest.copy_from_slice(&src[..line_bytes]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second plane
|
||||||
|
{
|
||||||
|
let line_bytes = (vframe.width() as usize + 1) / 2;
|
||||||
|
let dest_stride = vframe.plane_stride()[1] as usize;
|
||||||
|
let dest = vframe.plane_data_mut(1).unwrap();
|
||||||
|
let src_stride = video_frame.line_stride_in_bytes() as usize;
|
||||||
|
let src_stride1 = video_frame.line_stride_in_bytes() as usize / 2;
|
||||||
|
let src = &video_frame.data()[(video_frame.yres() as usize * src_stride)..];
|
||||||
|
|
||||||
|
for (dest, src) in dest.chunks_exact_mut(dest_stride).zip(src.chunks_exact(src_stride1)) {
|
||||||
|
dest.copy_from_slice(&src[..line_bytes]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Third plane
|
||||||
|
{
|
||||||
|
let line_bytes = (vframe.width() as usize + 1) / 2;
|
||||||
|
let dest_stride = vframe.plane_stride()[2] as usize;
|
||||||
|
let dest = vframe.plane_data_mut(2).unwrap();
|
||||||
|
let src_stride = video_frame.line_stride_in_bytes() as usize;
|
||||||
|
let src_stride1 = video_frame.line_stride_in_bytes() as usize / 2;
|
||||||
|
let src = &video_frame.data()[(video_frame.yres() as usize * src_stride +
|
||||||
|
(video_frame.yres() as usize + 1) / 2 * src_stride1)..];
|
||||||
|
|
||||||
|
for (dest, src) in dest.chunks_exact_mut(dest_stride).zip(src.chunks_exact(src_stride1)) {
|
||||||
|
dest.copy_from_slice(&src[..line_bytes]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
vframe.into_buffer()
|
||||||
|
};
|
||||||
|
|
||||||
gst_log!(self.cat, obj: element, "Produced buffer {:?}", buffer);
|
gst_log!(self.cat, obj: element, "Produced buffer {:?}", buffer);
|
||||||
|
|
||||||
Ok(buffer)
|
Ok(buffer)
|
||||||
|
|
Loading…
Reference in a new issue