Communitygithub.com

shiguredo/shiguredo-video-device

Fonctionnalités et référence API de la bibliothèque de capture vidéo multiplateforme shiguredo_video_device de Shiguredo. Utilisation pour les questions relatives à l'énumération des périphériques et la capture d'images sur macOS (AVFoundation) / Linux (V4L2 / PipeWire) / Windows (Media Foundation), à la sélection du backend via les fonctionnalités, aux formats de pixels et à la disposition mémoire des images, aux contraintes des callbacks et aux différences de comportement entre les backends.

Qu'est-ce que shiguredo-video-device ?

Cette compétence fournit une référence complète pour la bibliothèque Rust `shiguredo_video_device`, qui offre une API unifiée pour l'énumération des caméras et la capture d'images sur macOS, Linux et Windows. Elle permet de sélectionner le backend de capture (AVFoundation, V4L2, PipeWire, Media Foundation) via des fonctionnalités Cargo, et supporte les formats de pixels NV12, YUY2, I420, et MJPEG (sur Linux V4L2). La bibliothèque utilise un modèle de callback pour délivrer les frames, avec des contraintes strictes sur la durée de vie des données et l'exécution des callbacks. Elle gère les différences de comportement entre les systèmes d'exploitation, comme la gestion des autorisations sur macOS, les variations de stride et de timestamp, et les exigences de thread safety (notamment pour Windows avec COM). Le markdown détaillé inclut la configuration des fonctionnalités, les structures de données (VideoDeviceList, VideoCapture, VideoFrame, PixelFormat), des exemples de code pour l'énumération et la capture, ainsi que des conseils pour éviter les deadlocks et les use-after-free. Cette compétence est conçue pour les développeurs utilisant des agents IA comme Claude Code, Cursor ou Codex pour intégrer la capture vidéo multiplateforme dans leurs projets Rust.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/shiguredo/video-device-rs/tree/HEAD/skills/shiguredo-video-device

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

shiguredo_video_device

Bibliothèque fournissant l'énumération des caméras et la capture d'images sur macOS / Linux / Windows via une API Rust commune à toutes les plateformes.

Caractéristiques

  • Multiplateforme : macOS (AVFoundation), Linux (V4L2 / PipeWire), Windows (Media Foundation) avec une API identique
  • Sélection du backend par fonctionnalité : Choisissez le backend activé et le backend par défaut via les fonctionnalités Cargo
  • Piloté par callback : Pendant la capture, un callback est appelé pour chaque image sur le thread du backend
  • Formats de pixels : NV12 / YUY2 / I420, et passage MJPEG sur Linux (V4L2) avec la fonctionnalité mjpeg
  • Peu de dépendances : La seule crate Rust dépendante est windows (pour la fonctionnalité mf sur Windows)
  • Référence CVPixelBuffer (macOS) : Les frames incluent une référence au CVPixelBuffer (PixelBuffer), permettant de les passer à VideoToolbox sans copie

Informations de version

  • Nom de la crate : shiguredo_video_device
  • Version : 2026.4.0
  • Édition Rust : 2024
  • Version minimale de Rust : 1.95
  • Version minimale de macOS : 14.0 (nécessite AVCaptureDeviceTypeExternal, ne fonctionne pas sur macOS 13 et antérieur)
  • Licence : Apache-2.0
  • Dépôt : https://github.com/shiguredo/video-device-rs

Error / PixelFormat ne sont pas #[non_exhaustive]. Tous les variants peuvent être énumérés avec match.

Installation

[dependencies]
shiguredo_video_device = "2026.4"

Par défaut, le backend par défaut est AVFoundation sur macOS, V4L2 sur Linux et Media Foundation sur Windows. Les fonctionnalités pour un système d'exploitation autre que celui de la cible de compilation sont ignorées, il n'est donc pas nécessaire de séparer les dépendances par OS.

Fonctionnalités

