mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-01-08 10:15:29 +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)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum NDIlib_FourCC_type_e {
|
||||
NDIlib_FourCC_type_UYVY = 1_498_831_189,
|
||||
NDIlib_FourCC_type_BGRA = 1_095_911_234,
|
||||
NDIlib_FourCC_type_BGRX = 1_481_787_202,
|
||||
NDIlib_FourCC_type_RGBA = 1_094_862_674,
|
||||
NDIlib_FourCC_type_RGBX = 1_480_738_642,
|
||||
NDIlib_FourCC_type_UYVA = 1_096_178_005,
|
||||
NDIlib_FourCC_type_UYVY = 0x59_56_59_55,
|
||||
NDIlib_FourCC_type_YV12 = 0x32_31_56_59,
|
||||
NDIlib_FourCC_type_NV12 = 0x32_31_56_4e,
|
||||
NDIlib_FourCC_type_I420 = 0x30_32_34_49,
|
||||
NDIlib_FourCC_type_BGRA = 0x41_52_47_42,
|
||||
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)]
|
||||
|
|
|
@ -126,10 +126,14 @@ impl ObjectSubclass for NdiVideoSrc {
|
|||
(
|
||||
"format",
|
||||
&gst::List::new(&[
|
||||
//TODO add all formats
|
||||
&gst_video::VideoFormat::Uyvy.to_string(),
|
||||
//&gst_video::VideoFormat::Rgb.to_string(),
|
||||
//&gst_video::VideoFormat::Gray8.to_string(),
|
||||
&gst_video::VideoFormat::Yv12.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)),
|
||||
|
@ -375,11 +379,24 @@ impl BaseSrcImpl for NdiVideoSrc {
|
|||
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() *
|
||||
gst::Fraction::new(video_frame.yres(), video_frame.xres());
|
||||
|
||||
let info = gst_video::VideoInfo::new(
|
||||
gst_video::VideoFormat::Uyvy,
|
||||
format,
|
||||
video_frame.xres() as u32,
|
||||
video_frame.yres() as u32,
|
||||
)
|
||||
|
@ -415,11 +432,110 @@ impl BaseSrcImpl for NdiVideoSrc {
|
|||
let buffer = buffer.get_mut().unwrap();
|
||||
buffer.set_pts(pts);
|
||||
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);
|
||||
|
||||
Ok(buffer)
|
||||
|
|
Loading…
Reference in a new issue