Skip to content

src: Get video formats using Device Monitor#281

Merged
joaoantoniocardoso merged 5 commits into
mavlink:masterfrom
joaoantoniocardoso:use_gst_device_monitor
May 13, 2026
Merged

src: Get video formats using Device Monitor#281
joaoantoniocardoso merged 5 commits into
mavlink:masterfrom
joaoantoniocardoso:use_gst_device_monitor

Conversation

@joaoantoniocardoso

@joaoantoniocardoso joaoantoniocardoso commented Sep 4, 2023

Copy link
Copy Markdown
Collaborator

Merge after #607

update 13/05/26:

This PR is the first step towards supporting libcamera. In this step, we move from the v4l crate to give us the stream formats to get them from the GStreamer DeviceMonitor.

The further steps are already planned, and libcamera will be functional in the next PR.

With these changes, the v4l crate is only used for the controls API (which is fine).


update 09/29/25:

This seems very promising -- so far, I have already replaced the v4l formats and the v4l device discovery.

I'm thinking we should refactor the source/pipeline part of the application to fully make use of this Device Monitor:

  1. I still need to reason about the architecture, but I think we can safely say that at least we should split our "Pipelines" (v4l2_pipeline.rs, etc) into a source (pipeline: source -> capsfilter -> parser -> proxysink) + transcoding pipeline (pipeline: proxysrc -> video_tee -> rtp_payloader -> capsfilter -> rtp_tee, as well as the future optional decoder+encoder), which will then connect to our many sink (pipeline: proxysrc -> sink).
  2. Then we create a Device enum (w/ VideoSource and AudioSource variants) and a DeviceProvider trait, implemented by both this GSTDeviceMonitor and by the OnvifDiscovery, to give us a common interface.
  3. Each "gst::Device" is also an element factory provider, which allows you to create its source element with no effort, which will help us to more easily reach libcamera and audio support.

Helps #372, #273, #139, #79

Comment thread src/video/video_source_local.rs Outdated
@joaoantoniocardoso joaoantoniocardoso force-pushed the use_gst_device_monitor branch 2 times, most recently from 3639f6f to e25d761 Compare September 29, 2025 04:02
@joaoantoniocardoso joaoantoniocardoso force-pushed the use_gst_device_monitor branch 2 times, most recently from ab854c7 to 7bb361a Compare May 13, 2026 14:01
@joaoantoniocardoso joaoantoniocardoso marked this pull request as ready for review May 13, 2026 17:15
@patrickelectric

Copy link
Copy Markdown
Member

@joaoantoniocardoso can you rebase this PR ?

@joaoantoniocardoso joaoantoniocardoso merged commit 797996f into mavlink:master May 13, 2026
6 checks passed
@joaoantoniocardoso

joaoantoniocardoso commented May 13, 2026

Copy link
Copy Markdown
Collaborator Author

@patrickelectric oops, accidentally clicked to merge before review; Can you review it and I make a following PR to adjust any discrepancies?

@patrickelectric patrickelectric left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had no time to finish the review today. Will do the final commit tomorrow.

info!("GST Device Providers: {providers:#?}");

Ok(())
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just for curiosity, is there a reason for not having this in the default call of Manager ?

};

device.properties().iter().any(|s| {
let Ok(api) = s.get::<String>("device.api") else {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have a comment for this string:

# device.api is an inner string defined by gst for which api this device is accessed with: Ex: alsa, v4l..

It would be even better to have such strings as "device.path" to be defined as a global private property that explains that is a GST property string for this field

Comment on lines +728 to +732
let device = device_weak.upgrade()?;
let name = device.display_name().to_string();
let properties = device.properties()?;
let device_path = properties.get::<String>("device.path").ok()?;
let bus = properties.get::<String>("v4l2.device.bus_info").ok()?;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't it better to have abstraction for it under gst_device_monitor as the function device_caps ?

Comment thread src/lib/video/types.rs
Yuyv,
}

#[derive(Apiv2Schema, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit is unnecessary moving this structure.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm slowly moving things to get a top-to-bottom declaration, but if I added another commit, we'd have multiple commits touching the same lines.

Comment thread src/lib/stream/manager.rs
Comment on lines +160 to +171
for candidate in candidates.iter() {
let VideoSourceType::Local(camera) = candidate else {
continue;
};
if camera.name != source.name {
continue;
}
formats.insert(
candidate.inner().source_string().to_string(),
candidate.formats().await,
);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
for candidate in candidates.iter() {
let VideoSourceType::Local(camera) = candidate else {
continue;
};
if camera.name != source.name {
continue;
}
formats.insert(
candidate.inner().source_string().to_string(),
candidate.formats().await,
);
}
for candidate in candidates.iter().filter(|candidate| {
matches!(candidate, VideoSourceType::Local(camera) if camera.name == source.name)
}) {
formats.insert(
candidate.inner().source_string().to_string(),
candidate.formats().await,
);
}


fn get_device_formats_using_gstreamer(
device_path: &str,
_typ: &VideoSourceLocalType,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this necessary ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main idea is to use the DeviceMonitor's Device to interface the "local" kind of sources, and the previous approach to get formats was specific to v4l, so it wouldn't work for libcamerasrc or other sources.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants