#![cfg(target_os = "windows")]
#![cfg(feature = "dxgi")]
use crate::prelude::{CaptureStream, VideoFrame};
use std::error::Error;
use std::fmt::Display;
use windows::core::ComInterface;
use windows::Graphics::DirectX::DirectXPixelFormat;
use windows::Win32::System::WinRT::Direct3D11::IDirect3DDxgiInterfaceAccess;
use windows::Win32::Graphics::Direct3D11::ID3D11Texture2D;
#[derive(Debug, Clone)]
pub enum WindowsDxgiVideoFrameError {
Other(String),
}
impl Display for WindowsDxgiVideoFrameError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Other(error) => f.write_fmt(format_args!("WindowsDxgiVideoFrameError::Other(\"{}\")", error)),
}
}
}
impl Error for WindowsDxgiVideoFrameError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
fn description(&self) -> &str {
"description() is deprecated; use Display"
}
fn cause(&self) -> Option<&dyn Error> {
self.source()
}
}
pub trait WindowsDxgiVideoFrame {
fn get_dxgi_surface(&self) -> Result<(windows::Win32::Graphics::Dxgi::IDXGISurface, DirectXPixelFormat), WindowsDxgiVideoFrameError>;
}
impl WindowsDxgiVideoFrame for VideoFrame {
fn get_dxgi_surface(&self) -> Result<(windows::Win32::Graphics::Dxgi::IDXGISurface, DirectXPixelFormat), WindowsDxgiVideoFrameError> {
let d3d11_surface = self.impl_video_frame.frame.Surface()
.map_err(|e| WindowsDxgiVideoFrameError::Other(format!("Failed to get frame surface: {}", e.to_string())))?;
let interface_access: IDirect3DDxgiInterfaceAccess = d3d11_surface.cast()
.map_err(|e| WindowsDxgiVideoFrameError::Other(format!("Failed to cast d3d11 surface to dxgi interface access: {}", e.to_string())))?;
let d3d11_texture: ID3D11Texture2D = unsafe {
interface_access.GetInterface::<ID3D11Texture2D>()
}.map_err(|e| WindowsDxgiVideoFrameError::Other(format!("Failed to get ID3D11Texture2D interface from to IDirect3DSurface(IDirect3DDxgiInterfaceAccess): {}", e.to_string())))?;
d3d11_texture.cast().map_err(|e| WindowsDxgiVideoFrameError::Other(format!("Failed to cast ID3D11Texture2D to IDXGISurface: {}", e.to_string())))
.map(|texture| (texture, self.impl_video_frame.pixel_format))
}
}
#[derive(Debug)]
pub enum WindowsDxgiCaptureStreamError {
NoAdapter(String)
}
impl Display for WindowsDxgiCaptureStreamError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NoAdapter(error) => f.write_fmt(format_args!("WindowsDxgiCaptureStreamError::NoAdapter(\"{}\")", error)),
}
}
}
impl Error for WindowsDxgiCaptureStreamError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
fn description(&self) -> &str {
"description() is deprecated; use Display"
}
fn cause(&self) -> Option<&dyn Error> {
self.source()
}
}
pub trait WindowsDxgiCaptureStream {
fn get_dxgi_adapter(&self) -> Result<windows::Win32::Graphics::Dxgi::IDXGIAdapter, WindowsDxgiCaptureStreamError>;
fn get_dxgi_device(&self) -> windows::Win32::Graphics::Dxgi::IDXGIDevice;
}
impl WindowsDxgiCaptureStream for CaptureStream {
fn get_dxgi_adapter(&self) -> Result<windows::Win32::Graphics::Dxgi::IDXGIAdapter, WindowsDxgiCaptureStreamError> {
if let Some(dxgi_adapter) = self.impl_capture_stream.dxgi_adapter.clone() {
Ok(dxgi_adapter)
} else {
match &self.impl_capture_stream.dxgi_adapter_error {
Some(error) => Err(WindowsDxgiCaptureStreamError::NoAdapter(error.clone())),
None => unreachable!("Should have dxgi_adapter_error if dxgi_adapter is None")
}
}
}
fn get_dxgi_device(&self) -> windows::Win32::Graphics::Dxgi::IDXGIDevice {
self.impl_capture_stream.dxgi_device.clone()
}
}