From 3bd2ced3108d395371252a85151183d0d8678be3 Mon Sep 17 00:00:00 2001 From: NiiightmareXD Date: Thu, 2 Nov 2023 11:13:34 -0700 Subject: [PATCH] =?UTF-8?q?Further=20Optimizations=20=F0=9F=94=A5=20=09new?= =?UTF-8?q?=20file:=20=20=20.github/workflows/python.yml=20=09modified:=20?= =?UTF-8?q?=20=20Cargo.lock=20=09modified:=20=20=20Cargo.toml=20=09new=20f?= =?UTF-8?q?ile:=20=20=20Python/WindowsCapture/main.py=20=09new=20file:=20?= =?UTF-8?q?=20=20Python/windows-capture-native/.gitignore=20=09new=20file:?= =?UTF-8?q?=20=20=20Python/windows-capture-native/Cargo.lock=20=09new=20fi?= =?UTF-8?q?le:=20=20=20Python/windows-capture-native/Cargo.toml=20=09new?= =?UTF-8?q?=20file:=20=20=20Python/windows-capture-native/LICENCE=20=09new?= =?UTF-8?q?=20file:=20=20=20Python/windows-capture-native/pyproject.toml?= =?UTF-8?q?=20=09new=20file:=20=20=20Python/windows-capture-native/src/lib?= =?UTF-8?q?.rs=20=09modified:=20=20=20README.md=20=09new=20file:=20=20=20e?= =?UTF-8?q?xamples/basic.rs=20=09modified:=20=20=20src/buffer.rs=20=09modi?= =?UTF-8?q?fied:=20=20=20src/capture.rs=20=09modified:=20=20=20src/frame.r?= =?UTF-8?q?s=20=09modified:=20=20=20src/graphics=5Fcapture=5Fapi.rs=20=09m?= =?UTF-8?q?odified:=20=20=20src/lib.rs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/python.yml | 22 + Cargo.lock | 99 +++ Cargo.toml | 7 +- Python/WindowsCapture/main.py | 55 ++ Python/windows-capture-native/.gitignore | 1 + Python/windows-capture-native/Cargo.lock | 642 +++++++++++++++++++ Python/windows-capture-native/Cargo.toml | 27 + Python/windows-capture-native/LICENCE | 21 + Python/windows-capture-native/pyproject.toml | 23 + Python/windows-capture-native/src/lib.rs | 108 ++++ README.md | 2 +- examples/basic.rs | 54 ++ src/buffer.rs | 28 +- src/capture.rs | 21 +- src/frame.rs | 53 +- src/graphics_capture_api.rs | 64 +- src/lib.rs | 2 +- 17 files changed, 1116 insertions(+), 113 deletions(-) create mode 100644 .github/workflows/python.yml create mode 100644 Python/WindowsCapture/main.py create mode 100644 Python/windows-capture-native/.gitignore create mode 100644 Python/windows-capture-native/Cargo.lock create mode 100644 Python/windows-capture-native/Cargo.toml create mode 100644 Python/windows-capture-native/LICENCE create mode 100644 Python/windows-capture-native/pyproject.toml create mode 100644 Python/windows-capture-native/src/lib.rs create mode 100644 examples/basic.rs diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml new file mode 100644 index 0000000..f536e24 --- /dev/null +++ b/.github/workflows/python.yml @@ -0,0 +1,22 @@ +name: Python + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v3 + - name: Build + run: cargo build -p windows-capture-native --verbose + - name: Run tests + run: cargo test -p windows-capture-native --verbose diff --git a/Cargo.lock b/Cargo.lock index e225985..0572327 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -167,6 +167,12 @@ dependencies = [ "crunchy", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "image" version = "0.24.7" @@ -186,6 +192,12 @@ dependencies = [ "tiff", ] +[[package]] +name = "indoc" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" + [[package]] name = "jpeg-decoder" version = "0.3.0" @@ -272,6 +284,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + [[package]] name = "parking_lot" version = "0.12.1" @@ -317,6 +335,67 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "pyo3" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e8453b658fe480c3e70c8ed4e3d3ec33eb74988bd186561b0cc66b85c3bc4b" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "memoffset", + "parking_lot", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96fe70b176a89cff78f2fa7b3c930081e163d5379b4dcdf993e3ae29ca662e5" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214929900fd25e6604661ed9cf349727c8920d47deff196c4e28165a6ef2a96b" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac53072f717aa1bfa4db832b39de8c875b7c7af4f4a6fe93cdbf9264cf8383b" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7774b5a8282bd4f25f803b1f0d945120be959a36c72e08e7cd031c792fdfd424" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "qoi" version = "0.4.1" @@ -402,6 +481,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "target-lexicon" +version = "0.12.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" + [[package]] name = "thiserror" version = "1.0.49" @@ -439,6 +524,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unindent" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" + [[package]] name = "weezl" version = "0.1.7" @@ -467,6 +558,14 @@ dependencies = [ "windows", ] +[[package]] +name = "windows-capture-native" +version = "1.0.22" +dependencies = [ + "pyo3", + "windows-capture", +] + [[package]] name = "windows-core" version = "0.51.1" diff --git a/Cargo.toml b/Cargo.toml index fac95df..fb3b8ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "windows-capture" version = "1.0.22" authors = ["NiiightmareXD"] edition = "2021" -description = "Simple Windows Screen Capture Library For Rust And Python 🔥" +description = "Fastest Windows Screen Capture Library For Rust 🔥" documentation = "https://docs.rs/windows-capture" readme = "README.md" repository = "https://github.com/NiiightmareXD/windows-capture" @@ -16,6 +16,7 @@ categories = [ "gui", "multimedia", ] +resolver = "2" [dependencies] image = "0.24.7" @@ -38,4 +39,8 @@ windows = { version = "0.51.1", features = [ "Graphics_DirectX_Direct3D11", "Foundation_Metadata", "Win32_UI_HiDpi", + "Win32_System_Com", ] } + +[workspace] +members = ["Python/windows-capture-native"] diff --git a/Python/WindowsCapture/main.py b/Python/WindowsCapture/main.py new file mode 100644 index 0000000..f286a9f --- /dev/null +++ b/Python/WindowsCapture/main.py @@ -0,0 +1,55 @@ +# Python Version Is NOT Complete Yet + + +from windows_capture_native import NativeWindowsCapture + + +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 + ) + self.capture_cursor = capture_cursor + self.draw_border = draw_border + + def start(self): + self.capture.start() + + def on_frame_arrived(self, frame): + if self.frame_handler: + self.frame_handler(frame) + else: + raise Exception("on_frame_arrived Event Handler Is Not Set") + + def on_closed(self): + if self.closed_handler: + self.closed_handler() + else: + raise Exception("on_closed Event Handler Is Not Set") + + def event(self, handler): + if handler.__name__ == "on_frame_arrived": + self.frame_handler = handler + elif handler.__name__ == "on_closed": + self.closed_handler = handler + else: + raise Exception("Invalid Event Handler Use on_frame_arrived Or on_closed") + return handler + + +capture = Capture(False, False) + + +@capture.event +def on_frame_arrived(frame): + print("on_frame_arrived") + + +@capture.event +def on_closed(): + print("on_closed") + + +capture.start() diff --git a/Python/windows-capture-native/.gitignore b/Python/windows-capture-native/.gitignore new file mode 100644 index 0000000..2f7896d --- /dev/null +++ b/Python/windows-capture-native/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/Python/windows-capture-native/Cargo.lock b/Python/windows-capture-native/Cargo.lock new file mode 100644 index 0000000..9b900b6 --- /dev/null +++ b/Python/windows-capture-native/Cargo.lock @@ -0,0 +1,642 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bytemuck" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "exr" +version = "1.71.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8" +dependencies = [ + "bit_field", + "flume", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fdeflate" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "spin", +] + +[[package]] +name = "gif" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "half" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +dependencies = [ + "crunchy", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "image" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "exr", + "gif", + "jpeg-decoder", + "num-rational", + "num-traits", + "png", + "qoi", + "tiff", +] + +[[package]] +name = "indoc" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" + +[[package]] +name = "jpeg-decoder" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" +dependencies = [ + "rayon", +] + +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + +[[package]] +name = "libc" +version = "0.2.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", + "simd-adler32", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "png" +version = "0.17.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "proc-macro2" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pyo3" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04e8453b658fe480c3e70c8ed4e3d3ec33eb74988bd186561b0cc66b85c3bc4b" +dependencies = [ + "cfg-if", + "indoc", + "libc", + "memoffset", + "parking_lot", + "pyo3-build-config", + "pyo3-ffi", + "pyo3-macros", + "unindent", +] + +[[package]] +name = "pyo3-build-config" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96fe70b176a89cff78f2fa7b3c930081e163d5379b4dcdf993e3ae29ca662e5" +dependencies = [ + "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214929900fd25e6604661ed9cf349727c8920d47deff196c4e28165a6ef2a96b" +dependencies = [ + "libc", + "pyo3-build-config", +] + +[[package]] +name = "pyo3-macros" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dac53072f717aa1bfa4db832b39de8c875b7c7af4f4a6fe93cdbf9264cf8383b" +dependencies = [ + "proc-macro2", + "pyo3-macros-backend", + "quote", + "syn", +] + +[[package]] +name = "pyo3-macros-backend" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7774b5a8282bd4f25f803b1f0d945120be959a36c72e08e7cd031c792fdfd424" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quote" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "syn" +version = "2.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "target-lexicon" +version = "0.12.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a" + +[[package]] +name = "thiserror" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tiff" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unindent" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce" + +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" + +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core", + "windows-targets", +] + +[[package]] +name = "windows-capture" +version = "1.0.22" +dependencies = [ + "image", + "log", + "parking_lot", + "rayon", + "thiserror", + "windows", +] + +[[package]] +name = "windows-capture-native" +version = "1.0.22" +dependencies = [ + "pyo3", + "windows-capture", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] diff --git a/Python/windows-capture-native/Cargo.toml b/Python/windows-capture-native/Cargo.toml new file mode 100644 index 0000000..48e8a07 --- /dev/null +++ b/Python/windows-capture-native/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "windows-capture-native" +version = "1.0.22" +authors = ["NiiightmareXD"] +edition = "2021" +description = "Fastest Windows Screen Capture Library For Python 🔥" +documentation = "https://docs.rs/windows-capture" +readme = "../../README.md" +repository = "https://github.com/NiiightmareXD/windows-capture" +license = "MIT" +keywords = ["screen", "capture", "screenshot", "graphics", "windows"] +categories = [ + "os::windows-apis", + "api-bindings", + "graphics", + "gui", + "multimedia", +] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +name = "windows_capture_native" +crate-type = ["cdylib"] + +[dependencies] +pyo3 = "0.20.0" +windows-capture = { path = "../../" } diff --git a/Python/windows-capture-native/LICENCE b/Python/windows-capture-native/LICENCE new file mode 100644 index 0000000..fd16772 --- /dev/null +++ b/Python/windows-capture-native/LICENCE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 NiiightmareXD + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Python/windows-capture-native/pyproject.toml b/Python/windows-capture-native/pyproject.toml new file mode 100644 index 0000000..35713e6 --- /dev/null +++ b/Python/windows-capture-native/pyproject.toml @@ -0,0 +1,23 @@ +[build-system] +requires = ["maturin>=1.3,<2.0"] +build-backend = "maturin" + +[project] +name = "windows-capture-native" +requires-python = ">=3.7" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: GPU", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Rust", + "Programming Language :: Python", + "Topic :: Multimedia", + "Topic :: Multimedia :: Graphics :: Capture", + "Topic :: Multimedia :: Graphics :: Capture :: Screen Capture", + "Topic :: Multimedia :: Video :: Capture", +] +dynamic = ["version"] + +[tool.maturin] +features = ["pyo3/extension-module"] diff --git a/Python/windows-capture-native/src/lib.rs b/Python/windows-capture-native/src/lib.rs new file mode 100644 index 0000000..5b8b3c1 --- /dev/null +++ b/Python/windows-capture-native/src/lib.rs @@ -0,0 +1,108 @@ +#![warn(clippy::semicolon_if_nothing_returned)] +#![warn(clippy::inconsistent_struct_constructor)] +#![warn(clippy::must_use_candidate)] +#![warn(clippy::ptr_as_ptr)] +#![warn(clippy::borrow_as_ptr)] +#![warn(clippy::nursery)] +#![warn(clippy::cargo)] +#![allow(clippy::redundant_pub_crate)] + +use std::{sync::Arc, time::Instant}; + +use pyo3::{ + prelude::*, + types::{PyBytes, PyTuple}, +}; +use windows_capture::{ + capture::WindowsCaptureHandler, frame::Frame, monitor::Monitor, + settings::WindowsCaptureSettings, +}; + +/// Fastest Windows Screen Capture Library For Python 🔥. +#[pymodule] +fn windows_capture_native(_py: Python, m: &PyModule) -> PyResult<()> { + m.add_class::()?; + Ok(()) +} + +#[pyclass] +pub struct NativeWindowsCapture { + capture_cursor: bool, + draw_border: bool, + on_frame_arrived_callback: Arc, + on_closed: Arc, +} + +#[pymethods] +impl NativeWindowsCapture { + #[new] + #[must_use] + pub fn new( + capture_cursor: bool, + draw_border: bool, + on_frame_arrived_callback: PyObject, + on_closed: PyObject, + ) -> Self { + Self { + capture_cursor, + draw_border, + on_frame_arrived_callback: Arc::new(on_frame_arrived_callback), + on_closed: Arc::new(on_closed), + } + } + + pub fn start(&mut self) { + let settings = WindowsCaptureSettings::new( + Monitor::primary(), + Some(self.capture_cursor), + Some(self.draw_border), + ( + self.on_frame_arrived_callback.clone(), + self.on_closed.clone(), + ), + ) + .unwrap(); + + InnerNativeWindowsCapture::start(settings).unwrap(); + } +} + +pub struct InnerNativeWindowsCapture { + on_frame_arrived_callback: Arc, + on_closed: Arc, +} + +impl WindowsCaptureHandler for InnerNativeWindowsCapture { + type Flags = (Arc, Arc); + + fn new((on_frame_arrived_callback, on_closed): Self::Flags) -> Self { + Self { + on_frame_arrived_callback, + on_closed, + } + } + + fn on_frame_arrived(&mut self, mut frame: Frame) { + let instant = Instant::now(); + let buf = frame.buffer().unwrap(); + + let buf_bytes: &[u8] = unsafe { + std::slice::from_raw_parts(buf.as_ptr().cast::(), std::mem::size_of_val(buf)) + }; + + Python::with_gil(|py| { + let buf_pybytes = PyBytes::new(py, buf_bytes); + + let args = PyTuple::new(py, [buf_pybytes]); + + self.on_frame_arrived_callback.call1(py, args) + }) + .unwrap(); + + println!("Took: {}", instant.elapsed().as_nanos() as f32 / 1000000.0); + } + + fn on_closed(&mut self) { + Python::with_gil(|py| self.on_closed.call0(py)).unwrap(); + } +} diff --git a/README.md b/README.md index eeacd9d..badee95 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ fn main() { foreground_window, // Capture Cursor Some(true), - // Draw Borders + // Draw Border Some(false), // This Will Be Passed To The New Function "It Works".to_string(), diff --git a/examples/basic.rs b/examples/basic.rs new file mode 100644 index 0000000..051636b --- /dev/null +++ b/examples/basic.rs @@ -0,0 +1,54 @@ +use windows_capture::{ + capture::WindowsCaptureHandler, frame::Frame, settings::WindowsCaptureSettings, window::Window, +}; + +struct Capture; + +impl WindowsCaptureHandler for Capture { + type Flags = String; // To Get The Message (Or A Variable Or ...) From The Settings + + fn new(message: Self::Flags) -> Self { + // Function That Will Be Called To Create The Struct The Flags Can Be Passed + // From Settings + println!("Got The Message: {message}"); + + Self {} + } + + fn on_frame_arrived(&mut self, mut frame: Frame) { + // Called Every Time A New Frame Is Available + println!("Got A New Frame"); + + // Save The Frame As An Image To Specified Path + frame.save_as_image("image.png").unwrap(); + + // Call To Stop The Capture Thread, You Might Receive A Few More Frames + // Before It Stops + self.stop(); + } + + fn on_closed(&mut self) { + // Called When The Capture Item Closes Usually When The Window Closes, + // Capture Will End After This Function Ends + println!("Capture Item Closed"); + } +} + +fn main() { + // Checkout Docs For Other Capture Items + let foreground_window = Window::foreground().unwrap(); + + let settings = WindowsCaptureSettings::new( + // Item To Captue + foreground_window, + // Capture Cursor + Some(true), + // Draw Border + Some(false), + // This Will Be Passed To The New Function + "It Works".to_string(), + ) + .unwrap(); + + Capture::start(settings).unwrap(); +} diff --git a/src/buffer.rs b/src/buffer.rs index 9d82fcd..4e4576f 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -1,5 +1,3 @@ -use std::alloc::Layout; - /// To Send Raw Pointers Between Threads pub struct SendSyncPtr(pub *mut T); @@ -12,27 +10,13 @@ impl SendSyncPtr { unsafe impl Send for SendSyncPtr {} unsafe impl Sync for SendSyncPtr {} -/// To Share Buffer Struct Between Threads -pub struct SendBuffer(pub T); +/// To Send Raw Pointers Between Threads +pub struct SendPtr(pub *mut T); -impl SendBuffer { - pub const fn new(device: T) -> Self { - Self(device) +impl SendPtr { + pub const fn new(ptr: *mut T) -> Self { + Self(ptr) } } -#[allow(clippy::non_send_fields_in_send_ty)] -unsafe impl Send for SendBuffer {} - -/// To Save Pointer And It's Layout Together -#[derive(Clone, Copy)] -pub struct Buffer { - pub ptr: *mut u8, - pub layout: Layout, -} - -impl Buffer { - pub const fn new(ptr: *mut u8, layout: Layout) -> Self { - Self { ptr, layout } - } -} +unsafe impl Send for SendPtr {} diff --git a/src/capture.rs b/src/capture.rs index 54cc0c2..5286056 100644 --- a/src/capture.rs +++ b/src/capture.rs @@ -2,9 +2,12 @@ use log::{info, trace}; use windows::{ Foundation::AsyncActionCompletedHandler, Win32::{ - System::WinRT::{ - CreateDispatcherQueueController, DispatcherQueueOptions, RoInitialize, RoUninitialize, - DQTAT_COM_NONE, DQTYPE_THREAD_CURRENT, RO_INIT_SINGLETHREADED, + System::{ + Com::{CoInitializeEx, CoUninitialize, COINIT_MULTITHREADED, COINIT_SPEED_OVER_MEMORY}, + WinRT::{ + CreateDispatcherQueueController, DispatcherQueueOptions, DQTAT_COM_NONE, + DQTYPE_THREAD_CURRENT, + }, }, UI::{ HiDpi::{SetProcessDpiAwareness, PROCESS_PER_MONITOR_DPI_AWARE}, @@ -30,9 +33,9 @@ pub trait WindowsCaptureHandler: Sized { where Self: std::marker::Send + 'static, { - // Initialize WinRT - trace!("Initializing WinRT"); - unsafe { RoInitialize(RO_INIT_SINGLETHREADED)? }; + // Initialize COM + trace!("Initializing COM"); + unsafe { CoInitializeEx(None, COINIT_MULTITHREADED | COINIT_SPEED_OVER_MEMORY)? }; // Set DPI Awarness trace!("Setting DPI Awarness"); @@ -87,9 +90,9 @@ pub trait WindowsCaptureHandler: Sized { info!("Stopping Capture Thread"); capture.stop_capture(); - // Uninitialize WinRT - trace!("Uninitializing WinRT"); - unsafe { RoUninitialize() }; + // Uninitialize COM + trace!("Uninitializing COM"); + unsafe { CoUninitialize() }; Ok(()) } diff --git a/src/frame.rs b/src/frame.rs index 1a86ae2..9b161ee 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -1,17 +1,13 @@ -use std::{ - alloc::{self, Layout}, - mem, ptr, -}; +use std::{mem, ptr}; use image::ColorType; -use log::info; use rayon::prelude::{IntoParallelIterator, ParallelIterator}; use thiserror::Error; use windows::Win32::Graphics::Direct3D11::{ ID3D11DeviceContext, ID3D11Texture2D, D3D11_MAPPED_SUBRESOURCE, D3D11_MAP_READ, }; -use crate::buffer::{Buffer, SendSyncPtr}; +use crate::buffer::SendSyncPtr; /// Used To Handle Internal Frame Errors #[derive(Error, Eq, PartialEq, Clone, Copy, Debug)] @@ -31,23 +27,23 @@ pub struct Rgba { } /// Frame Struct Used To Crop And Get The Frame Buffer -pub struct Frame { - buffer: Buffer, +pub struct Frame<'a> { + buffer: *mut u8, texture: ID3D11Texture2D, frame_surface: ID3D11Texture2D, - context: ID3D11DeviceContext, + context: &'a ID3D11DeviceContext, width: u32, height: u32, } -impl Frame { +impl<'a> Frame<'a> { /// Craete A New Frame #[must_use] pub const fn new( - buffer: Buffer, + buffer: *mut u8, texture: ID3D11Texture2D, frame_surface: ID3D11Texture2D, - context: ID3D11DeviceContext, + context: &'a ID3D11DeviceContext, width: u32, height: u32, ) -> Self { @@ -106,37 +102,8 @@ impl Frame { // There Is Padding So We Have To Work According To: // https://learn.microsoft.com/en-us/windows/win32/medfound/image-stride - // Reallocate If Buffer Is Too Small - if self.buffer.layout.size() < (self.width * self.height * 4) as usize { - info!( - "Reallocating Buffer Size To {:.1}MB", - ((self.width * self.height * 4) as f32 / 1024.0 / 1024.0) - ); - - let new_cap = (self.width * self.height * 4) as usize; - let new_layout = Layout::array::(new_cap)?; - - assert!( - new_layout.size() <= isize::MAX as usize, - "Allocation too large" - ); - - unsafe { - let new_ptr = - alloc::realloc(self.buffer.ptr, self.buffer.layout, new_layout.size()); - - self.buffer.ptr = if new_ptr.is_null() { - alloc::handle_alloc_error(self.buffer.layout) - } else { - new_ptr - }; - - self.buffer.layout = new_layout; - }; - } - let row_size = self.width as usize * std::mem::size_of::(); - let send_sync_ptr = SendSyncPtr::new(self.buffer.ptr); + let send_sync_ptr = SendSyncPtr::new(self.buffer); let send_sync_pdata = SendSyncPtr::new(mapped_resource.pData.cast::()); (0..self.height).into_par_iter().for_each(|i| { @@ -156,7 +123,7 @@ impl Frame { unsafe { std::slice::from_raw_parts( - self.buffer.ptr.cast::(), + self.buffer.cast::(), (self.width * self.height) as usize, ) } diff --git a/src/graphics_capture_api.rs b/src/graphics_capture_api.rs index 64746dd..5980360 100644 --- a/src/graphics_capture_api.rs +++ b/src/graphics_capture_api.rs @@ -30,7 +30,7 @@ use windows::{ }; use crate::{ - buffer::{Buffer, SendBuffer}, + buffer::SendPtr, capture::WindowsCaptureHandler, d3d11::{create_d3d_device, create_direct3d_device, SendDirectX}, frame::Frame, @@ -47,8 +47,6 @@ pub enum WindowsCaptureError { BorderUnsupported, #[error("Already Started")] AlreadyStarted, - #[error("Capture Session Is Closed")] - CaptureClosed, } /// Struct To Use For Graphics Capture Api @@ -57,11 +55,11 @@ pub struct GraphicsCaptureApi { _d3d_device: ID3D11Device, _direct3d_device: IDirect3DDevice, _d3d_device_context: ID3D11DeviceContext, - buffer: Buffer, + buffer_layout: Layout, + buffer_ptr: *mut u8, frame_pool: Option>, session: Option, active: bool, - closed: bool, } impl GraphicsCaptureApi { @@ -78,16 +76,15 @@ impl GraphicsCaptureApi { return Err(Box::new(WindowsCaptureError::Unsupported)); } - // Allocate 8MB Of Memory - trace!("Allocating 8MB Of Memory"); - let layout = Layout::new::<[u8; 8 * 1024 * 1024]>(); - let ptr = unsafe { alloc::alloc(layout) }; - if ptr.is_null() { - alloc::handle_alloc_error(layout); + // Allocate 256MB Of Memory (This Makes It So There Is No Need To Ever + // Reallocate And It Supports Up To 16K Monitor Resolution) + trace!("Allocating 256MB Of Memory"); + let buffer_layout = Layout::new::<[u8; 256 * 1024 * 1024]>(); + let buffer_ptr = unsafe { alloc::alloc(buffer_layout) }; + if buffer_ptr.is_null() { + alloc::handle_alloc_error(buffer_layout); } - let buffer = Buffer::new(ptr, layout); - // Create DirectX Devices trace!("Creating DirectX Devices"); let (d3d_device, d3d_device_context) = create_d3d_device()?; @@ -121,12 +118,12 @@ impl GraphicsCaptureApi { let closed_item = closed.clone(); move |_, _| { + closed_item.store(true, atomic::Ordering::Relaxed); + unsafe { PostQuitMessage(0) }; callback_closed.lock().on_closed(); - closed_item.store(true, atomic::Ordering::Relaxed); - Result::Ok(()) } }), @@ -144,8 +141,8 @@ impl GraphicsCaptureApi { let mut last_size = item.Size()?; let callback_frame_arrived = callback; let direct3d_device_recreate = SendDirectX::new(direct3d_device.clone()); + let buffer_frame_arrived = SendPtr::new(buffer_ptr); - let buffer = SendBuffer::new(buffer); move |frame, _| { // Return Early If The Capture Is Closed if closed_frame_pool.load(atomic::Ordering::Relaxed) { @@ -229,12 +226,12 @@ impl GraphicsCaptureApi { }; let texture = texture.unwrap(); - let buffer = &buffer; + let buffer_frame_arrived = &buffer_frame_arrived; let frame = Frame::new( - buffer.0, + buffer_frame_arrived.0, texture, frame_surface, - context.clone(), + &context, texture_width, texture_height, ); @@ -258,11 +255,11 @@ impl GraphicsCaptureApi { _d3d_device: d3d_device, _direct3d_device: direct3d_device, _d3d_device_context: d3d_device_context, - buffer, + buffer_layout, + buffer_ptr, frame_pool: Some(frame_pool), session: Some(session), active: false, - closed: false, }) } @@ -277,10 +274,6 @@ impl GraphicsCaptureApi { return Err(Box::new(WindowsCaptureError::AlreadyStarted)); } - if self.closed { - return Err(Box::new(WindowsCaptureError::CaptureClosed)); - } - // Config if capture_cursor.is_some() { if ApiInformation::IsPropertyPresent( @@ -319,9 +312,7 @@ impl GraphicsCaptureApi { } /// Stop Capture - pub fn stop_capture(&mut self) { - self.closed = true; - + pub fn stop_capture(mut self) { if let Some(frame_pool) = self.frame_pool.take() { frame_pool.Close().expect("Failed to Close Frame Pool"); } @@ -356,18 +347,19 @@ impl GraphicsCaptureApi { } } +// Close Screen Capture And Deallocate Memory impl Drop for GraphicsCaptureApi { fn drop(&mut self) { - if !self.closed { - if let Some(frame_pool) = self.frame_pool.take() { - frame_pool.Close().expect("Failed to Close Frame Pool"); - } + if let Some(frame_pool) = self.frame_pool.take() { + frame_pool.Close().expect("Failed to Close Frame Pool"); + } - if let Some(session) = self.session.take() { - session.Close().expect("Failed to Close Capture Session"); - } + if let Some(session) = self.session.take() { + session.Close().expect("Failed to Close Capture Session"); } - unsafe { alloc::dealloc(self.buffer.ptr, self.buffer.layout) }; + // Deallocate 256MB Of Memory + trace!("Deallocating 256MB Of Memory"); + unsafe { alloc::dealloc(self.buffer_ptr, self.buffer_layout) }; } } diff --git a/src/lib.rs b/src/lib.rs index f6dff7d..2123a32 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,7 +78,7 @@ //! foreground_window, //! // Capture Cursor //! Some(true), -//! // Draw Borders +//! // Draw Border //! Some(false), //! // This Will Be Passed To The New Function //! "It Works".to_string(),