FonctionnalitéOS cibleDescription
avfmacOSActive le backend AVFoundation
v4l2LinuxActive le backend V4L2
pipewireLinuxActive le backend PipeWire (lien dynamique avec libpipewire-0.3)
mfWindowsActive le backend Media Foundation (dépend de la crate windows)
mjpegLinuxActive le passage MJPEG sur V4L2 (inclut v4l2)
default-avfmacOSDéfinit AVFoundation comme backend par défaut (inclut avf)
default-v4l2LinuxDéfinit V4L2 comme backend par défaut (inclut v4l2)
default-pipewireLinuxDéfinit PipeWire comme backend par défaut (inclut pipewire)
default-mfWindowsDéfinit Media Foundation comme backend par défaut (inclut mf)

Les fonctionnalités par défaut sont default-avf / default-v4l2 / default-mf.

  • Activer deux default-* ou plus sur le même OS provoquera une panique du script de build
  • Pour utiliser PipeWire par défaut sur Linux, il faut default-features = false. Cela désactive également les valeurs par défaut sur macOS/Windows, donc pour une application multiplateforme, il faut réactiver default-avf / default-mf
  • Sur un OS sans default-*, VideoDeviceList::enumerate() / VideoCapture::new() n'existent pas. Utilisez les API explicites comme enumerate_avf() / new_v4l2()
  • Sur un OS où aucun backend n'est activé, VideoCapture / VideoDevice / VideoDeviceList ne sont pas exposés (seuls les types comme Error / PixelFormat restent)
  • Sur Linux, v4l2 et pipewire peuvent être activés simultanément
  • Les cfg enable_* internes de la crate sont définis par le script de build uniquement pour cette crate et ne sont pas accessibles depuis l'extérieur. L'utilisateur doit se baser sur #[cfg(target_os = "linux")] et ses propres fonctionnalités

Pour utiliser PipeWire comme backend par défaut sur Linux tout en conservant les valeurs par défaut sur macOS et Windows :

[dependencies.shiguredo_video_device]
version = "2026.4"
default-features = false
features = ["default-avf", "default-mf", "default-pipewire"]

Pour conserver V4L2 par défaut tout en activant PipeWire et MJPEG :

[dependencies]
shiguredo_video_device = { version = "2026.4", features = ["pipewire", "mjpeg"] }

Prérequis de compilation

OSPrérequis
macOSXcode Command Line Tools (inclut libclang pour bindgen)
Linux (V4L2)libclang (sur Ubuntu : libclang-dev)
Linux (PipeWire)libclang et libpipewire-0.3-dev, pkg-config
WindowsAucun paquet supplémentaire requis

API principale

Types exposés

TypeDescriptionAPI principale
VideoDeviceListRésultat de l'énumération des périphériquesenumerate(), enumerate_avf(), enumerate_v4l2(), enumerate_pipewire(), enumerate_mf(), as_slice(), len(), is_empty(), &VideoDeviceList: IntoIterator
VideoDeviceUn seul périphériquename() -> Result<String>, unique_id() -> Result<String>, formats() -> Vec<VideoFormat>, format_count() -> usize
VideoFormatFormat signalé par le périphériquewidth: i32, height: i32, min_fps: f32, max_fps: f32, pixel_format: PixelFormat
VideoCaptureSession de capturenew(), new_avf(), new_v4l2(), new_pipewire(), new_mf(), start(), stop(), config()
VideoCaptureConfigConfiguration de capture (implémente Default)device_id: Option<String>, width: i32, height: i32, fps: i32, pixel_format: Option<PixelFormat>
VideoFrame<'a>Image empruntée passée au callbackdata, uv_data, width, height, stride, stride_uv, pixel_format, timestamp_us, pixel_buffer, to_owned()
VideoFrameOwnedImage possédéeMêmes champs que VideoFrame (stockés dans Vec<u8>), as_frame()
PixelFormatFormat de pixelNv12, Yuy2, I420, Mjpeg, Unknown(u32), name(), to_raw(), Display
PixelBufferRéférence à un CVPixelBuffer (macOS)as_ptr() -> *mut c_void (Clone fait CFRetain, Drop fait CFRelease)
Error / Result<T>Type d'erreur et type de résultatVoir la section « Types d'erreur »

