Skip to content

Commit

Permalink
Added Capture Control 🎉
Browse files Browse the repository at this point in the history
	modified:   Cargo.lock
	modified:   Cargo.toml
	modified:   Python/WindowsCapture/main.py
	modified:   Python/windows-capture-native/Cargo.toml
	modified:   Python/windows-capture-native/src/lib.rs
	deleted:    src/buffer.rs
	modified:   src/capture.rs
	modified:   src/d3d11.rs
	modified:   src/frame.rs
	modified:   src/graphics_capture_api.rs
	modified:   src/lib.rs
	modified:   src/monitor.rs
	modified:   src/settings.rs
	modified:   src/window.rs
  • Loading branch information
NiiightmareXD committed Nov 9, 2023
1 parent 3bd2ced commit 2ebce7d
Show file tree
Hide file tree
Showing 14 changed files with 344 additions and 170 deletions.
41 changes: 40 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ resolver = "2"
[dependencies]
image = "0.24.7"
log = "0.4.20"
ndarray = "0.15.6"
parking_lot = "0.12.1"
rayon = "1.8.0"
thiserror = "1.0.49"
windows = { version = "0.51.1", features = [
"Win32_System_WinRT_Graphics_Capture",
Expand Down
28 changes: 20 additions & 8 deletions Python/WindowsCapture/main.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
# Python Version Is NOT Complete Yet


from windows_capture_native import NativeWindowsCapture
import ctypes
import numpy


class Capture:
def __init__(self, capture_cursor: bool = True, draw_border: bool = False):
self.frame_handler = None
self.closed_handler = None
self.capture = NativeWindowsCapture(
False, False, self.on_frame_arrived, self.on_closed
True, False, self.on_frame_arrived, self.on_closed
)
self.capture_cursor = capture_cursor
self.draw_border = draw_border

def start(self):
self.capture.start()

def on_frame_arrived(self, frame):
def stop(self):
self.capture.stop()

def on_frame_arrived(self, buffer_ptr, width, height, row_pitch):
if self.frame_handler:
self.frame_handler(frame)
num_array = numpy.ctypeslib.as_array(
ctypes.cast(buffer_ptr, ctypes.POINTER(ctypes.c_uint8)),
shape=(height, row_pitch),
)

if row_pitch == width * 4:
self.frame_handler(num_array.reshape(height, width, 4))
else:
self.frame_handler(num_array[:, : width * 4].reshape(height, width, 4))

else:
raise Exception("on_frame_arrived Event Handler Is Not Set")

Expand All @@ -43,8 +54,9 @@ def event(self, handler):


@capture.event
def on_frame_arrived(frame):
print("on_frame_arrived")
def on_frame_arrived(frame_bytes):
print("lol")
capture.stop()


@capture.event
Expand Down
4 changes: 4 additions & 0 deletions Python/windows-capture-native/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@ crate-type = ["cdylib"]

[dependencies]
pyo3 = "0.20.0"
windows = { version = "0.51.1", features = [
"Win32_UI_WindowsAndMessaging",
"Win32_Foundation",
] }
windows-capture = { path = "../../" }
59 changes: 41 additions & 18 deletions Python/windows-capture-native/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@
#![warn(clippy::cargo)]
#![allow(clippy::redundant_pub_crate)]

use std::{sync::Arc, time::Instant};

use pyo3::{
prelude::*,
types::{PyBytes, PyTuple},
use std::{
sync::{
atomic::{self, AtomicBool},
Arc,
},
time::Instant,
};

use pyo3::prelude::*;
use windows::Win32::UI::WindowsAndMessaging::PostQuitMessage;
use windows_capture::{
capture::WindowsCaptureHandler, frame::Frame, monitor::Monitor,
settings::WindowsCaptureSettings,
Expand All @@ -25,16 +29,19 @@ fn windows_capture_native(_py: Python, m: &PyModule) -> PyResult<()> {
Ok(())
}

/// Internal Struct Used For Windows Capture
#[pyclass]
pub struct NativeWindowsCapture {
capture_cursor: bool,
draw_border: bool,
on_frame_arrived_callback: Arc<PyObject>,
on_closed: Arc<PyObject>,
active: Arc<AtomicBool>,
}

#[pymethods]
impl NativeWindowsCapture {
/// Create A New Windows Capture Struct
#[new]
#[must_use]
pub fn new(
Expand All @@ -48,9 +55,11 @@ impl NativeWindowsCapture {
draw_border,
on_frame_arrived_callback: Arc::new(on_frame_arrived_callback),
on_closed: Arc::new(on_closed),
active: Arc::new(AtomicBool::new(true)),
}
}

/// Start Capture
pub fn start(&mut self) {
let settings = WindowsCaptureSettings::new(
Monitor::primary(),
Expand All @@ -59,45 +68,59 @@ impl NativeWindowsCapture {
(
self.on_frame_arrived_callback.clone(),
self.on_closed.clone(),
self.active.clone(),
),
)
.unwrap();

InnerNativeWindowsCapture::start(settings).unwrap();
}

/// Stop Capture
pub fn stop(&mut self) {
println!("STOP");
self.active.store(false, atomic::Ordering::Relaxed);
}
}

pub struct InnerNativeWindowsCapture {
/// Internal Capture Struct Used From NativeWindowsCapture
struct InnerNativeWindowsCapture {
on_frame_arrived_callback: Arc<PyObject>,
on_closed: Arc<PyObject>,
active: Arc<AtomicBool>,
}

impl WindowsCaptureHandler for InnerNativeWindowsCapture {
type Flags = (Arc<PyObject>, Arc<PyObject>);
type Flags = (Arc<PyObject>, Arc<PyObject>, Arc<AtomicBool>);

fn new((on_frame_arrived_callback, on_closed): Self::Flags) -> Self {
fn new((on_frame_arrived_callback, on_closed, active): Self::Flags) -> Self {
Self {
on_frame_arrived_callback,
on_closed,
active,
}
}

fn on_frame_arrived(&mut self, mut frame: Frame) {
if !self.active.load(atomic::Ordering::Relaxed) {
unsafe { PostQuitMessage(0) };
return;
}

let instant = Instant::now();
let width = frame.width();
let height = frame.height();
let buf = frame.buffer().unwrap();

let buf_bytes: &[u8] = unsafe {
std::slice::from_raw_parts(buf.as_ptr().cast::<u8>(), std::mem::size_of_val(buf))
};
let buf = buf.as_raw_buffer();
let row_pitch = buf.len() / height as usize;

Python::with_gil(|py| {
let buf_pybytes = PyBytes::new(py, buf_bytes);
py.check_signals().unwrap();

let args = PyTuple::new(py, [buf_pybytes]);

self.on_frame_arrived_callback.call1(py, args)
})
.unwrap();
self.on_frame_arrived_callback
.call1(py, (buf.as_ptr() as isize, width, height, row_pitch))
.unwrap();
});

println!("Took: {}", instant.elapsed().as_nanos() as f32 / 1000000.0);
}
Expand Down
22 changes: 0 additions & 22 deletions src/buffer.rs

This file was deleted.

Loading

0 comments on commit 2ebce7d

Please sign in to comment.