From 6bf19ba35362b10a90a405eb369aadd60cc568ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Ant=C3=B4nio=20Cardoso?= Date: Wed, 9 Aug 2023 18:16:23 -0300 Subject: [PATCH] src: stream, video: Update code to use the generic Raw --- src/stream/pipeline/fake_pipeline.rs | 21 +++-- src/stream/pipeline/v4l_pipeline.rs | 15 +++- src/stream/sink/image_sink.rs | 2 +- src/video/video_source_gst.rs | 4 +- src/video/video_source_local.rs | 117 +++++++++++++++++++++++---- 5 files changed, 132 insertions(+), 27 deletions(-) diff --git a/src/stream/pipeline/fake_pipeline.rs b/src/stream/pipeline/fake_pipeline.rs index 8928a654..701892ab 100644 --- a/src/stream/pipeline/fake_pipeline.rs +++ b/src/stream/pipeline/fake_pipeline.rs @@ -1,5 +1,8 @@ use crate::{ - stream::types::CaptureConfiguration, + stream::{ + pipeline::{DEFAULT_RAW_FORMAT, KNOWN_RTP_RAW_FORMATS}, + types::CaptureConfiguration, + }, video::{ types::{VideoEncodeType, VideoSourceType}, video_source_gst::VideoSourceGstType, @@ -70,7 +73,7 @@ impl FakePipeline { format!(concat!( "videotestsrc pattern={pattern} is-live=true do-timestamp=true", " ! timeoverlay", - " ! video/x-raw,format=I420", + " ! video/x-raw,format={format}", " ! x264enc tune=zerolatency speed-preset=ultrafast bitrate=5000", " ! h264parse", " ! capsfilter name={filter_name} caps=video/x-h264,profile={profile},stream-format=avc,alignment=au,width={width},height={height},framerate={interval_denominator}/{interval_numerator}", @@ -78,6 +81,7 @@ impl FakePipeline { " ! tee name={sink_tee_name} allow-not-linked=true" ), pattern = pattern, + format = DEFAULT_RAW_FORMAT, profile = "constrained-baseline", width = configuration.width, height = configuration.height, @@ -87,7 +91,12 @@ impl FakePipeline { sink_tee_name = sink_tee_name, ) } - VideoEncodeType::Yuyv => { + VideoEncodeType::Raw(fourcc) => { + let mut fourcc = fourcc.clone(); + if !KNOWN_RTP_RAW_FORMATS.contains(&fourcc.as_str()) { + fourcc = DEFAULT_RAW_FORMAT.to_string(); + } + format!( concat!( // Because application-rtp templates doesn't accept "YUY2", we @@ -95,12 +104,13 @@ impl FakePipeline { // format available ("UYVY"). "videotestsrc pattern={pattern} is-live=true do-timestamp=true", " ! timeoverlay", - " ! video/x-raw,format=I420", " ! capsfilter name={filter_name} caps=video/x-raw,format=I420,width={width},height={height},framerate={interval_denominator}/{interval_numerator}", + " ! capsfilter name={filter_name} caps=video/x-raw,format={format},width={width},height={height},framerate={interval_denominator}/{interval_numerator}", " ! rtpvrawpay pt=96", " ! tee name={sink_tee_name} allow-not-linked=true", ), pattern = pattern, + format = fourcc, width = configuration.width, height = configuration.height, interval_denominator = configuration.frame_interval.denominator, @@ -114,13 +124,14 @@ impl FakePipeline { concat!( "videotestsrc pattern={pattern} is-live=true do-timestamp=true", " ! timeoverlay", - " ! video/x-raw,format=I420", + " ! video/x-raw,format={format}", " ! jpegenc quality=85 idct-method=1", " ! capsfilter name={filter_name} caps=image/jpeg,width={width},height={height},framerate={interval_denominator}/{interval_numerator}", " ! rtpjpegpay pt=96", " ! tee name={sink_tee_name} allow-not-linked=true", ), pattern = pattern, + format = DEFAULT_RAW_FORMAT, width = configuration.width, height = configuration.height, interval_denominator = configuration.frame_interval.denominator, diff --git a/src/stream/pipeline/v4l_pipeline.rs b/src/stream/pipeline/v4l_pipeline.rs index 465279fe..6062ba36 100644 --- a/src/stream/pipeline/v4l_pipeline.rs +++ b/src/stream/pipeline/v4l_pipeline.rs @@ -1,5 +1,8 @@ use crate::{ - stream::types::CaptureConfiguration, + stream::{ + pipeline::{DEFAULT_RAW_FORMAT, KNOWN_RTP_RAW_FORMATS}, + types::CaptureConfiguration, + }, video::types::{VideoEncodeType, VideoSourceType}, video_stream::types::VideoAndStreamInformation, }; @@ -69,16 +72,22 @@ impl V4lPipeline { sink_tee_name = sink_tee_name, ) } - VideoEncodeType::Yuyv => { + VideoEncodeType::Raw(fourcc) => { + let mut fourcc = fourcc.clone(); + if !KNOWN_RTP_RAW_FORMATS.contains(&fourcc.as_str()) { + fourcc = DEFAULT_RAW_FORMAT.to_string(); + } + format!( concat!( "v4l2src device={device} do-timestamp=false", " ! videoconvert", - " ! capsfilter name={filter_name} caps=video/x-raw,format=I420,width={width},height={height},framerate={interval_denominator}/{interval_numerator}", + " ! capsfilter name={filter_name} caps=video/x-raw,format={format},width={width},height={height},framerate={interval_denominator}/{interval_numerator}", " ! rtpvrawpay pt=96", " ! tee name={sink_tee_name} allow-not-linked=true" ), device = device, + format = fourcc, width = width, height = height, interval_denominator = interval_denominator, diff --git a/src/stream/sink/image_sink.rs b/src/stream/sink/image_sink.rs index 3b9adacb..91d8d013 100644 --- a/src/stream/sink/image_sink.rs +++ b/src/stream/sink/image_sink.rs @@ -356,7 +356,7 @@ impl ImageSink { _transcoding_elements.push(parser); _transcoding_elements.push(decoder); } - VideoEncodeType::Yuyv => { + VideoEncodeType::Raw(_) => { let depayloader = gst::ElementFactory::make("rtpvrawdepay").build()?; _transcoding_elements.push(depayloader); } diff --git a/src/video/video_source_gst.rs b/src/video/video_source_gst.rs index 63823db2..ec565345 100644 --- a/src/video/video_source_gst.rs +++ b/src/video/video_source_gst.rs @@ -1,3 +1,5 @@ +use crate::stream::pipeline::DEFAULT_RAW_FORMAT; + use super::types::*; use super::video_source::{VideoSource, VideoSourceAvailable}; use super::video_source_local::VideoSourceLocal; @@ -66,7 +68,7 @@ impl VideoSource for VideoSourceGst { sizes: sizes.clone(), }, Format { - encode: VideoEncodeType::Yuyv, + encode: VideoEncodeType::Raw(DEFAULT_RAW_FORMAT.to_string()), sizes: sizes.clone(), }, Format { diff --git a/src/video/video_source_local.rs b/src/video/video_source_local.rs index 1aea91bc..09413d70 100644 --- a/src/video/video_source_local.rs +++ b/src/video/video_source_local.rs @@ -698,7 +698,10 @@ mod tests { mod device_identification_tests { use super::*; use crate::{ - stream::types::{CaptureConfiguration, StreamInformation}, + stream::{ + pipeline::DEFAULT_RAW_FORMAT, + types::{CaptureConfiguration, StreamInformation}, + }, video_stream::types::VideoAndStreamInformation, }; use VideoEncodeType::*; @@ -777,11 +780,26 @@ mod device_identification_tests { let candidates = vec![ add_available_camera("A", "/dev/video0", "usb_port_0", vec![H264]), - add_available_camera("A", "/dev/video1", "usb_port_0", vec![Yuyv, Mjpg]), + add_available_camera( + "A", + "/dev/video1", + "usb_port_0", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), add_available_camera("A", "/dev/video2", "usb_port_1", vec![H264]), - add_available_camera("A", "/dev/video3", "usb_port_1", vec![Yuyv, Mjpg]), + add_available_camera( + "A", + "/dev/video3", + "usb_port_1", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), add_available_camera("B", "/dev/video4", "usb_port_2", vec![H264]), - add_available_camera("B", "/dev/video5", "usb_port_2", vec![Yuyv, Mjpg]), + add_available_camera( + "B", + "/dev/video5", + "usb_port_2", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), ]; let same_name_candidates = VideoSourceLocal::get_cameras_with_same_name(&candidates, "A"); @@ -798,8 +816,18 @@ mod device_identification_tests { let candidates = vec![ add_available_camera("A", "/dev/video0", "usb_port_0", vec![H264]), add_available_camera("B", "/dev/video1", "usb_port_1", vec![H264]), - add_available_camera("C", "/dev/video2", "usb_port_0", vec![Yuyv, Mjpg]), - add_available_camera("D", "/dev/video3", "usb_port_1", vec![Yuyv, Mjpg]), + add_available_camera( + "C", + "/dev/video2", + "usb_port_0", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), + add_available_camera( + "D", + "/dev/video3", + "usb_port_1", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), ]; let same_encode_candidates = @@ -816,9 +844,19 @@ mod device_identification_tests { let candidates = vec![ add_available_camera("A", "/dev/video0", "usb_port_0", vec![H264]), - add_available_camera("B", "/dev/video1", "usb_port_0", vec![Yuyv, Mjpg]), + add_available_camera( + "B", + "/dev/video1", + "usb_port_0", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), add_available_camera("C", "/dev/video2", "usb_port_1", vec![H264]), - add_available_camera("D", "/dev/video3", "usb_port_1", vec![Yuyv, Mjpg]), + add_available_camera( + "D", + "/dev/video3", + "usb_port_1", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), ]; let same_encode_candidates = VideoSourceLocal::get_cameras_with_same_bus( @@ -838,10 +876,25 @@ mod device_identification_tests { let candidates = vec![ add_available_camera("A", "/dev/video0", "usb_port_0", vec![H264]), - add_available_camera("A", "/dev/video1", "usb_port_0", vec![Yuyv, Mjpg]), + add_available_camera( + "A", + "/dev/video1", + "usb_port_0", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), add_available_camera("B", "/dev/video2", "usb_port_1", vec![H264]), - add_available_camera("B", "/dev/video3", "usb_port_1", vec![Yuyv, Mjpg]), - add_available_camera("C", "/dev/video3", "usb_port_1", vec![H264, Yuyv, Mjpg]), + add_available_camera( + "B", + "/dev/video3", + "usb_port_1", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), + add_available_camera( + "C", + "/dev/video3", + "usb_port_1", + vec![H264, Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), ]; let stream = create_stream("A", "/dev/video0", "usb_port_0", H264); let (VideoSourceType::Local(source), CaptureConfiguration::Video(capture_configuration)) = (&stream.video_source, &stream.stream_information.configuration) else { @@ -878,9 +931,19 @@ mod device_identification_tests { let candidates = vec![ add_available_camera("A", "/dev/video0", current_usb_bus, vec![H264]), - add_available_camera("A", "/dev/video1", current_usb_bus, vec![Yuyv, Mjpg]), + add_available_camera( + "A", + "/dev/video1", + current_usb_bus, + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), add_available_camera("B", "/dev/video2", "usb_port_3", vec![H264]), - add_available_camera("B", "/dev/video3", "usb_port_3", vec![Yuyv, Mjpg]), + add_available_camera( + "B", + "/dev/video3", + "usb_port_3", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), ]; for n in (0..3).collect::>() { @@ -922,8 +985,18 @@ mod device_identification_tests { let candidates = vec![ add_available_camera("A", current_path, "usb_port_0", vec![H264]), add_available_camera("A", last_path, "usb_port_1", vec![H264]), - add_available_camera("A", "/dev/video3", "usb_port_0", vec![Yuyv, Mjpg]), - add_available_camera("A", "/dev/video5", "usb_port_1", vec![Yuyv, Mjpg]), + add_available_camera( + "A", + "/dev/video3", + "usb_port_0", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), + add_available_camera( + "A", + "/dev/video5", + "usb_port_1", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), ]; for n in (0..=1).collect::>() { @@ -957,9 +1030,19 @@ mod device_identification_tests { let candidates = vec![ add_available_camera("A", "/dev/video0", current_usb_bus, vec![H264]), - add_available_camera("A", "/dev/video1", current_usb_bus, vec![Yuyv, Mjpg]), + add_available_camera( + "A", + "/dev/video1", + current_usb_bus, + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), add_available_camera("A", "/dev/video4", "usb_port_2", vec![H264]), - add_available_camera("A", "/dev/video5", "usb_port_2", vec![Yuyv, Mjpg]), + add_available_camera( + "A", + "/dev/video5", + "usb_port_2", + vec![Raw(DEFAULT_RAW_FORMAT.to_string()), Mjpg], + ), ]; for n in (0..5).collect::>() {