Skip to content

Commit e893cb6

Browse files
committed
feat: add QOIZ image codec
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
1 parent c07211d commit e893cb6

File tree

13 files changed

+225
-29
lines changed

13 files changed

+225
-29
lines changed

Cargo.lock

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ironrdp-client/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ default = ["rustls"]
2828
rustls = ["ironrdp-tls/rustls"]
2929
native-tls = ["ironrdp-tls/native-tls"]
3030
qoi = ["ironrdp/qoi"]
31+
qoiz = ["ironrdp/qoiz"]
3132

3233
[dependencies]
3334
# Protocols

crates/ironrdp-connector/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ test = false
1919
default = []
2020
arbitrary = ["dep:arbitrary"]
2121
qoi = ["ironrdp-pdu/qoi"]
22+
qoiz = ["ironrdp-pdu/qoiz"]
2223

2324
[dependencies]
2425
ironrdp-svc = { path = "../ironrdp-svc", version = "0.3" } # public

crates/ironrdp-pdu/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ default = []
2020
std = ["alloc", "ironrdp-error/std", "ironrdp-core/std"]
2121
alloc = ["ironrdp-core/alloc", "ironrdp-error/alloc"]
2222
qoi = []
23+
qoiz = ["qoi"]
2324

2425
[dependencies]
2526
bitflags = "2.4"

crates/ironrdp-pdu/src/rdp/capability_sets/bitmap_codecs.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ const GUID_IGNORE: Guid = Guid(0x9c43_51a6, 0x3535, 0x42ae, 0x91, 0x0c, 0xcd, 0x
4242
#[rustfmt::skip]
4343
#[cfg(feature="qoi")]
4444
const GUID_QOI: Guid = Guid(0x4dae_9af8, 0xb399, 0x4df6, 0xb4, 0x3a, 0x66, 0x2f, 0xd9, 0xc0, 0xf5, 0xd6);
45+
#[rustfmt::skip]
46+
#[cfg(feature="qoiz")]
47+
const GUID_QOIZ: Guid = Guid(0x229c_c6dc, 0xa860, 0x4b52, 0xb4, 0xd8, 0x05, 0x3a, 0x22, 0xb3, 0x89, 0x2b);
4548

4649
#[derive(Debug, PartialEq, Eq)]
4750
pub struct Guid(u32, u16, u16, u8, u8, u8, u8, u8, u8, u8, u8);
@@ -171,6 +174,8 @@ impl Encode for Codec {
171174
CodecProperty::Ignore => GUID_IGNORE,
172175
#[cfg(feature = "qoi")]
173176
CodecProperty::Qoi => GUID_QOI,
177+
#[cfg(feature = "qoiz")]
178+
CodecProperty::QoiZ => GUID_QOIZ,
174179
_ => return Err(other_err!("invalid codec")),
175180
};
176181
guid.encode(dst)?;
@@ -210,6 +215,8 @@ impl Encode for Codec {
210215
}
211216
#[cfg(feature = "qoi")]
212217
CodecProperty::Qoi => dst.write_u16(0),
218+
#[cfg(feature = "qoiz")]
219+
CodecProperty::QoiZ => dst.write_u16(0),
213220
CodecProperty::Ignore => dst.write_u16(0),
214221
CodecProperty::None => dst.write_u16(0),
215222
};
@@ -235,6 +242,8 @@ impl Encode for Codec {
235242
},
236243
#[cfg(feature = "qoi")]
237244
CodecProperty::Qoi => 0,
245+
#[cfg(feature = "qoiz")]
246+
CodecProperty::QoiZ => 0,
238247
CodecProperty::Ignore => 0,
239248
CodecProperty::None => 0,
240249
}
@@ -271,6 +280,8 @@ impl<'de> Decode<'de> for Codec {
271280
}
272281
#[cfg(feature = "qoi")]
273282
GUID_QOI => CodecProperty::Qoi,
283+
#[cfg(feature = "qoiz")]
284+
GUID_QOIZ => CodecProperty::QoiZ,
274285
GUID_IGNORE => CodecProperty::Ignore,
275286
_ => CodecProperty::None,
276287
}
@@ -284,6 +295,8 @@ impl<'de> Decode<'de> for Codec {
284295
}
285296
#[cfg(feature = "qoi")]
286297
GUID_QOI => CodecProperty::Qoi,
298+
#[cfg(feature = "qoiz")]
299+
GUID_QOIZ => CodecProperty::QoiZ,
287300
GUID_IGNORE => CodecProperty::Ignore,
288301
_ => CodecProperty::None,
289302
}
@@ -307,6 +320,8 @@ pub enum CodecProperty {
307320
Ignore,
308321
#[cfg(feature = "qoi")]
309322
Qoi,
323+
#[cfg(feature = "qoiz")]
324+
QoiZ,
310325
None,
311326
}
312327

@@ -644,6 +659,8 @@ pub enum CodecId {
644659
RemoteFx = 0x03,
645660
#[cfg(feature = "qoi")]
646661
Qoi = 0x0A,
662+
#[cfg(feature = "qoiz")]
663+
QoiZ = 0x0B,
647664
}
648665

