Screen Capturing and Encoding (#2)

* prototype

* add scrap with DXGI

* prototype

* openh264 prototype

* fixes

* x264 prototype

* fix ips

* refactoring

* refactor

* refactoring

* add params
This commit is contained in:
Harry
2022-10-19 13:49:39 -04:00
committed by GitHub
parent bcdf078501
commit 389206bc5d
16 changed files with 1143 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
/target
+8
View File
@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/mira_sharer.iml" filepath="$PROJECT_DIR$/mira_sharer.iml" />
</modules>
</component>
</project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
Generated
+653
View File
@@ -0,0 +1,653 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
dependencies = [
"winapi",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "backtrace"
version = "0.3.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7"
dependencies = [
"addr2line",
"cc",
"cfg-if 1.0.0",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bindgen"
version = "0.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75"
dependencies = [
"bitflags",
"cexpr",
"cfg-if 0.1.10",
"clang-sys",
"clap 2.34.0",
"env_logger",
"lazy_static",
"log",
"peeking_take_while",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"which",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cexpr"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clang-sys"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853"
dependencies = [
"glob",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "2.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim 0.8.0",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "clap"
version = "4.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ea54a38e4bce14ff6931c72e5b3c43da7051df056913d4e7e1fcdb1c03df69d"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"once_cell",
"strsim 0.10.0",
"termcolor",
]
[[package]]
name = "clap_derive"
version = "4.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c42f169caba89a7d512b5418b09864543eeb4d497416c917d7137863bd2076ad"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "env_logger"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "error-chain"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9435d864e017c3c6afeac1654189b06cdb491cf2ff73dbf0d73b0f292f42ff8"
[[package]]
name = "failure"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
dependencies = [
"backtrace",
"failure_derive",
]
[[package]]
name = "failure_derive"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
dependencies = [
"proc-macro2",
"quote",
"syn",
"synstructure",
]
[[package]]
name = "gimli"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
dependencies = [
"quick-error",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.134"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb"
[[package]]
name = "libloading"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
dependencies = [
"cc",
"winapi",
]
[[package]]
name = "log"
version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "metadeps"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b122901b3a675fac8cecf68dcb2f0d3036193bc861d1ac0e1c337f7d5254c2"
dependencies = [
"error-chain",
"pkg-config",
"toml",
]
[[package]]
name = "miniz_oxide"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
dependencies = [
"adler",
]
[[package]]
name = "mira_sharer"
version = "0.1.0"
dependencies = [
"clap 4.0.14",
"failure",
"windows",
"x264-sys",
]
[[package]]
name = "nom"
version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
dependencies = [
"memchr",
"version_check 0.1.5",
]
[[package]]
name = "object"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
[[package]]
name = "os_str_bytes"
version = "6.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "pkg-config"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check 0.9.4",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check 0.9.4",
]
[[package]]
name = "proc-macro2"
version = "1.0.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quick-error"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "shlex"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "synstructure"
version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2",
"quote",
"syn",
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "toml"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
[[package]]
name = "unicode-ident"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "unicode-width"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "which"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
dependencies = [
"libc",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0286ba339aa753e70765d521bb0242cc48e1194562bfa2a2ad7ac8a6de28f5d5"
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.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
[[package]]
name = "x264-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ed8f9c5101e193216a32330eb68fea45ac2b9fb2e7327bf61896b9262b373ec"
dependencies = [
"bindgen",
"metadeps",
]
+39
View File
@@ -0,0 +1,39 @@
[package]
name = "mira_sharer"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[profile.release]
debug = true
[dependencies]
x264-sys = "0.2.0"
failure = "0.1.8"
clap = { version = "4.0.14", features = ["derive"] }
[dependencies.windows]
version = "0.42.0"
features = [
"Data_Xml_Dom",
"Foundation",
"Win32_Foundation",
"Win32_Security",
"Win32_System_Threading",
"Win32_UI_WindowsAndMessaging",
"Win32_Graphics_Gdi",
"Win32_System_WinRT",
"Win32_System_WinRT_Graphics_Capture",
"Win32_Graphics_Direct3D",
"Win32_Graphics_Direct3D11",
"Win32_Graphics_Dwm",
"Win32_Graphics_Gdi",
"Win32_Graphics_Dxgi",
"Win32_Graphics_Dxgi_Common",
"Graphics",
"Graphics_Capture",
"Graphics_DirectX",
"Graphics_DirectX_Direct3D11",
"Graphics_Imaging",
"Win32_System_WinRT_Direct3D11",
]
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RUST_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
+9
View File
@@ -0,0 +1,9 @@
use crate::{Encoder, OutputSink, Result};
pub trait ScreenCapture {
fn capture(&mut self, encoder: &mut dyn Encoder, output: &mut dyn OutputSink) -> Result<()>;
}
mod wgc_capture;
pub use wgc_capture::WGCScreenCapture;
+99
View File
@@ -0,0 +1,99 @@
use std::slice;
use std::sync::mpsc::channel;
use windows::core::{IInspectable, Interface};
use windows::Foundation::TypedEventHandler;
use windows::Graphics::Capture::{Direct3D11CaptureFramePool, GraphicsCaptureItem};
use windows::Graphics::DirectX::Direct3D11::IDirect3DSurface;
use windows::Graphics::DirectX::DirectXPixelFormat;
use windows::Win32::Graphics::Direct3D11::{D3D11_BIND_FLAG, D3D11_CPU_ACCESS_READ, D3D11_MAP_READ, D3D11_RESOURCE_MISC_FLAG, D3D11_TEXTURE2D_DESC, D3D11_USAGE_STAGING, ID3D11Device, ID3D11DeviceContext, ID3D11Resource, ID3D11Texture2D};
use crate::result::Result;
use crate::{d3d, OutputSink};
use crate::encoder::Encoder;
use super::ScreenCapture;
pub struct WGCScreenCapture<'a> {
item: &'a GraphicsCaptureItem,
device: ID3D11Device,
d3d_context: ID3D11DeviceContext,
frame_pool: Direct3D11CaptureFramePool,
}
impl<'a> WGCScreenCapture<'a> {
unsafe fn surface_to_texture(&mut self, surface: &IDirect3DSurface) -> Result<ID3D11Texture2D> {
let source_texture: ID3D11Texture2D = d3d::get_d3d_interface_from_object(surface)?;
let mut desc = D3D11_TEXTURE2D_DESC::default();
source_texture.GetDesc(&mut desc);
desc.BindFlags = D3D11_BIND_FLAG(0);
desc.MiscFlags = D3D11_RESOURCE_MISC_FLAG(0);
desc.Usage = D3D11_USAGE_STAGING;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
let copy_texture = self.device.CreateTexture2D(&desc, None)?;
let src: ID3D11Resource = source_texture.cast()?;
let dst: ID3D11Resource = copy_texture.cast()?;
self.d3d_context.CopyResource(&dst, &src);
Ok(copy_texture)
}
pub fn new(item: &'a GraphicsCaptureItem) -> Result<Self> {
let item_size = item.Size()?;
let (device, d3d_device, d3d_context) = d3d::create_direct3d_devices_and_context()?;
let frame_pool = Direct3D11CaptureFramePool::CreateFreeThreaded(
&d3d_device,
DirectXPixelFormat::B8G8R8A8UIntNormalized,
1,
item_size,
)?;
Ok(Self {
item,
device,
d3d_context,
frame_pool,
})
}
}
impl ScreenCapture for WGCScreenCapture<'_> {
fn capture(&mut self, encoder: &mut dyn Encoder, output: &mut dyn OutputSink) -> Result<()> {
let session = self.frame_pool.CreateCaptureSession(self.item)?;
let (sender, receiver) = channel();
self.frame_pool.FrameArrived(
&TypedEventHandler::<Direct3D11CaptureFramePool, IInspectable>::new({
move |frame_pool, _| {
let frame_pool = frame_pool.as_ref().unwrap();
let frame = frame_pool.TryGetNextFrame()?;
sender.send(frame).unwrap();
Ok(())
}
}),
)?;
session.StartCapture()?;
let height = self.item.Size()?.Height as u32;
while let Ok(frame) = receiver.recv() {
unsafe {
let texture = self.surface_to_texture(&frame.Surface()?)?;
let resource: ID3D11Resource = texture.cast()?;
let mapped = self.d3d_context.Map(&resource, 0, D3D11_MAP_READ, 0)?;
let frame: &[u8] = slice::from_raw_parts(
mapped.pData as *const _,
(height * mapped.RowPitch) as usize,
);
let encoded = encoder.encode(frame).unwrap();
output.write(encoded).unwrap();
self.d3d_context.Unmap(&resource, 0);
};
}
session.Close()?;
Ok(())
}
}
impl Drop for WGCScreenCapture<'_> {
fn drop(&mut self) {
self.frame_pool.Close().unwrap();
}
}
+73
View File
@@ -0,0 +1,73 @@
use windows::core::{Abi, Interface, Result};
use windows::Graphics::DirectX::Direct3D11::IDirect3DDevice;
use windows::Win32::Graphics::{
Direct3D::{D3D_DRIVER_TYPE, D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP},
Direct3D11::{
D3D11CreateDevice, ID3D11Device, D3D11_CREATE_DEVICE_BGRA_SUPPORT,
D3D11_CREATE_DEVICE_FLAG, D3D11_SDK_VERSION,
},
Dxgi::{IDXGIDevice, DXGI_ERROR_UNSUPPORTED},
};
use windows::Win32::Graphics::Direct3D11::ID3D11DeviceContext;
use windows::Win32::System::WinRT::Direct3D11::{
CreateDirect3D11DeviceFromDXGIDevice, IDirect3DDxgiInterfaceAccess,
};
fn create_d3d_device_with_type(
driver_type: D3D_DRIVER_TYPE,
flags: D3D11_CREATE_DEVICE_FLAG,
device: *mut Option<ID3D11Device>,
) -> Result<()> {
unsafe {
D3D11CreateDevice(
None,
driver_type,
None,
flags,
None,
D3D11_SDK_VERSION as u32,
Some(device),
None,
None,
)
}
}
fn create_d3d_device() -> Result<ID3D11Device> {
let mut device = None;
let mut result = create_d3d_device_with_type(
D3D_DRIVER_TYPE_HARDWARE,
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
&mut device,
);
if let Err(error) = &result {
if error.code() == DXGI_ERROR_UNSUPPORTED {
result = create_d3d_device_with_type(
D3D_DRIVER_TYPE_WARP,
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
&mut device,
);
}
}
result?;
Ok(device.unwrap())
}
pub fn create_direct3d_devices_and_context() -> Result<(ID3D11Device, IDirect3DDevice, ID3D11DeviceContext)> {
let d3d_device = create_d3d_device()?;
let d3d_context = unsafe {
let mut d3d_context = None;
d3d_device.GetImmediateContext(&mut d3d_context);
d3d_context.unwrap()
};
let dxgi_device: IDXGIDevice = d3d_device.cast()?;
let inspectable = unsafe { CreateDirect3D11DeviceFromDXGIDevice(&dxgi_device)? };
let id3d_device: IDirect3DDevice = inspectable.cast()?;
Ok((d3d_device, id3d_device, d3d_context))
}
pub fn get_d3d_interface_from_object<S: Interface, R: Interface + Abi>(object: &S) -> Result<R> {
let access: IDirect3DDxgiInterfaceAccess = object.cast()?;
let object = unsafe { access.GetInterface::<R>()? };
Ok(object)
}
+65
View File
@@ -0,0 +1,65 @@
use windows::Graphics::Capture::GraphicsCaptureItem;
use windows::Win32::Foundation::{BOOL, LPARAM, RECT};
use windows::Win32::Graphics::Gdi::{
EnumDisplayMonitors, GetMonitorInfoW, HDC, HMONITOR, MONITORINFOEXW,
};
use windows::Win32::System::WinRT::Graphics::Capture::IGraphicsCaptureItemInterop;
use crate::result::Result;
#[derive(Clone)]
pub struct DisplayInfo {
pub handle: HMONITOR,
pub display_name: String,
pub resolution: (u32, u32),
}
impl DisplayInfo {
pub fn displays() -> Result<Vec<Self>> {
unsafe {
let displays = Box::into_raw(Box::new(Vec::<DisplayInfo>::new()));
EnumDisplayMonitors(
HDC(0),
None,
Some(enum_monitor),
LPARAM(displays as isize),
);
Ok(*Box::from_raw(displays))
}
}
pub fn new(monitor_handle: HMONITOR) -> Result<Self> {
let mut info = MONITORINFOEXW::default();
info.monitorInfo.cbSize = std::mem::size_of::<MONITORINFOEXW>() as u32;
unsafe {
GetMonitorInfoW(monitor_handle, &mut info as *mut _ as *mut _).ok()?;
}
let display_name = String::from_utf16_lossy(&info.szDevice)
.trim_matches(char::from(0))
.to_string();
Ok(Self {
handle: monitor_handle,
display_name,
resolution: ((info.monitorInfo.rcMonitor.right - info.monitorInfo.rcMonitor.left) as u32,
(info.monitorInfo.rcMonitor.bottom - info.monitorInfo.rcMonitor.top) as u32),
})
}
pub fn create_capture_item_for_monitor(&self) -> Result<GraphicsCaptureItem> {
let interop = windows::core::factory::<GraphicsCaptureItem, IGraphicsCaptureItemInterop>()?;
Ok(unsafe { interop.CreateForMonitor(self.handle) }?)
}
}
// callback function for EnumDisplayMonitors
extern "system" fn enum_monitor(monitor: HMONITOR, _: HDC, _: *mut RECT, state: LPARAM) -> BOOL {
unsafe {
// get the vector from the param, use leak because this function is not responsible for its lifetime
let state = Box::leak(Box::from_raw(state.0 as *mut Vec<DisplayInfo>));
state.push(DisplayInfo::new(monitor).unwrap());
}
true.into()
}
+86
View File
@@ -0,0 +1,86 @@
use std::{mem, slice};
use std::ptr::null_mut;
use crate::result::Result;
use x264_sys::{
X264_CSP_BGRA, x264_encoder_close, x264_encoder_encode, x264_encoder_open, x264_picture_clean,
x264_param_default_preset, x264_picture_alloc, x264_t, x264_nal_t, x264_picture_t
};
pub trait Encoder {
fn encode(&mut self, input: &[u8]) -> Result<&[u8]>;
}
pub struct X264Encoder {
encoder: *mut x264_t,
pic_in: x264_picture_t,
pic_out: mem::MaybeUninit<x264_picture_t>,
nal: *const x264_nal_t,
nal_size: i32,
}
impl X264Encoder {
pub fn new(w: u32, h: u32) -> Self {
let mut par = unsafe {
let mut par = mem::MaybeUninit::uninit();
x264_param_default_preset(
par.as_mut_ptr(),
b"ultrafast\0".as_ptr() as *const i8,
b"zerolatency\0".as_ptr() as *const i8,
);
let mut par = par.assume_init();
par.i_width = w as i32;
par.i_height = h as i32;
par.i_fps_num = 60;
par.i_threads = 4;
par.b_annexb = true as i32;
par.i_csp = X264_CSP_BGRA as i32;
par
};
let pic_in = unsafe {
let mut pic_in = mem::MaybeUninit::<x264_picture_t>::uninit();
x264_picture_alloc(pic_in.as_mut_ptr(), par.i_csp, par.i_width, par.i_height);
pic_in.assume_init()
};
Self {
encoder: unsafe { x264_encoder_open(&mut par) },
pic_in,
pic_out: mem::MaybeUninit::<x264_picture_t>::uninit(),
nal: null_mut(),
nal_size: 0,
}
}
}
impl Encoder for X264Encoder {
fn encode(&mut self, input: &[u8]) -> Result<&[u8]> {
self.pic_in.img.plane = [
input.as_ptr() as *mut u8,
null_mut(),
null_mut(),
null_mut(),
];
//pic_in.i_pts = ((frame_ms - start_relative_time.unwrap()) as f64 / (1.0 / 60.0 * 1000.0)).round() as i64;
let frame_size = unsafe {
x264_encoder_encode(
self.encoder,
&mut self.nal as *mut _ as *mut _,
&mut self.nal_size,
&mut self.pic_in,
self.pic_out.as_mut_ptr()
)
};
return Ok(unsafe { slice::from_raw_parts((*self.nal).p_payload, frame_size as usize) });
}
}
impl Drop for X264Encoder {
fn drop(&mut self) {
unsafe {
x264_picture_clean(&mut self.pic_in);
x264_encoder_close(self.encoder);
}
}
}
+43
View File
@@ -0,0 +1,43 @@
use crate::display::DisplayInfo;
use crate::result::Result;
use crate::capture::ScreenCapture;
use crate::output::OutputSink;
use crate::encoder::Encoder;
use clap::Parser;
mod d3d;
mod display;
mod result;
mod capture;
mod encoder;
mod output;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
/// Display index
#[arg(short, long, default_value = "0")]
display: usize,
}
fn main() -> Result<()> {
let args = Args::parse();
let displays = DisplayInfo::displays()?;
for (i, display) in displays.iter().enumerate() {
println!(
"display: {} {}x{} {}",
display.display_name,
display.resolution.0,
display.resolution.1,
if i==args.display { "(selected)" } else { "" },
);
}
let display = displays.iter().nth(args.display).unwrap();
let item = display.create_capture_item_for_monitor()?;
let mut capture = capture::WGCScreenCapture::new(&item)?;
let mut encoder = encoder::X264Encoder::new(display.resolution.0, display.resolution.1);
let mut output = output::FileOutput::new("output.h264");
capture.capture(&mut encoder, &mut output)?;
Ok(())
}
+32
View File
@@ -0,0 +1,32 @@
use std::fs::File;
use std::io::Write;
use crate::Result;
pub trait OutputSink {
fn write(&mut self, input: &[u8]) -> Result<()>;
}
pub struct FileOutput {
file: File,
}
impl FileOutput {
pub fn new(path: &str) -> Self {
Self {
file: File::create(path).unwrap(),
}
}
}
impl OutputSink for FileOutput {
fn write(&mut self, input: &[u8]) -> Result<()> {
self.file.write_all(input)?;
Ok(())
}
}
impl Drop for FileOutput {
fn drop(&mut self) {
self.file.flush().unwrap();
}
}
+3
View File
@@ -0,0 +1,3 @@
use failure::Error;
pub type Result<T> = std::result::Result<T, Error>;