👕 refactor

main
_ 2023-09-09 04:00:14 -05:00
parent 677a8c7ebd
commit fdec833fd0
2 changed files with 307 additions and 276 deletions

295
src/controller.rs Normal file
View File

@ -0,0 +1,295 @@
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_network_busy (&mut self, x: bool)
{
self.tx_pipe.handle_network_busy (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_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_network_busy (&mut self, busy: bool)
{
self.network_busy = busy;
}
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_busy
{
if let Some (buf_enc) = self.buf_enc.take ()
{
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,
}

View File

@ -6,7 +6,10 @@ use std::{
}; };
use rayon::ThreadPool; use rayon::ThreadPool;
use thiserror::Error;
use crate::controller::*;
mod controller;
fn main() fn main()
{ {
@ -89,7 +92,7 @@ impl <'a> Driver <'_>
_ => panic! ("tried to finish an already finished capture"), _ => panic! ("tried to finish an already finished capture"),
}; };
self.ctl.tx_pipe.handle_capture_frame (buf_raw).unwrap (); self.ctl.handle_capture_frame (buf_raw).unwrap ();
}, },
TaskOutput::TxEncode (enc) => TaskOutput::TxEncode (enc) =>
{ {
@ -99,7 +102,7 @@ impl <'a> Driver <'_>
_ => panic! ("tried to finish an already finished encode"), _ => panic! ("tried to finish an already finished encode"),
}; };
self.ctl.tx_pipe.encoder_is_busy = false; self.ctl.handle_encoder_finished ();
}, },
TaskOutput::TxTransmit ((tx, busy)) => TaskOutput::TxTransmit ((tx, busy)) =>
{ {
@ -109,7 +112,7 @@ impl <'a> Driver <'_>
_ => panic! ("tried to finish an already finished transmit"), _ => panic! ("tried to finish an already finished transmit"),
}; };
self.ctl.tx_pipe.handle_network_busy (busy); self.ctl.handle_network_busy (busy);
} }
} }
} }
@ -157,9 +160,12 @@ impl <'a> Driver <'_>
let may_have_data = encoder.poll_encoded (&mut buf); let may_have_data = encoder.poll_encoded (&mut buf);
if may_have_data if may_have_data
{ {
self.ctl.tx_pipe.handle_encoded_packet (BufEncoded {buf}).unwrap (); self.ctl.handle_encoded_packet (Some (BufEncoded {buf})).unwrap ();
}
else
{
self.ctl.handle_encoded_packet (None).unwrap ();
} }
self.ctl.tx_pipe.encoder_has_data = may_have_data;
} }
TxPipelineEvent::Encode (buf_raw) => TxPipelineEvent::Encode (buf_raw) =>
{ {
@ -223,241 +229,6 @@ impl fmt::Debug for TaskOutput {
} }
} }
#[derive (Default)]
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)]
struct ControlEvent
{
rx: Option <RxPipelineEvent>,
tx: Option <TxPipelineEvent>,
}
impl Controller
{
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)]
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_encoded_packet (&mut self, buf_enc: BufEncoded) -> Result <(), RxPipeError>
{
if self.has_encoded_data ()
{
return Err (RxPipeError::AlreadyHaveEncodedData);
}
self.buf_enc = Some (buf_enc);
Ok (())
}
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_busy: bool,
}
#[derive (Debug)]
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: BufEncoded) -> Result <(), ControlError>
{
self.encoder_is_busy = false;
if self.has_encoded_packet ()
{
return Err (ControlError::AlreadyHaveEncodedData);
}
self.buf_enc = Some (buf_enc);
Ok (())
}
fn handle_network_busy (&mut self, busy: bool)
{
self.network_busy = busy;
}
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_busy
{
if let Some (buf_enc) = self.buf_enc.take ()
{
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
}
}
/// Wraps non-thread-safe capture device like a v4l webcam /// Wraps non-thread-safe capture device like a v4l webcam
#[derive (Default)] #[derive (Default)]
@ -562,38 +333,3 @@ impl Transmitter
false false
} }
} }
struct BufEncoded
{
buf: Vec <u8>
}
impl fmt::Debug for BufEncoded {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f
.debug_struct("BufEncoded")
.finish()
}
}
struct BufRaw
{
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)]
enum ControlError
{
#[error ("already have encoded data")]
AlreadyHaveEncodedData,
#[error ("already have raw data")]
AlreadyHaveRawData,
}