use std::str::FromStr;
use clap::{ArgGroup, Args, Parser, Subcommand};
use thiserror::Error;
use url::Url;
use videocall_nokhwa::utils::FrameFormat;
#[derive(Parser, Debug)]
#[clap(name = "client")]
pub struct Opt {
#[clap(subcommand)]
pub mode: Mode,
}
#[derive(Clone, Debug)]
pub enum IndexKind {
String(String),
Index(u32),
}
#[derive(Error, Debug)]
pub enum ParseIndexKindError {
#[error("Invalid index value: {0}")]
InvalidIndex(String),
}
impl FromStr for IndexKind {
type Err = ParseIndexKindError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(index) = s.parse::<u32>() {
Ok(IndexKind::Index(index))
} else {
Ok(IndexKind::String(s.to_string()))
}
}
}
#[derive(Subcommand, Debug)]
pub enum Mode {
Stream(Stream),
Info(Info),
}
#[derive(Args, Debug, Clone)]
pub struct Stream {
#[clap(
long = "url",
default_value = "https://webtransport-us-east.webtransport.video"
)]
pub url: Url,
#[clap(long = "user-id")]
pub user_id: String,
#[clap(long = "meeting-id")]
pub meeting_id: String,
#[clap(long = "video-device-index", short = 'v')]
pub video_device_index: Option<IndexKind>,
#[clap(long = "audio-device", short = 'a')]
pub audio_device: Option<String>,
#[clap(long = "resolution", short = 'r')]
#[clap(default_value = "1280x720")]
pub resolution: String,
#[clap(long = "fps")]
#[clap(default_value = "30")]
pub fps: u32,
#[clap(long = "bitrate-kbps")]
#[clap(default_value = "500")]
pub bitrate_kbps: u32,
#[arg(long, default_value_t = 5, value_parser = clap::value_parser!(u8).range(4..=15))]
pub vp9_cpu_used: u8,
#[arg(long, default_value_t = FrameFormat::NV12, value_parser = parse_frame_format)]
pub frame_format: FrameFormat,
#[clap(long = "debug-keylog")]
pub keylog: bool,
#[clap(long = "debug-send-test-pattern")]
pub send_test_pattern: bool,
#[clap(long = "debug-offline-streaming-test")]
pub local_streaming_test: bool,
#[clap(long = "insecure-skip-verify")]
pub insecure_skip_verify: bool,
}
fn parse_frame_format(s: &str) -> Result<FrameFormat, String> {
match s {
"NV12" => Ok(FrameFormat::NV12),
"YUYV" => Ok(FrameFormat::YUYV),
_ => Err("Invalid frame format, please use one of [NV12, BGRA, YUYV]".to_string()),
}
}
#[derive(Args, Debug)]
#[clap(group = ArgGroup::new("info").required(true))]
pub struct Info {
#[clap(long = "list-cameras", group = "info")]
pub list_cameras: bool,
#[clap(long = "list-formats", group = "info")]
pub list_formats: Option<IndexKind>,
#[clap(long = "list-resolutions", group = "info")]
pub list_resolutions: Option<IndexKind>, }
#[derive(Args, Debug, Clone)]
pub struct TestCamera {
#[clap(long = "video-device-index")]
pub video_device_index: IndexKind,
}