Skip to content

Commit 8014d27

Browse files
committed
wip
1 parent c41b486 commit 8014d27

7 files changed

Lines changed: 87 additions & 41 deletions

File tree

media-video/capture/src/wayland/mod.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub use ashpd::{
1616
#[derive(Debug)]
1717
pub struct ScreenCaptureOptions {
1818
/// Embed the cursor in the video
19-
pub embed_cursor: bool,
19+
pub show_cursor: bool,
2020

2121
/// Which sources to captures
2222
pub source_types: BitFlags<SourceType>,
@@ -31,7 +31,7 @@ pub struct ScreenCaptureOptions {
3131
impl Default for ScreenCaptureOptions {
3232
fn default() -> Self {
3333
Self {
34-
embed_cursor: true,
34+
show_cursor: true,
3535
source_types: SourceType::all(),
3636
persist_mode: PersistMode::DoNot,
3737
pipewire: PipewireOptions::default(),
@@ -42,16 +42,30 @@ impl Default for ScreenCaptureOptions {
4242
#[derive(Debug, Clone)]
4343
pub struct PipewireOptions {
4444
/// Maximum framerate to negotiate in the pipewire stream
45+
///
46+
/// > Note: This does not guarantee that the framerate is exceeded and a proper frame limit can only be achieved by
47+
/// > blocking the frame callback.
4548
pub max_framerate: u32,
4649

50+
/// Set the supported pixel formats, only they will be negotiated
51+
pub pixel_formats: Vec<PixelFormat>,
52+
4753
/// Configure usage of DMA buffers
4854
pub dma_usage: Option<DmaUsageOptions>,
4955
}
5056

5157
impl Default for PipewireOptions {
5258
fn default() -> Self {
53-
Self {
59+
PipewireOptions {
5460
max_framerate: 30,
61+
pixel_formats: vec![
62+
PixelFormat::NV12,
63+
PixelFormat::I420,
64+
PixelFormat::RGBA(RgbaSwizzle::RGBA),
65+
PixelFormat::RGBA(RgbaSwizzle::BGRA),
66+
PixelFormat::RGBA(RgbaSwizzle::ARGB),
67+
PixelFormat::RGBA(RgbaSwizzle::ABGR),
68+
],
5569
dma_usage: None,
5670
}
5771
}
@@ -75,7 +89,7 @@ pub struct DmaUsageOptions {
7589
pub supported_modifier: Vec<u64>,
7690
}
7791

78-
#[derive(Debug)]
92+
#[derive(Debug, Clone, Copy)]
7993
pub enum PixelFormat {
8094
/// 2 Plane YUV with 4:2:0 subsampling
8195
NV12,
@@ -85,7 +99,7 @@ pub enum PixelFormat {
8599
RGBA(RgbaSwizzle),
86100
}
87101

88-
#[derive(Debug)]
102+
#[derive(Debug, Clone, Copy)]
89103
pub enum RgbaSwizzle {
90104
RGBA,
91105
BGRA,
@@ -181,6 +195,8 @@ impl StreamHandle {
181195

182196
#[derive(Debug, thiserror::Error)]
183197
pub enum StartCaptureError {
198+
#[error("Config contains an empty list of pixel formats")]
199+
NoPixelFormats,
184200
#[error(transparent)]
185201
DesktopPortal(#[from] ashpd::Error),
186202
#[error("no streams were selected")]
@@ -208,11 +224,15 @@ async fn start_screen_capture_boxed(
208224
options: ScreenCaptureOptions,
209225
on_frame: Box<dyn FnMut(CapturedFrame) -> bool + Send>,
210226
) -> Result<StreamHandle, StartCaptureError> {
227+
if options.pipewire.pixel_formats.is_empty() {
228+
return Err(StartCaptureError::NoPixelFormats);
229+
}
230+
211231
let proxy = Screencast::new().await?;
212232

213233
let session = proxy.create_session().await?;
214234

215-
let cursor_mode = if options.embed_cursor {
235+
let cursor_mode = if options.show_cursor {
216236
CursorMode::Embedded
217237
} else {
218238
CursorMode::Hidden

media-video/capture/src/wayland/stream.rs

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::wayland::{
22
CapturedDmaBuffer, CapturedDmaBufferSync, CapturedFrame, CapturedFrameBuffer,
3-
CapturedFrameFormat, PipewireOptions, RgbaSwizzle,
3+
CapturedFrameFormat, PipewireOptions, PixelFormat, RgbaSwizzle,
44
};
55
use pipewire::{
66
context::ContextRc,
@@ -52,6 +52,13 @@ struct UserStreamState {
5252
impl UserStreamState {
5353
fn handle_state_changed(&mut self, _stream: &Stream, old: StreamState, new: StreamState) {
5454
log::debug!("stream changed: {old:?} -> {new:?}");
55+
56+
if old == StreamState::Streaming
57+
&& matches!(new, StreamState::Unconnected | StreamState::Error(..))
58+
&& let Some(main_loop) = self.main_loop.upgrade()
59+
{
60+
main_loop.quit();
61+
}
5562
}
5663

5764
fn handle_param_changed(&mut self, stream: &Stream, id: u32, param: Option<&Pod>) {
@@ -543,15 +550,18 @@ fn build_stream(
543550

544551
// Add the format params with the video drm modifier property first if dma buffers are to be used
545552
if let Some(dma_usage) = options.dma_usage {
546-
let mut format_params = format_params(options.max_framerate);
553+
let mut format_params = format_params(&options.pixel_formats, options.max_framerate);
547554
format_params
548555
.properties
549556
.push(drm_modifier_property(&dma_usage.supported_modifier));
550557
connect_params.push(serialize_object(format_params));
551558
}
552559

553560
// Add format without video drm modifier property
554-
connect_params.push(serialize_object(format_params(options.max_framerate)));
561+
connect_params.push(serialize_object(format_params(
562+
&options.pixel_formats,
563+
options.max_framerate,
564+
)));
555565

556566
let mut connect_params: SmallVec<[&Pod; 2]> = connect_params
557567
.iter()
@@ -569,31 +579,44 @@ fn build_stream(
569579
}
570580

571581
/// Build the video format capabilities which will be used to negotiate a video stream with pipewire
572-
fn format_params(max_framerate: u32) -> Object {
582+
fn format_params(pixel_formats: &[PixelFormat], max_framerate: u32) -> Object {
583+
fn map(p: PixelFormat) -> &'static [VideoFormat] {
584+
match p {
585+
PixelFormat::NV12 => &[VideoFormat::NV12],
586+
PixelFormat::I420 => &[VideoFormat::I420],
587+
PixelFormat::RGBA(rgba_swizzle) => match rgba_swizzle {
588+
RgbaSwizzle::RGBA => &[VideoFormat::RGBA, VideoFormat::RGBx],
589+
RgbaSwizzle::BGRA => &[VideoFormat::BGRA, VideoFormat::BGRx],
590+
RgbaSwizzle::ARGB => &[VideoFormat::ARGB, VideoFormat::xRGB],
591+
RgbaSwizzle::ABGR => &[VideoFormat::ABGR, VideoFormat::xBGR],
592+
},
593+
}
594+
}
595+
596+
let video_formats = Value::Choice(ChoiceValue::Id(Choice(
597+
ChoiceFlags::empty(),
598+
ChoiceEnum::Enum {
599+
default: Id(map(pixel_formats[0])[0].0),
600+
alternatives: pixel_formats
601+
.iter()
602+
.flat_map(|p| map(*p).iter().copied())
603+
.map(|video_format| Id(video_format.as_raw()))
604+
.collect(),
605+
},
606+
)));
607+
608+
let video_formats_property = Property {
609+
key: FormatProperties::VideoFormat.as_raw(),
610+
flags: PropertyFlags::empty(),
611+
value: video_formats,
612+
};
613+
573614
object!(
574615
SpaTypes::ObjectParamFormat,
575616
ParamType::EnumFormat,
576617
property!(FormatProperties::MediaType, Id, MediaType::Video),
577618
property!(FormatProperties::MediaSubtype, Id, MediaSubtype::Raw),
578-
property!(
579-
FormatProperties::VideoFormat,
580-
Choice,
581-
Enum,
582-
Id,
583-
// Default
584-
VideoFormat::NV12,
585-
// Alternatives
586-
VideoFormat::NV12,
587-
VideoFormat::I420,
588-
VideoFormat::RGBA,
589-
VideoFormat::BGRA,
590-
VideoFormat::ARGB,
591-
VideoFormat::ABGR,
592-
VideoFormat::RGBx,
593-
VideoFormat::BGRx,
594-
VideoFormat::xRGB,
595-
VideoFormat::xBGR,
596-
),
619+
video_formats_property,
597620
property!(
598621
FormatProperties::VideoSize,
599622
Choice,

media-video/h264/tests/vaenc_pw_capture.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use capture::wayland::{
2-
BitFlag, CapturedFrameBuffer, PersistMode, PipewireOptions, ScreenCaptureOptions, SourceType,
2+
BitFlag, CapturedFrameBuffer, PersistMode, PipewireOptions, PixelFormat, RgbaSwizzle,
3+
ScreenCaptureOptions, SourceType,
34
};
45
use ezk_h264::{
56
Level, Profile,
@@ -30,11 +31,12 @@ async fn va_encode_memory_inner() {
3031
let (tx, mut rx) = mpsc::channel(8);
3132

3233
let options = ScreenCaptureOptions {
33-
embed_cursor: true,
34+
show_cursor: true,
3435
source_types: SourceType::all(),
3536
persist_mode: PersistMode::DoNot,
3637
pipewire: PipewireOptions {
3738
max_framerate: 30,
39+
pixel_formats: vec![PixelFormat::RGBA(RgbaSwizzle::BGRA)],
3840
dma_usage: None,
3941
},
4042
};

media-video/h264/tests/vkenc_pw_capture.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use capture::wayland::{
22
BitFlag, CapturedDmaBufferSync, CapturedFrameBuffer, CapturedFrameFormat, DmaUsageOptions,
3-
PersistMode, PipewireOptions, ScreenCaptureOptions, SourceType,
3+
PersistMode, PipewireOptions, PixelFormat, RgbaSwizzle, ScreenCaptureOptions, SourceType,
44
};
55
use ezk_h264::{
66
Level, Profile,
@@ -48,11 +48,12 @@ async fn vk_encode_dma_inner() {
4848
let (tx, mut rx) = mpsc::channel(8);
4949

5050
let options = ScreenCaptureOptions {
51-
embed_cursor: true,
51+
show_cursor: true,
5252
source_types: SourceType::all(),
5353
persist_mode: PersistMode::DoNot,
5454
pipewire: PipewireOptions {
5555
max_framerate: 30,
56+
pixel_formats: vec![PixelFormat::RGBA(RgbaSwizzle::BGRA)],
5657
dma_usage: Some(DmaUsageOptions {
5758
request_sync_obj: true,
5859
num_buffers: 16,
@@ -257,11 +258,12 @@ async fn vk_encode_memory_inner() {
257258
let (tx, mut rx) = mpsc::channel(8);
258259

259260
let options = ScreenCaptureOptions {
260-
embed_cursor: true,
261+
show_cursor: true,
261262
source_types: SourceType::all(),
262263
persist_mode: PersistMode::DoNot,
263264
pipewire: PipewireOptions {
264265
max_framerate: 30,
266+
pixel_formats: vec![PixelFormat::RGBA(RgbaSwizzle::BGRA)],
265267
dma_usage: None,
266268
},
267269
};

media-video/vulkan/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ license.workspace = true
77
repository.workspace = true
88

99
[dependencies]
10-
bitflags = "2"
1110
log = "0.4"
1211
ash = "0.38.0"
1312
naga = { version = "27", features = ["wgsl-in", "spv-out"] }
@@ -27,7 +26,6 @@ anyhow = "1"
2726

2827
[dev-dependencies]
2928
image = { version = "0.25", default-features = false, features = ["png"] }
30-
env_logger = "0.11"
3129

3230
[lints]
3331
workspace = true

media-video/vulkan/src/device.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,12 @@ impl Device {
121121
};
122122

123123
// Query all available queues families
124-
let queue_family_properties = vk_adapter
125-
.shared_instance()
126-
.raw_instance()
127-
.get_physical_device_queue_family_properties(vk_adapter.raw_physical_device());
124+
let queue_family_properties = dbg!(
125+
vk_adapter
126+
.shared_instance()
127+
.raw_instance()
128+
.get_physical_device_queue_family_properties(vk_adapter.raw_physical_device())
129+
);
128130

129131
let mut separate_encode_queue_family_index = None;
130132

media/rtp/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,3 @@ workspace = true
1414
bytes = "1"
1515
rtcp-types = "0.2"
1616
rtp-types = "0.1"
17-
thiserror = "2"

0 commit comments

Comments
 (0)