Skip to content

Commit fce21b9

Browse files
committed
feat(graphics,egfx): add progressive RFX decode and EGFX integration
Add progressive RemoteFX decode pipeline and wire it into the EGFX client and server: ironrdp-graphics: Progressive decode algorithms (first-pass and upgrade-pass coefficient reconstruction via SRL + inverse DWT), tile state tracking for multi-pass refinement, surface-level tile management with automatic quality progression. ironrdp-egfx: WireToSurface2 dispatch for progressive codec in GraphicsPipelineClient. Progressive surface state stored on the server for multi-pass frame scheduling.
1 parent e5ab222 commit fce21b9

9 files changed

Lines changed: 1403 additions & 11 deletions

File tree

crates/ironrdp-dvc/src/client.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ use alloc::vec::Vec;
44
use core::any::TypeId;
55
use core::fmt;
66

7-
use crate::alloc::borrow::ToOwned as _;
87
use ironrdp_core::{Decode as _, DecodeResult, ReadCursor, impl_as_any};
98
use ironrdp_pdu::{self as pdu, decode_err, encode_err, pdu_other_err};
109
use ironrdp_svc::{ChannelFlags, CompressionCondition, SvcClientProcessor, SvcMessage, SvcProcessor};
1110
use pdu::PduResult;
1211
use pdu::gcc::ChannelName;
1312
use tracing::debug;
1413

14+
use crate::alloc::borrow::ToOwned as _;
1515
use crate::pdu::{
1616
CapabilitiesResponsePdu, CapsVersion, ClosePdu, CreateResponsePdu, CreationStatus, DrdynvcClientPdu,
1717
DrdynvcServerPdu,

crates/ironrdp-dvc/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44

55
extern crate alloc;
66

7-
use core::any::TypeId;
8-
97
use alloc::boxed::Box;
108
use alloc::string::String;
119
use alloc::vec::Vec;
10+
use core::any::TypeId;
1211

1312
use pdu::DrdynvcDataPdu;
1413

crates/ironrdp-egfx/src/decode.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,10 @@ pub trait H264Decoder: Send {
149149

150150
#[cfg(feature = "openh264")]
151151
mod openh264_impl {
152-
use super::{DecodedFrame, DecoderError, DecoderResult, H264Decoder};
153152
use tracing::warn;
154153

154+
use super::{DecodedFrame, DecoderError, DecoderResult, H264Decoder};
155+
155156
/// H.264 decoder backed by Cisco's OpenH264 library
156157
///
157158
/// This decoder converts AVC-format NAL units to Annex B format

crates/ironrdp-egfx/src/server.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,10 @@ use crate::CHANNEL_NAME;
7070
use crate::pdu::{
7171
Avc420BitmapStream, Avc420Region, Avc444BitmapStream, CacheImportOfferPdu, CacheImportReplyPdu,
7272
CapabilitiesAdvertisePdu, CapabilitiesConfirmPdu, CapabilitiesV8Flags, CapabilitiesV10Flags, CapabilitiesV81Flags,
73-
CapabilitiesV103Flags, CapabilitiesV104Flags, CapabilitiesV107Flags, CapabilitySet, Codec1Type, CreateSurfacePdu,
74-
DeleteSurfacePdu, Encoding, EndFramePdu, FrameAcknowledgePdu, GfxPdu, MapSurfaceToOutputPdu, PixelFormat,
75-
QoeFrameAcknowledgePdu, ResetGraphicsPdu, StartFramePdu, Timestamp, WireToSurface1Pdu, encode_avc420_bitmap_stream,
73+
CapabilitiesV103Flags, CapabilitiesV104Flags, CapabilitiesV107Flags, CapabilitySet, Codec1Type, Codec2Type,
74+
CreateSurfacePdu, DeleteSurfacePdu, Encoding, EndFramePdu, FrameAcknowledgePdu, GfxPdu, MapSurfaceToOutputPdu,
75+
PixelFormat, QoeFrameAcknowledgePdu, ResetGraphicsPdu, StartFramePdu, Timestamp, WireToSurface1Pdu,
76+
WireToSurface2Pdu, encode_avc420_bitmap_stream,
7677
};
7778

7879
// ============================================================================
@@ -1408,6 +1409,52 @@ impl GraphicsPipelineServer {
14081409
Some(frame_id)
14091410
}
14101411

1412+
/// Queue a RemoteFX Progressive frame for transmission.
1413+
///
1414+
/// Progressive frames use `WireToSurface2Pdu` with a pre-encoded progressive
1415+
/// block stream as the bitmap payload. The `codec_context_id` associates
1416+
/// this data with persistent tile state on the client.
1417+
///
1418+
/// The `progressive_data` must be a valid progressive block stream
1419+
/// (SYNC + CONTEXT + FRAME_BEGIN + REGION + FRAME_END) as produced by
1420+
/// `ironrdp_pdu::codecs::rfx::progressive::encode_progressive_stream()`.
1421+
///
1422+
/// Returns `Some(frame_id)` if queued, `None` if not ready or backpressured.
1423+
pub fn send_remotefx_progressive_frame(
1424+
&mut self,
1425+
surface_id: u16,
1426+
codec_context_id: u32,
1427+
progressive_data: Vec<u8>,
1428+
timestamp_ms: u32,
1429+
) -> Option<u32> {
1430+
if !self.is_ready() {
1431+
return None;
1432+
}
1433+
if self.should_backpressure() {
1434+
return None;
1435+
}
1436+
1437+
let surface = self.surfaces.get(surface_id)?;
1438+
1439+
let timestamp = Self::make_timestamp(timestamp_ms);
1440+
let frame_id = self.frames.begin_frame(timestamp);
1441+
1442+
self.output_queue
1443+
.push_back(GfxPdu::StartFrame(StartFramePdu { timestamp, frame_id }));
1444+
1445+
self.output_queue.push_back(GfxPdu::WireToSurface2(WireToSurface2Pdu {
1446+
surface_id,
1447+
codec_id: Codec2Type::RemoteFxProgressive,
1448+
codec_context_id,
1449+
pixel_format: surface.pixel_format,
1450+
bitmap_data: progressive_data,
1451+
}));
1452+
1453+
self.output_queue.push_back(GfxPdu::EndFrame(EndFramePdu { frame_id }));
1454+
1455+
Some(frame_id)
1456+
}
1457+
14111458
// ========================================================================
14121459
// Output Management
14131460
// ========================================================================

crates/ironrdp-graphics/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub mod dwt;
88
pub mod dwt_extrapolate;
99
pub mod image_processing;
1010
pub mod pointer;
11+
pub mod progressive;
1112
pub mod quantization;
1213
pub mod rdp6;
1314
pub mod rectangle_processing;

0 commit comments

Comments
 (0)