299 lines
6.3 KiB
Rust
299 lines
6.3 KiB
Rust
use std::fmt;
|
|
|
|
use thiserror::Error;
|
|
|
|
#[derive (Default)]
|
|
pub struct Controller
|
|
{
|
|
/// Pipeline for pulling data from the network, decoding it,
|
|
/// and displaying it.
|
|
|
|
rx_pipe: RxPipeline,
|
|
|
|
/// Pipeline for pulling data from capture devices, encoding it,
|
|
/// and sending it over the network.
|
|
|
|
tx_pipe: TxPipeline,
|
|
}
|
|
|
|
#[derive (Debug)]
|
|
pub struct ControlEvent
|
|
{
|
|
pub rx: Option <RxPipelineEvent>,
|
|
pub tx: Option <TxPipelineEvent>,
|
|
}
|
|
|
|
impl Controller
|
|
{
|
|
pub fn handle_capture_frame (&mut self, buf_raw: BufRaw)
|
|
-> Result <(), ControlError>
|
|
{
|
|
self.tx_pipe.handle_capture_frame (buf_raw)
|
|
}
|
|
|
|
pub fn handle_encoder_finished (&mut self)
|
|
{
|
|
self.tx_pipe.encoder_is_busy = false;
|
|
}
|
|
|
|
pub fn handle_encoded_packet (&mut self, buf_enc: Option <BufEncoded>) -> Result <(), ControlError>
|
|
{
|
|
self.tx_pipe.handle_encoded_packet (buf_enc)
|
|
}
|
|
|
|
pub fn handle_transmitted (&mut self, x: bool)
|
|
{
|
|
self.tx_pipe.handle_transmitted (x)
|
|
}
|
|
|
|
pub fn poll (&mut self) -> ControlEvent
|
|
{
|
|
let rx = self.rx_pipe.poll ();
|
|
let tx = self.tx_pipe.poll ();
|
|
|
|
ControlEvent {
|
|
rx,
|
|
tx,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive (Default)]
|
|
struct RxPipeline
|
|
{
|
|
buf_enc: Option <BufEncoded>,
|
|
buf_raw: Option <BufRaw>,
|
|
}
|
|
|
|
#[derive (Debug)]
|
|
pub enum RxPipelineEvent
|
|
{
|
|
DisplayRaw (BufRaw),
|
|
Decode (BufEncoded),
|
|
Receive,
|
|
}
|
|
|
|
#[derive (Debug, Error)]
|
|
enum RxPipeError
|
|
{
|
|
#[error ("already have encoded data")]
|
|
AlreadyHaveEncodedData,
|
|
#[error ("already have raw data")]
|
|
AlreadyHaveRawData,
|
|
}
|
|
|
|
impl RxPipeline
|
|
{
|
|
|
|
fn handle_encoder_polled (&mut self, has_data: bool)
|
|
{
|
|
|
|
}
|
|
|
|
fn handle_raw_frame (&mut self, buf_raw: BufRaw) -> Result <(), RxPipeError>
|
|
{
|
|
if self.has_raw_data ()
|
|
{
|
|
return Err (RxPipeError::AlreadyHaveRawData);
|
|
}
|
|
|
|
self.buf_raw = Some (buf_raw);
|
|
|
|
Ok (())
|
|
}
|
|
|
|
fn poll (&mut self) -> Option <RxPipelineEvent>
|
|
{
|
|
if let Some (buf_raw) = self.buf_raw.take ()
|
|
{
|
|
return Some (RxPipelineEvent::DisplayRaw (buf_raw));
|
|
}
|
|
|
|
if ! self.has_raw_data ()
|
|
{
|
|
if let Some (buf_enc) = self.buf_enc.take ()
|
|
{
|
|
return Some (RxPipelineEvent::Decode (buf_enc));
|
|
}
|
|
}
|
|
|
|
if ! self.has_encoded_data ()
|
|
{
|
|
return Some (RxPipelineEvent::Receive);
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
/// True if we have a buffer of received data, ready
|
|
/// to be decoded.
|
|
|
|
fn has_encoded_data (&self) -> bool
|
|
{
|
|
self.buf_enc.is_some ()
|
|
}
|
|
|
|
fn has_raw_data (&self) -> bool
|
|
{
|
|
self.buf_raw.is_some ()
|
|
}
|
|
}
|
|
|
|
#[derive (Default)]
|
|
struct TxPipeline
|
|
{
|
|
buf_enc: Option <BufEncoded>,
|
|
buf_raw: Option <BufRaw>,
|
|
capture_is_busy: bool,
|
|
encoder_has_data: bool,
|
|
encoder_is_busy: bool,
|
|
network_congested: bool,
|
|
transmitter_is_busy: bool,
|
|
}
|
|
|
|
#[derive (Debug)]
|
|
pub enum TxPipelineEvent
|
|
{
|
|
/// Capture a raw frame and pass it to handle_capture_frame
|
|
Capture,
|
|
|
|
/// Poll the encoder. If it returns a packet, pass it to
|
|
/// handle_encoded_packet.
|
|
PollEncoder,
|
|
|
|
/// Encode this raw frame and pass the encoded frame to
|
|
/// handle_encoded_packet
|
|
Encode (BufRaw),
|
|
|
|
/// Transmit this encoded frame to the network
|
|
Transmit (BufEncoded),
|
|
}
|
|
|
|
impl TxPipeline
|
|
{
|
|
fn handle_capture_frame (&mut self, buf_raw: BufRaw)
|
|
-> Result <(), ControlError>
|
|
{
|
|
self.capture_is_busy = false;
|
|
|
|
if self.has_raw_frame ()
|
|
{
|
|
return Err (ControlError::AlreadyHaveRawData);
|
|
}
|
|
|
|
self.buf_raw = Some (buf_raw);
|
|
|
|
Ok (())
|
|
}
|
|
|
|
fn handle_encoded_packet (&mut self, buf_enc: Option <BufEncoded>) -> Result <(), ControlError>
|
|
{
|
|
self.encoder_has_data = buf_enc.is_some ();
|
|
let buf_enc = match buf_enc
|
|
{
|
|
None => return Ok (()),
|
|
Some (x) => x,
|
|
};
|
|
|
|
self.encoder_is_busy = false;
|
|
|
|
if self.has_encoded_packet ()
|
|
{
|
|
return Err (ControlError::AlreadyHaveEncodedData);
|
|
}
|
|
|
|
self.buf_enc = Some (buf_enc);
|
|
|
|
Ok (())
|
|
}
|
|
|
|
fn handle_transmitted (&mut self, busy: bool)
|
|
{
|
|
self.network_congested = busy;
|
|
self.transmitter_is_busy = false;
|
|
}
|
|
|
|
fn has_encoded_packet (&self) -> bool
|
|
{
|
|
self.buf_enc.is_some ()
|
|
}
|
|
|
|
fn has_raw_frame (&self) -> bool
|
|
{
|
|
self.buf_raw.is_some ()
|
|
}
|
|
|
|
fn poll (&mut self) -> Option <TxPipelineEvent>
|
|
{
|
|
if ! self.network_congested && ! self.transmitter_is_busy
|
|
{
|
|
if let Some (buf_enc) = self.buf_enc.take ()
|
|
{
|
|
self.transmitter_is_busy = true;
|
|
return Some (TxPipelineEvent::Transmit (buf_enc));
|
|
}
|
|
}
|
|
|
|
if ! self.has_encoded_packet () && ! self.encoder_is_busy
|
|
{
|
|
if self.encoder_has_data
|
|
{
|
|
return Some (TxPipelineEvent::PollEncoder);
|
|
}
|
|
|
|
if let Some (buf_raw) = self.buf_raw.take ()
|
|
{
|
|
self.encoder_has_data = true;
|
|
self.encoder_is_busy = true;
|
|
return Some (TxPipelineEvent::Encode (buf_raw));
|
|
}
|
|
}
|
|
|
|
if ! self.has_raw_frame ()
|
|
{
|
|
if ! self.capture_is_busy
|
|
{
|
|
self.capture_is_busy = true;
|
|
return Some (TxPipelineEvent::Capture);
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
}
|
|
|
|
pub struct BufEncoded
|
|
{
|
|
pub buf: Vec <u8>
|
|
}
|
|
|
|
impl fmt::Debug for BufEncoded {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f
|
|
.debug_struct("BufEncoded")
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
pub struct BufRaw
|
|
{
|
|
pub buf: Vec <u8>
|
|
}
|
|
|
|
impl fmt::Debug for BufRaw {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f
|
|
.debug_struct("BufRaw")
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
#[derive (Debug, Error)]
|
|
pub enum ControlError
|
|
{
|
|
#[error ("already have encoded data")]
|
|
AlreadyHaveEncodedData,
|
|
#[error ("already have raw data")]
|
|
AlreadyHaveRawData,
|
|
}
|