enumerate() / new() utilisent le backend par défaut (default-*). enumerate_*() / new_*() n'existent que si l'OS cible correspond et que la fonctionnalité associée est activée.

VideoDeviceList / VideoDevice

  • VideoDevice ne peut être extrait que par emprunt (&VideoDevice) depuis VideoDeviceList. Si vous avez besoin des informations après avoir abandonné la liste, copiez des valeurs comme unique_id()
  • La valeur de unique_id() peut être passée directement à VideoCaptureConfig::device_id (pour le même backend uniquement)
  • name() / unique_id() renvoient un Result car le backend FFI (macOS / Linux) peut retourner NULL ou des chaînes non UTF-8. Windows ne peut pas échouer
  • format_count() correspond au nombre d'entrées signalé par le backend C, qui peut être supérieur à formats().len() (les entrées non récupérables sont exclues)
  • min_fps / max_fps de VideoFormat sont des valeurs approximatives dépendant du backend (voir la section « Différences de comportement entre les backends »)

Cycle de vie de VideoCapture

  • new*() crée la session sans démarrer la capture (sur macOS, si l'autorisation n'est pas encore déterminée, une boîte de dialogue système apparaît et la fonction ne retourne qu'après la réponse de l'utilisateur)
  • start() est idempotent : si la capture est déjà en cours, il renvoie Ok(()). Un nouveau start() après stop() est autorisé
  • stop() est bloquant : il attend la fin du thread de capture et la complétion de tous les callbacks avant de retourner. Ne fait rien si la capture n'est pas en cours
  • Lors du drop, si la capture est en cours, un arrêt bloquant (identique à stop()) est effectué avant de détruire la session
  • config() renvoie les valeurs demandées lors de new*(). Il ne s'agit pas des valeurs réelles après négociation : pour la résolution, le format et le stride, référez-vous aux champs de chaque frame

VideoCaptureConfig

ChampValeur par défautDescription
device_idNoneValeur de VideoDevice::unique_id(). None signifie le périphérique par défaut
width640Largeur demandée
height480Hauteur demandée
fps30Fréquence d'images demandée
pixel_formatNoneFormat de pixel demandé. None laisse le backend choisir
  • Sur Windows, si width / height / fps sont inférieurs ou égaux à zéro, une erreur Error::InvalidCaptureConfig est renvoyée. Les autres backends ne vérifient pas ces valeurs côté Rust
  • pixel_format: Some(PixelFormat::Unknown(_)) renvoie Error::UnsupportedPixelFormat sur tous les backends
  • pixel_format: Some(PixelFormat::Mjpeg) n'est utilisable qu'avec Linux V4L2 + la fonctionnalité mjpeg. Sinon, renvoie Error::UnsupportedPixelFormat(PixelFormat::Mjpeg)
  • Les valeurs demandées ne sont que des souhaits : les valeurs réelles sont déterminées par le backend et le périphérique

PixelFormat

VariantContenuto_raw() (FourCC)
Nv12YUV 4:2:0 semi-planaire (plan Y + plan UV entrelacé)0x3231564E (NV12)
Yuy2YUV 4:2:2 paquet (Y0 U Y1 V)0x32595559 (YUY2)
I420YUV 4:2:0 planaire (3 plans Y / U / V)0x30323449 (I420)
MjpegMotion JPEG. Le décodage est à la charge de l'utilisateur0x47504A4D (MJPG)
Unknown(u32)FourCC inconnuLa valeur stockée
  • name() renvoie "NV12" / "YUY2" / "I420" / "MJPEG" / "Unknown". Display affiche Unknown(0x????????) pour le variant Unknown
  • Actuellement, les backends ne génèrent pas de Unknown. Les formats inconnus sont exclus de formats() et leurs frames ne sont pas passées au callback