649666
impl CodecId {
@@ -653,6 +670,8 @@ impl CodecId {
653670
0x03 => Some(Self::RemoteFx),
654671
#[cfg(feature = "qoi")]
655672
0x0A => Some(Self::Qoi),
673+
#[cfg(feature = "qoiz")]
674+
0x0B => Some(Self::QoiZ),
656675
_ => None,
657676
}
658677
}
@@ -723,6 +742,14 @@ pub fn client_codecs_capabilities(config: &[&str]) -> Result<BitmapCodecs, Strin
723742
});
724743
}
725744

745+
#[cfg(feature = "qoiz")]
746+
if config.remove("qoiz").unwrap_or(true) {
747+
codecs.push(Codec {
748+
id: CodecId::QoiZ as u8,
749+
property: CodecProperty::QoiZ,
750+
});
751+
}
752+
726753
let codec_names = config.keys().copied().collect::<Vec<_>>().join(", ");
727754
if !codec_names.is_empty() {
728755
return Err(format!("Unknown codecs: {}", codec_names));
@@ -772,6 +799,14 @@ pub fn server_codecs_capabilities(config: &[&str]) -> Result<BitmapCodecs, Strin
772799
});
773800
}
774801

802+
#[cfg(feature = "qoiz")]
803+
if config.remove("qoiz").unwrap_or(true) {
804+
codecs.push(Codec {
805+
id: 0,
806+
property: CodecProperty::QoiZ,
807+
});
808+
}
809+
775810
let codec_names = config.keys().copied().collect::<Vec<_>>().join(", ");
776811
if !codec_names.is_empty() {
777812
return Err(format!("Unknown codecs: {}", codec_names));

crates/ironrdp-server/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ name = "perfenc"
1919
required-features = ["__bench"]
2020

2121
[features]
22-
default = ["rayon", "qoi"]
22+
default = ["rayon", "qoi", "qoiz"]
2323
helper = ["dep:x509-cert", "dep:rustls-pemfile"]
2424
rayon = ["dep:rayon"]
2525
qoi = ["dep:qoi", "ironrdp-pdu/qoi"]
26+
qoiz = ["dep:zstd-safe", "qoi", "ironrdp-pdu/qoiz"]
2627

2728
# Internal (PRIVATE!) features used to aid testing.
2829
# Don't rely on these whatsoever. They may disappear at any time.
@@ -52,6 +53,7 @@ rayon = { version = "1.10.0", optional = true }
5253
bytes = "1"
5354
visibility = { version = "0.1", optional = true }
5455
qoi = { version = "0.4", optional = true }
56+
zstd-safe = { version = "7.2", optional = true }
5557

5658
[dev-dependencies]
5759
tokio = { version = "1", features = ["sync", "fs"] }

crates/ironrdp-server/examples/perfenc.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use ironrdp_server::{
1111
};
1212
use tokio::{fs::File, io::AsyncReadExt};
1313

14+
#[allow(clippy::similar_names)]
1415
#[tokio::main(flavor = "current_thread")]
1516
async fn main() -> Result<(), anyhow::Error> {
1617
setup_logging()?;
@@ -41,22 +42,26 @@ async fn main() -> Result<(), anyhow::Error> {
4142
let mut flags = CmdFlags::all();
4243

4344
#[allow(unused)]
44-
let (remotefx, qoicodec) = match codec {
45-
OptCodec::RemoteFX => (Some((EntropyBits::Rlgr3, 0)), None::<u8>),
45+
let (remotefx, qoicodec, qoizcodec) = match codec {
46+
OptCodec::RemoteFX => (Some((EntropyBits::Rlgr3, 0)), None, None),
4647
OptCodec::Bitmap => {
4748
flags -= CmdFlags::SET_SURFACE_BITS;
48-
(None, None)
49+
(None, None, None)
4950
}
50-
OptCodec::None => (None, None),
51+
OptCodec::None => (None, None, None),
5152
#[cfg(feature = "qoi")]
52-
OptCodec::Qoi => (None, Some(0)),
53+
OptCodec::Qoi => (None, Some(0), None),
54+
#[cfg(feature = "qoiz")]
55+
OptCodec::QoiZ => (None, None, Some(0)),
5356
};
5457
let mut encoder = UpdateEncoder::new(
5558
DesktopSize { width, height },
5659
flags,
5760
remotefx,
5861
#[cfg(feature = "qoi")]
5962
qoicodec,
63+
#[cfg(feature = "qoiz")]
64+
qoizcodec,
6065
);
6166

6267
let mut total_raw = 0u64;
@@ -158,6 +163,8 @@ enum OptCodec {
158163
None,
159164
#[cfg(feature = "qoi")]
160165
Qoi,
166+
#[cfg(feature = "qoiz")]
167+
QoiZ,
161168
}
162169

163170
impl Default for OptCodec {
@@ -176,6 +183,8 @@ impl core::str::FromStr for OptCodec {
176183
"none" => Ok(Self::None),
177184
#[cfg(feature = "qoi")]
178185
"qoi" => Ok(Self::Qoi),
186+
#[cfg(feature = "qoiz")]
187+
"qoiz" => Ok(Self::QoiZ),
179188
_ => Err(anyhow::anyhow!("unknown codec: {}", s)),
180189
}
181190
}

0 commit comments

Comments
 (0)