Skip to content

Commit

Permalink
Checkpoint: working on RPI and PC
Browse files Browse the repository at this point in the history
  • Loading branch information
joaoantoniocardoso committed Sep 28, 2024
1 parent fef5cb3 commit 99fd8db
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 41 deletions.
8 changes: 5 additions & 3 deletions src/lib/stream/pipeline/fake_pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,11 @@ impl FakePipeline {
"videotestsrc pattern={pattern} is-live=true do-timestamp=true",
" ! timeoverlay",
" ! video/x-raw,format=I420",
" ! jpegenc quality=85 idct-method=1",
" ! capsfilter name={filter_name} caps=image/jpeg,width={width},height={height},framerate={interval_denominator}/{interval_numerator}",
" ! jpegenc quality=85 idct-method=fast",
" ! capsfilter name={filter_name} caps = \"image/jpeg, sof-marker=(int)0, width=(int){width}, height=(int){height}, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){interval_numerator}/{interval_denominator}, interlace-mode=(string)progressive, colorimetry=(string)bt601, chroma-site=(string)jpeg\"",
" ! tee name={video_tee_name} allow-not-linked=true",
" ! rtpjpegpay pt=96",
" ! rtpjpegpay pt=26",
" ! capsfilter caps = \"application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)JPEG, a-framerate=(string){framerate}, payload=(int)26\"",
" ! tee name={rtp_tee_name} allow-not-linked=true",
),
pattern = pattern,
Expand All @@ -134,6 +135,7 @@ impl FakePipeline {
filter_name = filter_name,
video_tee_name = video_tee_name,
rtp_tee_name = rtp_tee_name,
framerate = format!("{:.6}", configuration.frame_interval.numerator as f32 / configuration.frame_interval.denominator as f32),
)
}
unsupported => {
Expand Down
21 changes: 19 additions & 2 deletions src/lib/stream/pipeline/v4l_pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,30 @@ impl V4lPipeline {
rtp_tee_name = rtp_tee_name,
)
}
/*
clear; GST_DEBUG="*:3" gst-launch-1.0 -v \
v4l2src do-timestamp=true device=/dev/video6 \
! videoconvert \
! capsfilter caps="video/x-raw, width=(int)320, height=(int)320, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)I420, colorimetry=(string)bt601" \
! tee name=TeeVideo allow-not-linked=true \
TeeVideo. \
! queue leaky=downstream silent=true flush-on-eos=true max-size-buffers=0 \
! rtpvrawpay pt=96 \
! capsfilter caps = "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)RAW, sampling=(string)YCbCr-4:2:0, depth=(string)8, width=(string)320, height=(string)320, colorimetry=(string)BT601-5, payload=(int)96, a-framerate=(string)30" \
! tee name=TeeRTP allow-not-linked=true \
TeeRTP. \
! queue leaky=downstream silent=true flush-on-eos=true max-size-buffers=0 \
! multiudpsink clients=127.0.0.1:5600 sync=false
*/
VideoEncodeType::Yuyv => {
format!(
concat!(
"v4l2src device={device} do-timestamp=true",
" ! videoconvert",
" ! capsfilter name={filter_name} caps=video/x-raw,format=I420,width={width},height={height},framerate={interval_denominator}/{interval_numerator},colorimetry=bt601",
" ! capsfilter name={filter_name} caps=video/x-raw,format=I420,width={width},height={height},framerate={interval_denominator}/{interval_numerator},colorimetry=bt601,pixel-aspect-ratio=1/1,interlace-mode=progressive",
" ! tee name={video_tee_name} allow-not-linked=true",
" ! rtpvrawpay pt=96",
" ! capsfilter caps=\"application/x-rtp, clock-rate=(int)90000, encoding-name=(string)RAW, sampling=(string)YCbCr-4:2:0, depth=(string)8, width=(string){width}, height=(string){height}, colorimetry=(string)BT601-5, payload=(int)96, a-framerate=(string){framerate}\"",
" ! tee name={rtp_tee_name} allow-not-linked=true"
),
device = device,
Expand All @@ -91,6 +107,7 @@ impl V4lPipeline {
filter_name = filter_name,
video_tee_name = video_tee_name,
rtp_tee_name = rtp_tee_name,
framerate = (configuration.frame_interval.denominator as f32 / configuration.frame_interval.numerator as f32) as u32,
)
}
VideoEncodeType::Mjpg => {
Expand All @@ -100,7 +117,7 @@ impl V4lPipeline {
// We don't need a jpegparse, as it leads to incompatible caps, spoiling the negotiation.
" ! capsfilter name={filter_name} caps=image/jpeg,width={width},height={height},framerate={interval_denominator}/{interval_numerator}",
" ! tee name={video_tee_name} allow-not-linked=true",
" ! rtpjpegpay pt=96",
" ! rtpjpegpay pt=26",
" ! tee name={rtp_tee_name} allow-not-linked=true"
),
device = device,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/stream/rtsp/rtsp_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ impl RTSPServer {
" ! queue leaky=downstream flush-on-eos=true silent=true max-size-buffers=10",
" ! capsfilter caps={rtp_caps:?}",
" ! rtpjpegdepay",
" ! rtpjpegpay name=pay0 pt=96",
" ! rtpjpegpay name=pay0 pt=26",
),
socket_path = socket_path,
rtp_caps = rtp_caps,
Expand Down
75 changes: 40 additions & 35 deletions tests/v4l2_latency_and_jitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,12 @@ impl V4l2LoopBack {
VideoEncodeType::H264 => format!(
concat!(
"qrtimestampsrc do-timestamp=true",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, format=(string)RGB\"",
" ! videoconvert",
" ! video/x-raw,width={width},height={height},framerate={framerate_num}/{framerate_den},format=I420",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, format=(string)I420\"",
" ! x264enc tune=zerolatency speed-preset=ultrafast bitrate=5000",
" ! h264parse",
" ! video/x-h264,profile=constrained-baseline,stream-format=byte-stream,alignment=au",
" ! capsfilter caps=\"video/x-h264, profile=(string)constrained-baseline, stream-format=(string)byte-stream, alignment=(string)au\"",
" ! v4l2sink device={device_path} sync=false",
),
height = configuration.height,
Expand All @@ -85,10 +86,12 @@ impl V4l2LoopBack {
VideoEncodeType::Mjpg => format!(
concat!(
"qrtimestampsrc do-timestamp=true",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, format=(string)RGB\"",
" ! videoconvert",
" ! video/x-raw,width={width},height={height},framerate={framerate_num}/{framerate_den},format=I420",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, format=(string)I420\"",
" ! jpegenc quality=85 idct-method=ifast",
" ! jpegparse",
" ! capsfilter caps=\"image/jpeg, colorspace=(string)sYUV, sampling=(string)YCbCr-4:2:0, colorimetry=(string)bt601\"",
" ! v4l2sink device={device_path} sync=false",
),
height = configuration.height,
Expand All @@ -100,9 +103,11 @@ impl V4l2LoopBack {
VideoEncodeType::Yuyv => format!(
concat!(
"qrtimestampsrc do-timestamp=true",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, format=(string)RGB\"",
" ! videoconvert",
" ! video/x-raw,width={width},height={height},framerate={framerate_num}/{framerate_den},format=YUY2",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, format=(string)YUY2\"",
" ! rawvideoparse use-sink-caps=true",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)YUY2, colorimetry=(string)bt601\"",
" ! v4l2sink device={device_path} sync=false",
),
height = configuration.height,
Expand Down Expand Up @@ -178,52 +183,46 @@ impl QrTimeStampSink {
VideoEncodeType::H264 => format!(
concat!(
"{source_description}",
" ! application/x-rtp,payload=96",
" ! capsfilter caps=\"application/x-rtp, clock-rate=(int)90000, encoding-name=(string)H264, a-framerate=(string){framerate}, payload=(int)96\"",
" ! rtph264depay",
" ! h264parse",
" ! video/x-h264,width={width},height={height}",
" ! avdec_h264 discard-corrupted-frames=true",
" ! videoconvert",
" ! identity check-imperfect-timestamp=true check-imperfect-offset=true",
" ! qrtimestampsink name=qrsink sync=false",
),
source_description = source_description,
width = configuration.width,
height = configuration.height,
framerate = format!("{:.6}", configuration.frame_interval.denominator as f32 / configuration.frame_interval.numerator as f32),
),
VideoEncodeType::Mjpg => format!(
concat!(
"{source_description}",
" ! application/x-rtp,payload=96",
" ! capsfilter caps=\"application/x-rtp, clock-rate=(int)90000, encoding-name=(string)JPEG, a-framerate=(string){framerate}, payload=(int)26\"",
" ! rtpjpegdepay",
" ! image/jpeg,width={width},height={height}",
" ! jpegparse",
" ! jpegdec",
" ! videoconvert",
" ! identity check-imperfect-timestamp=true check-imperfect-offset=true",
" ! qrtimestampsink name=qrsink sync=false",
),
source_description = source_description,
width = configuration.width,
height = configuration.height,
framerate = format!("{:.6}", configuration.frame_interval.denominator as f32 / configuration.frame_interval.numerator as f32),
),
VideoEncodeType::Yuyv => format!(
concat!(
"{source_description}",
" ! capsfilter caps=\"application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)RAW, sampling=(string)YCbCr-4:2:0, depth=(string)8, width=(string)320, height=(string)320, colorimetry=(string)BT601-5, payload=(int)96, a-framerate=(string)30\"",
" ! capsfilter caps=\"application/x-rtp, clock-rate=(int)90000, encoding-name=(string)RAW, sampling=(string)YCbCr-4:2:0, depth=(string)8, width=(string){width}, height=(string){height}, colorimetry=(string)BT601-5, payload=(int)96, a-framerate=(string){framerate}\"",
" ! rtpvrawdepay",
" ! videorate skip-to-first=true silent=true",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)I420, colorimetry=(string)bt601\"",
// " ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)I420, colorimetry=(string)bt601\"",
" ! rawvideoparse use-sink-caps=true ",
" ! rawvideoparse width={width} height={height} framerate={framerate_num}/{framerate_den} format=i420 colorimetry=bt601 pixel-aspect-ratio=1/1 interlaced=false",
" ! videoconvert",
" ! identity check-imperfect-timestamp=true check-imperfect-offset=true",
" ! qrtimestampsink name=qrsink sync=false",
),
source_description = source_description,
width = configuration.width,
height = configuration.height,
framerate_num = configuration.frame_interval.denominator,
framerate_den = configuration.frame_interval.numerator,
framerate = format!("{:.6}", configuration.frame_interval.denominator as f32 / configuration.frame_interval.numerator as f32),
),
_ => unimplemented!(),
};
Expand Down Expand Up @@ -308,14 +307,15 @@ impl Baseline {
let pipeline_description = match configuration.encode {
VideoEncodeType::H264 => format!(
concat!(
// source
"qrtimestampsrc do-timestamp=true",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, format=(string)RGB\"",
" ! videoconvert",
" ! video/x-raw,width={width},height={height},framerate={framerate_num}/{framerate_den},format=I420",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, format=(string)I420\"",
" ! x264enc tune=zerolatency speed-preset=ultrafast bitrate=5000",
" ! h264parse",
" ! video/x-h264,profile=constrained-baseline,stream-format=byte-stream,alignment=au",
" ! h264parse",
" ! video/x-h264,width={width},height={height},framerate={framerate_num}/{framerate_den}",
" ! capsfilter caps=\"video/x-h264, profile=(string)constrained-baseline, stream-format=(string)byte-stream, alignment=(string)au\"",
// sink
" ! avdec_h264 discard-corrupted-frames=true",
" ! videoconvert",
" ! identity check-imperfect-timestamp=true check-imperfect-offset=true",
Expand All @@ -328,11 +328,14 @@ impl Baseline {
),
VideoEncodeType::Mjpg => format!(
concat!(
// source
"qrtimestampsrc do-timestamp=true",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, format=(string)RGB\"",
" ! videoconvert",
" ! video/x-raw,width={width},height={height},framerate={framerate_num}/{framerate_den},format=I420",
" ! capsfilter caps = \"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, format=(string)I420\"",
" ! jpegenc quality=85 idct-method=ifast",
" ! image/jpeg,width={width},height={height},framerate={framerate_num}/{framerate_den}",
" ! capsfilter caps = \"image/jpeg, interlace-mode=(string)progressive, colorimetry=(string)bt601, chroma-site=(string)jpeg\"",
// sink
" ! jpegdec",
" ! videoconvert",
" ! identity check-imperfect-timestamp=true check-imperfect-offset=true",
Expand All @@ -345,14 +348,16 @@ impl Baseline {
),
VideoEncodeType::Yuyv => format!(
concat!(
// source
"qrtimestampsrc do-timestamp=true",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, format=(string)RGB\"",
" ! videoconvert",
" ! video/x-raw,width={width},height={height},framerate={framerate_num}/{framerate_den},format=YUY2",
" ! rawvideoparse use-sink-caps=true ",
" ! videorate skip-to-first=true silent=true",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, format=(string)YUY2\"",
" ! rawvideoparse use-sink-caps=true disable-passthrough=true",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)YUY2, colorimetry=(string)bt601\"",
// sink
" ! rawvideoparse use-sink-caps=true disable-passthrough=true",
" ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, framerate=(fraction){framerate_num}/{framerate_den}, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)YUY2, colorimetry=(string)bt601\"",
// " ! capsfilter caps=\"video/x-raw, width=(int){width}, height=(int){height}, pixel-aspect-ratio=(fraction)1/1, interlace-mode=(string)progressive, format=(string)YUY2, colorimetry=(string)bt601\"",
" ! rawvideoparse use-sink-caps=true ",
" ! videoconvert",
" ! identity check-imperfect-timestamp=true check-imperfect-offset=true",
" ! qrtimestampsink name=qrsink sync=false",
Expand Down Expand Up @@ -563,23 +568,23 @@ async fn main() {
let buffers = 100;

let test_cases = [
(VideoEncodeType::H264, format!("udp://{address}:5600"), 5.),
(VideoEncodeType::Mjpg, format!("udp://{address}:5600"), 5.),
(VideoEncodeType::Yuyv, format!("udp://{address}:5600"), 8.),
(VideoEncodeType::H264, format!("udp://{address}:5600"), 30.),
(VideoEncodeType::Mjpg, format!("udp://{address}:5600"), 30.),
(VideoEncodeType::Yuyv, format!("udp://{address}:5600"), 30.),
(
VideoEncodeType::H264,
format!("rtsp://{address}:8554/test"),
5.,
30.,
),
(
VideoEncodeType::Mjpg,
format!("rtsp://{address}:8554/test"),
5.,
30.,
),
(
VideoEncodeType::Yuyv,
format!("rtsp://{address}:8554/test"),
8.,
30.,
),
];

Expand Down

0 comments on commit 99fd8db

Please sign in to comment.