Disposition mémoire des frames

Formatdatauv_datastridestride_uv
NV12Plan YSome : plan UV entrelacé (ceil(height / 2) lignes)Nombre d'octets par ligne de YNombre d'octets par ligne de UV
I420Plan YSome : zone contiguë avec le plan U suivi du plan V (chacun stride_uv * ceil(height / 2) octets)Nombre d'octets par ligne de YNombre d'octets par ligne de U/V
YUY2Données paquetNoneNombre d'octets par ligne0
MJPEGPayload JPEG (longueur = data.len())None00
  • stride peut inclure le padding en fin de ligne. Si vous avez besoin d'un buffer contigu exact, il faut recompacter ligne par ligne (voir pack_frame dans les exemples)
  • data.len() pour NV12 / I420 / YUY2 vaut stride * height sur les backends FFI (macOS / Linux) et width * height sur Windows (YUY2 : width * 2 * height)
  • timestamp_us est en microsecondes, mais son origine varie selon le backend. Utilisez-le uniquement pour des temps relatifs entre frames, pas comme horloge murale
  • pixel_buffer vaut Some sur macOS, None ailleurs

Contraintes du callback de frame

Le type du callback est F: Fn(VideoFrame<'_>) + Send + 'static.

  • Les slices de VideoFrame ne sont valides que pendant l'exécution du callback. Pour les utiliser après, copiez-les avec frame.to_owned() pour obtenir un VideoFrameOwned
  • Le callback est exécuté sur le thread de capture du backend. Un traitement lourd peut entraîner la perte de frames ; passez les données à un autre thread via sync_channel + try_send
  • Il n'est pas FnMut, donc pour mettre à jour un état, utilisez la mutabilité intérieure (Cell / RefCell / Mutex / types atomiques). Aucune exigence Sync : le callback ne sera jamais appelé en parallèle
  • Le callback ne doit pas paniquer. Sur macOS/Linux, cela peut provoquer un abort du processus. Sur Windows, le thread de capture se termine et un start() après stop() renverra Error::CaptureFaulted (un start() sans stop() intermédiaire est considéré comme déjà en cours et renvoie Ok(())). La bibliothèque n'utilise pas catch_unwind
  • Ne pas appeler stop() ni drop le VideoCapture depuis le callback. Cela pourrait causer un use-after-free sur Linux (V4L2 / PipeWire) ou un deadlock sur macOS. Le VideoCapture Windows est !Send, donc en Rust safe, il ne peut pas être passé au callback. Pour arrêter, utilisez un canal ou un flag pour notifier un autre thread, et appelez stop() depuis ce thread

Sécurité des threads

TypeSendSyncNotes
VideoDeviceList / VideoDeviceOuiOui
VideoCapture (macOS / Linux)OuiNon
VideoCapture (Windows)NonNonContient un garde d'initialisation COM ; à utiliser et drop sur le thread de création
VideoFrameOwned / PixelBufferOuiNonArc<VideoFrameOwned> ne peut pas être partagé entre threads. Pour distribuer à plusieurs récepteurs, clonez ou encapsulez dans un Mutex
ErrorOuiOuiCopy

Exemples de code

Énumération des périphériques

use shiguredo_video_device::VideoDeviceList;

fn main() -> shiguredo_video_device::Result<()> {
    // Énumérer les périphériques avec le backend par défaut
    let devices = VideoDeviceList::enumerate()?;
    for device in &devices {
        // name() / unique_id() peuvent échouer sur les backends FFI, donc renvoient un Result
        println!("{} ({})", device.name()?, device.unique_id()?);
        for format in device.formats() {
            println!(
                "  {}x{} {:.0}-{:.0}fps {}",
                format.width, format.height, format.min_fps, format.max_fps, format.pixel_format
            );
        }
    }
    Ok(())
}

Réception des frames via un canal (modèle recommandé)

use std::sync::mpsc::sync_channel;
use std::time::Duration;

use shiguredo_video_device::{VideoCapture, VideoCaptureConfig, VideoFrame, VideoFrameOwned};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Canal avec limite pour créer une contre-pression. Un canal illimité ferait croître la mémoire si le récepteur est lent
    let (tx, rx) = sync_channel::<VideoFrameOwned>(4);

    let config = VideoCaptureConfig {
        width: 1280,
        height: 720,
        fps: 30,
        ..VideoCaptureConfig::default()
    };

    let mut capture = VideoCapture::new(config, move |frame: VideoFrame<'_>| {
        // Les slices ne sont valides que pendant le callback, donc copiez avec to_owned() avant d'envoyer
        // Si le récepteur est saturé, ne bloquez pas et jetez la frame
        let _ = tx.try_send(frame.to_owned());
    })?;

    capture.start()?;

    for _ in 0..30 {
        let frame = rx.recv_timeout(Duration::from_secs(5))?;
        // La résolution et le format réels sont ceux de la frame (config() donne les valeurs demandées)
        println!(
            "{}x{} {} ts={}us",
            frame.width, frame.height, frame.pixel_format, frame.timestamp_us
        );
    }

    // stop() attend la fin des callbacks avant de retourner. Ne pas appeler depuis un callback
    capture.stop();
    Ok(())
}

Spécifier un périphérique et un format

use shiguredo_video_device::{
    Error, PixelFormat, VideoCapture, VideoCaptureConfig, VideoDeviceList,
};

fn open_first_device() -> Result<VideoCapture, Box<dyn std::error::Error>> {
    let devices = VideoDeviceList::enumerate()?;
    let Some(device) = devices.as_slice().first() else {
        return Err("no video device found".into());
    };

    // Si le périphérique signale du NV12 en 1280x720, demandez-le ; sinon, laissez le backend choisir
    let pixel_format = device
        .formats()
        .into_iter()
        .find(|f| f.width == 1280 && f.height == 720 && f.pixel_format == PixelFormat::Nv12)
        .map(|f| f.pixel_format);

    let config = VideoCaptureConfig {
        // La valeur de unique_id() peut être passée directement à device_id
        device_id: Some(device.unique_id()?),
        width: 1280,
        height: 720,
        fps: 30,
        pixel_format,
    };

    match VideoCapture::new(config, |frame| {
        let _ = frame.data.len();
    }) {
        Ok(capture) => Ok(capture),
        Err(Error::UnsupportedPixelFormat(format)) => {
            Err(format!("pixel format {format} is not supported").into())
        }
        Err(e) => Err(e.into()),
    }
}

Supprimer le stride pour obtenir un buffer contigu

Utile lorsque des encodeurs nécessitent un buffer contigu de la largeur exacte.

use shiguredo_video_device::{PixelFormat, VideoFrame};

/// Concatène les octets utiles de chaque ligne d'un plan avec stride
fn pack_plane(src: &[u8], stride: usize, row_bytes: usize, rows: usize) -> Option<Vec<u8>> {
    if row_bytes > stride {
        return None;
    }
    // Les dimensions proviennent du périphérique et ne sont pas fiables ; n'allouez pas à l'avance, agrandissez au fur et à mesure
    let mut out = Vec::new();
    for row in 0..rows {
        let start = row.checked_mul(stride)?;
        out.extend_from_slice(src.get(start..start.checked_add(row_bytes)?)?);
    }
    Some(out)
}

/// Reconditionne une frame en un buffer contigu sans stride. Renvoie None si les dimensions sont incohérentes
fn pack_frame(frame: &VideoFrame<'_>) -> Option<Vec<u8>> {
    let w = usize::try_from(frame.width).ok()?;
    let h = usize::try_from(frame.height).ok()?;
    let stride = usize::try_from(frame.stride).ok()?;
    let stride_uv = usize::try_from(frame.stride_uv).ok()?;
    let chroma_w = w.div_ceil(2);
    let chroma_h = h.div_ceil(2);
    match frame.pixel_format {
        PixelFormat::Nv12 => {
            let mut out = pack_plane(frame.data, stride, w, h)?;
            // UV : U et V alternent, donc le nombre d'octets utiles par ligne = chroma_w * 2
            out.extend(pack_plane(
                frame.uv_data?,
                stride_uv,
                chroma_w * 2,
                chroma_h,
            )?);
            Some(out)
        }
        PixelFormat::I420 => {
            let uv = frame.uv_data?;
            // uv_data est une zone contiguë : plan U suivi du plan V
            let plane_size = stride_uv.checked_mul(chroma_h)?;
            let mut out = pack_plane(frame.data, stride, w, h)?;
            out.extend(pack_plane(
                uv.get(..plane_size)?,
                stride_uv,
                chroma_w,
                chroma_h,
            )?);
            out.extend(pack_plane(
                uv.get(plane_size..)?,
                stride_uv,
                chroma_w,
                chroma_h,
            )?);
            Some(out)
        }
        // YUY2 : 2 pixels = 4 octets
        PixelFormat::Yuy2 => pack_plane(frame.data, stride, chroma_w * 4, h),
        // MJPEG : payload JPEG sans stride
        PixelFormat::Mjpeg => Some(frame.data.to_vec()),
        PixelFormat::Unknown(_) => None,
    }
}

Utiliser un backend non par défaut (Linux PipeWire)

// Suppose que la fonctionnalité pipewire est activée dans les dépendances
// Pour éviter les imports inutilisés sur d'autres OS, ajoutez cfg à use
#[cfg(target_os = "linux")]
use shiguredo_video_device::VideoCapture;

#[cfg(target_os = "linux")]
fn main() -> Result<(), Box<dyn std::error::Error>> {
    // new_pipewire() n'existe que sur Linux avec la fonctionnalité pipewire
    let mut capture = VideoCapture::new_pipewire(
        VideoCaptureConfig::default(),
        |frame: VideoFrame<'_>| {
            println!("Frame reçue : {}x{}", frame.width, frame.height);
        },
    )?;
    capture.start()?;
    std::thread::sleep(std::time::Duration::from_secs(2));
    capture.stop();
    Ok(())
}

#[cfg(not(target_os = "linux"))]
fn main() {
    println!("PipeWire n'est disponible que sous Linux.");
}

Énumération explicite par backend

use shiguredo_video_device::VideoDeviceList;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Énumération explicite : les fonctions enumerate_*() ne sont disponibles que si le backend correspondant est activé
    
    #[cfg(target_os = "macos")]
    {
        let avf_devices = VideoDeviceList::enumerate_avf()?;
        println!("Périphériques AVFoundation : {}", avf_devices.len());
    }

    #[cfg(target_os = "linux")]
    {
        let v4l2_devices = VideoDeviceList::enumerate_v4l2()?;
        println!("Périphériques V4L2 : {}", v4l2_devices.len());

        let pw_devices = VideoDeviceList::enumerate_pipewire()?;
        println!("Périphériques PipeWire : {}", pw_devices.len());
    }

    #[cfg(target_os = "windows")]
    {
        let mf_devices = VideoDeviceList::enumerate_mf()?;
        println!("Périphériques Media Foundation : {}", mf_devices.len());
    }

    Ok(())
}

Types d'erreur

pub enum Error {
    /// L'appel système ou la fonction du backend a échoué avec un message
    SystemError(String),
    /// Le périphérique spécifié est introuvable lors du démarrage de la capture
    DeviceNotFound,
    /// Le format de pixel demandé n'est pas supporté
    UnsupportedPixelFormat(PixelFormat),
    /// La configuration de capture est invalide (par ex. largeur/hauteur/fps <= 0 sur Windows)
    InvalidCaptureConfig,
    /// Le thread de capture a planté (Windows seulement)
    CaptureFaulted,
    /// Le format de pixel demandé n'est pas supporté par le périphérique
    UnsupportedFormat,
    /// Erreur de conversion de chaîne (nom ou ID de périphérique non UTF-8)
    StringConversionError,
    /// Timeout lors de l'attente de l'autorisation de la caméra sur macOS
    PermissionTimeout,
    /// Erreur liée à la gestion du thread
    ThreadError(String),
    /// Erreur liée au pool de threads
    ThreadPoolError(String),
    /// Autre erreur interne
    Other(String),
}

pub type Result<T> = std::result::Result<T, Error>;

Différences de comportement entre les backends

macOS (AVFoundation)

  • new() peut bloquer pour afficher la boîte de dialogue d'autorisation de la caméra. Si l'utilisateur refuse, start() renvoie Error::SystemError
  • min_fps / max_fps dans VideoFormat sont extraits des AVFrameRateRange du AVCaptureDeviceFormat
  • pixel_buffer dans VideoFrame contient toujours Some(PixelBuffer) permettant un accès direct au CVPixelBuffer
  • Les identifiants de périphériques (unique_id()) sont des UID de type "0x1a2b3c4d5e6f7g8h"

Linux V4L2

  • Necessite le paquet libclang-dev pour la compilation
  • Les formats MJPEG ne sont disponibles qu'avec la fonctionnalité mjpeg. Sans elle, formats() exclut le format MJPEG et pixel_format: Some(PixelFormat::Mjpeg) renvoie Error::UnsupportedPixelFormat
  • min_fps / max_fps : V4L2 ne fournit pas directement les FPS via VIDIOC_ENUM_FRAMESIZES / VIDIOC_ENUM_FRAMEINTERVALS. Les valeurs sont dérivées des intervalles supportés ; si non disponibles, min_fps = max_fps = 0.0
  • Les identifiants de périphériques sont des chemins de fichiers comme /dev/video0
  • Les noms de périphériques peuvent contenir des caractères non UTF-8 (provenant du noyau)

Linux PipeWire

  • Necessite libpipewire-0.3-dev et pkg-config pour la compilation, et libpipewire-0.3 au runtime
  • min_fps / max_fps : PipeWire ne fournit pas d'informations de FPS via l'API de registre. Les valeurs sont toujours 0.0
  • Les identifiants de périphériques sont des ID d'objet PipeWire (entier sous forme de chaîne)
  • PipeWire peut énumérer des périphériques virtuels (comme les sources d'écran)

Windows Media Foundation

  • Ne necessite aucun paquet supplémentaire pour la compilation
  • VideoCapture n'est pas Send en raison du garde d'initialisation COM. Créez et utilisez le sur le même thread
  • width / height / fps doivent être > 0 ; sinon, new() renvoie Error::InvalidCaptureConfig
  • min_fps / max_fps : Media Foundation fournit ces informations via IMFMediaType. Les valeurs sont extraites du type de média du dispositif
  • Les identifiants de périphériques sont des chaînes de symbole du dispositif (ex. "\\?\usb#vid_xxxx&pid_yyyy&mi_00#...")
  • Les noms de périphériques sont toujours en UTF-16 convertis en UTF-8 ; le Result de name() ne devrait jamais échouer
  • Si le thread de capture plante, start() après stop() renverra Error::CaptureFaulted

Licence

Licencié sous Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.

Sauf obligation légale ou accord écrit, le logiciel distribué sous cette licence est fourni « EN L'ÉTAT », SANS GARANTIE NI CONDITION D'AUCUNE SORTE, explicite ou implicite.

Skills associés